[libjogl2-java] 42/58: Imported Upstream version 2.0-rc12

Tony Mancill tmancill at moszumanska.debian.org
Thu Sep 4 03:59:20 UTC 2014


This is an automated email from the git hooks/post-receive script.

tmancill pushed a commit to branch master
in repository libjogl2-java.

commit bfc77eafe11022baffb744e7a9535b6fdd9ca44c
Author: tony mancill <tmancill at debian.org>
Date:   Fri Aug 29 18:45:36 2014 -0700

    Imported Upstream version 2.0-rc12
---
 .classpath                                         |    1 +
 LICENSE.txt                                        |    6 +-
 README.txt                                         |    4 +-
 doc/HowToBuild.html                                |    2 +-
 etc/profile.jogl                                   |   30 +-
 etc/test_dbg.sh                                    |    2 +-
 .../jogl-applet-runner-newt-gears-gl3-napplet.html |    2 +-
 ...gl-applet-runner-newt-gears-normal-napplet.html |    2 +-
 ...l-applet-runner-newt-gears-normal-napplet2.html |    2 +-
 make/build-common.xml                              |   48 +-
 make/build-jogl.xml                                |  118 +-
 make/build-nativewindow.xml                        |   32 +-
 make/build-newt.xml                                |   39 +-
 make/build-test.xml                                |  187 ++-
 make/build.xml                                     |   37 +-
 make/config/jogl/cg-common-CustomJavaCode.java     |    6 +-
 make/config/jogl/cg-common.cfg                     |    2 +
 make/config/jogl/cgl-macosx-CustomJavaCode.java    |   35 +
 make/config/jogl/cgl-macosx.cfg                    |   11 +
 make/config/jogl/gl-common.cfg                     |    1 +
 .../config/jogl/gl-impl-CustomJavaCode-common.java |    5 +
 make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java |  138 +-
 make/config/jogl/gl-impl-CustomJavaCode-gles1.java |   59 +-
 make/config/jogl/gl-impl-CustomJavaCode-gles2.java |   59 +-
 make/config/jogl/glu-CustomJavaCode-base.java      |   14 +-
 make/config/jogl/glu-common.cfg                    |    1 +
 make/config/jogl/glu-gl2.cfg                       |    3 +-
 make/config/jogl/glx-CustomJavaCode.java           |   14 +-
 make/config/nativewindow/x11-CustomJavaCode.java   |    5 +-
 make/joglversion                                   |    3 +
 make/{joglversion => joglversion-all}              |    3 +
 make/joglversion-test                              |    3 +-
 make/joglversion-test-android                      |    3 +-
 make/nativewindowversion                           |    3 +
 make/newtversion                                   |    3 +
 make/resources/android/AndroidManifest-test.xml    |   40 +-
 make/resources/android/res-test/values/strings.xml |    4 +
 make/scripts/adb-launch-junit.sh                   |   82 ++
 make/scripts/adb-launch-main.sh                    |   70 +-
 make/scripts/check-junit.sh                        |    1 +
 make/scripts/java-win.bat                          |    4 +
 make/scripts/java-win32.bat                        |   25 -
 make/scripts/java-win64.bat                        |   19 -
 make/scripts/lstjars.sh                            |    7 +-
 make/scripts/make.jogl.all.android-armv6-cross.sh  |   44 +-
 make/scripts/make.jogl.all.android-armv7-cross.sh  |   44 +-
 make/scripts/make.jogl.all.linux-armv6-cross.sh    |   11 +-
 make/scripts/make.jogl.all.linux-armv6.sh          |    5 +-
 make/scripts/make.jogl.all.linux-armv6hf-cross.sh  |    9 +-
 make/scripts/make.jogl.all.linux-armv6hf.sh        |    5 +-
 make/scripts/make.jogl.all.linux-x86.sh            |    8 +
 ...6_64.sh => make.jogl.all.linux-x86_64.java7.sh} |   17 +-
 make/scripts/make.jogl.all.linux-x86_64.sh         |   18 +-
 make/scripts/make.jogl.all.macosx-java7.sh         |   22 +
 make/scripts/make.jogl.all.macosx.sh               |   16 +-
 make/scripts/make.jogl.all.sh                      |    9 +
 make/scripts/make.jogl.all.solaris-x86.sh          |    7 +
 make/scripts/make.jogl.all.solaris-x86_64.sh       |    7 +
 make/scripts/make.jogl.all.win32.bat               |   11 +-
 make/scripts/make.jogl.all.win64.bat               |   15 +-
 make/scripts/setenv-jogl.sh                        |   74 +-
 make/scripts/tests-javaws-x64.bat                  |    2 +-
 make/scripts/tests-linux-x64-junit-swt.sh          |    7 +
 make/scripts/tests-macosx64-junit-java7.sh         |    8 +
 make/scripts/tests-macosx64-junit-swt.sh           |    7 +
 .../{tests-osx-x64.sh => tests-osx-x64-custom.sh}  |    2 +-
 .../{tests-osx-x64.sh => tests-osx-x64-java6.sh}   |    5 +-
 make/scripts/tests-osx-x64.sh                      |    7 +-
 make/scripts/tests-win.bat                         |  163 +++
 make/scripts/tests-win64-junit-swt.bat             |    7 +
 .../{java-win32-dbg.bat => tests-x32-dbg.bat}      |   11 +-
 make/scripts/tests-x32.bat                         |  131 +-
 make/scripts/tests-x32.sh                          |    2 +
 make/scripts/tests-x64-custom.sh                   |   12 +
 .../{java-win64-dbg.bat => tests-x64-dbg.bat}      |   19 +-
 make/scripts/tests-x64.bat                         |  146 +-
 make/scripts/tests.sh                              |  383 +++--
 make/stub_includes/jni/macosx/jawt_md.h            |   48 +-
 make/stub_includes/opengl/GL/glext.h               |    2 +
 make/stub_includes/opengl/GL3/gl3.h                |    2 +
 make/stub_includes/opengl/macosx-window-system.h   |    3 +
 make/stub_includes/win32/WindowsDWM.h              |    5 +-
 make/versions.xml                                  |   47 -
 .../com/jogamp/gluegen/opengl/GLConfiguration.java |    0
 .../com/jogamp/gluegen/opengl/GLEmitter.java       |   83 +-
 .../gluegen/opengl/GLJavaMethodBindingEmitter.java |    0
 .../opengl/nativesig/NativeSignatureEmitter.java   |    0
 .../NativeSignatureJavaMethodBindingEmitter.java   |    0
 .../com/jogamp/graph/curve/OutlineShape.java       |    4 +-
 .../classes/com/jogamp/graph/curve/Region.java     |    2 +-
 .../com/jogamp/graph/curve/opengl/GLRegion.java    |    0
 .../com/jogamp/graph/curve/opengl/Renderer.java    |   43 +-
 src/jogl/classes/com/jogamp/graph/font/Font.java   |    2 +-
 .../classes/com/jogamp/graph/font/FontFactory.java |   16 +-
 .../classes/com/jogamp/graph/geom/Outline.java     |    3 +-
 src/jogl/classes/com/jogamp/graph/geom/Vertex.java |   12 +-
 .../com/jogamp/graph/geom/opengl/SVertex.java      |    8 +-
 .../classes/com/jogamp/graph/math/Quaternion.java  |  382 -----
 src/jogl/classes/com/jogamp/opengl/FBObject.java   |  196 +--
 .../com/jogamp/opengl/GLAutoDrawableDelegate.java  |   25 +-
 .../com/jogamp/opengl/GLEventListenerState.java    |  435 ++++++
 .../classes/com/jogamp/opengl/GLExtensions.java    |    5 +-
 .../com/jogamp/opengl/GLRendererQuirks.java        |  144 +-
 .../classes/com/jogamp/opengl/GLStateKeeper.java   |  100 ++
 .../classes/com/jogamp/opengl/JoglVersion.java     |   41 +-
 .../opengl/cg/CgDynamicLibraryBundleInfo.java      |   21 +-
 .../jogamp/opengl/{util => math}/FixedPoint.java   |    2 +-
 .../com/jogamp/opengl/{ => math}/FloatUtil.java    |  165 ++-
 .../classes/com/jogamp/opengl/math/Quaternion.java |  426 ++++++
 .../jogamp/{graph => opengl}/math/VectorUtil.java  |  130 +-
 .../com/jogamp/opengl/math/Vert2fImmutable.java}   |   23 +-
 .../com/jogamp/opengl/math/Vert3fImmutable.java}   |   20 +-
 .../jogamp/{graph => opengl/math}/geom/AABBox.java |   70 +-
 .../com/jogamp/opengl/math/geom/Frustum.java       |  388 +++++
 .../classes/com/jogamp/opengl/swt/GLCanvas.java    |  531 +++++--
 .../com/jogamp/opengl/util/AWTAnimatorImpl.java    |    2 +-
 .../classes/com/jogamp/opengl/util/Animator.java   |  205 ++-
 .../com/jogamp/opengl/util/AnimatorBase.java       |  468 +++++-
 .../jogamp/opengl/util/DefaultAnimatorImpl.java    |    2 +-
 .../com/jogamp/opengl/util/FPSAnimator.java        |  318 ++--
 .../com/jogamp/opengl/util/GLArrayDataClient.java  |   55 +-
 .../com/jogamp/opengl/util/GLArrayDataServer.java  |   29 +
 .../com/jogamp/opengl/util/GLArrayDataWrapper.java |   84 +-
 .../classes/com/jogamp/opengl/util/GLBuffers.java  |  232 ++-
 .../com/jogamp/opengl/util/GLDrawableUtil.java     |  167 +++
 .../com/jogamp/opengl/util/GLPixelBuffer.java      |  269 ++++
 .../jogamp/opengl/util/GLPixelStorageModes.java    |   34 +-
 .../com/jogamp/opengl/util/GLReadBufferUtil.java   |  165 ++-
 .../com/jogamp/opengl/util/ImmModeSink.java        |  281 +++-
 .../classes/com/jogamp/opengl/util/PMVMatrix.java  |  204 ++-
 .../jogamp/opengl/util/awt/AWTGLPixelBuffer.java   |  228 +++
 .../opengl/util/awt/AWTGLReadBufferUtil.java       |   76 +
 .../com/jogamp/opengl/util/awt/Screenshot.java     |   38 +-
 .../com/jogamp/opengl/util/glsl/ShaderCode.java    |  175 ++-
 .../com/jogamp/opengl/util/glsl/ShaderProgram.java |    4 +-
 .../com/jogamp/opengl/util/glsl/ShaderState.java   |  208 +--
 .../com/jogamp/opengl/util/glsl/ShaderUtil.java    |   18 +-
 .../com/jogamp/opengl/util/texture/Texture.java    |    1 +
 .../jogamp/opengl/util/texture/TextureCoords.java  |    1 +
 .../jogamp/opengl/util/texture/TextureData.java    |  174 ++-
 .../com/jogamp/opengl/util/texture/TextureIO.java  |   59 +-
 .../opengl/util/texture/awt/AWTTextureData.java    |  148 +-
 .../jogamp/opengl/util/texture/spi/JPEGImage.java  |  175 +++
 .../jogamp/opengl/util/texture/spi/PNGImage.java   |  230 ++-
 .../javax/media/opengl/GLAnimatorControl.java      |   64 +-
 .../classes/javax/media/opengl/GLArrayData.java    |   57 +-
 .../classes/javax/media/opengl/GLAutoDrawable.java |  261 +++-
 src/jogl/classes/javax/media/opengl/GLBase.java    |   15 +-
 .../classes/javax/media/opengl/GLCapabilities.java |   63 +-
 .../media/opengl/GLCapabilitiesImmutable.java      |   27 -
 src/jogl/classes/javax/media/opengl/GLContext.java |  272 ++--
 .../classes/javax/media/opengl/GLDrawable.java     |   91 +-
 .../javax/media/opengl/GLDrawableFactory.java      |  104 +-
 .../classes/javax/media/opengl/GLFBODrawable.java  |   22 +-
 src/jogl/classes/javax/media/opengl/GLPbuffer.java |   34 -
 src/jogl/classes/javax/media/opengl/GLProfile.java |   39 +-
 .../classes/javax/media/opengl/GLUniformData.java  |   22 +-
 .../classes/javax/media/opengl/awt/GLCanvas.java   |  480 +++---
 .../classes/javax/media/opengl/awt/GLJPanel.java   | 1151 ++++++++-------
 .../jogamp/graph/curve/opengl/RegionFactory.java   |    0
 .../graph/curve/opengl/RegionRendererImpl01.java   |   29 +-
 .../graph/curve/opengl/TextRendererImpl01.java     |   20 +-
 ...r02a-xxx.fp => curverenderer01-1pass-weight.fp} |    9 +-
 ...renderer01a-xxx.fp => curverenderer01-1pass.fp} |    9 +-
 ...r02b-xxx.fp => curverenderer01-2pass-weight.fp} |   16 +-
 ...renderer01b-xxx.fp => curverenderer01-2pass.fp} |   16 +-
 .../opengl/shader/curverenderer01-es2-merged.vp    |   19 -
 .../curve/opengl/shader/curverenderer01-es2.vp     |    9 -
 .../curve/opengl/shader/curverenderer01-gl2.vp     |    6 -
 .../{curverenderer01-xxx.vp => curverenderer01.vp} |    5 +
 .../opengl/shader/curverenderer01a-es2-merged.fp   |   52 -
 .../curve/opengl/shader/curverenderer01a-es2.fp    |   13 -
 .../curve/opengl/shader/curverenderer01a-gl2.fp    |    6 -
 .../curve/opengl/shader/curverenderer01b-es2.fp    |   14 -
 .../curve/opengl/shader/curverenderer01b-gl2.fp    |    6 -
 .../curve/opengl/shader/curverenderer02a-es2.fp    |   14 -
 .../curve/opengl/shader/curverenderer02a-gl2.fp    |    6 -
 .../curve/opengl/shader/curverenderer02b-es2.fp    |   14 -
 .../curve/opengl/shader/curverenderer02b-gl2.fp    |    6 -
 .../jogamp/graph/curve/tess/CDTriangulator2D.java  |    2 +-
 src/jogl/classes/jogamp/graph/curve/tess/Loop.java |    6 +-
 .../jogamp/graph/curve/text/GlyphShape.java        |    2 +-
 .../jogamp/graph/curve/text/GlyphString.java       |    2 +-
 .../jogamp/graph/font/typecast/TypecastFont.java   |    2 +-
 .../font/typecast/TypecastFontConstructor.java     |    2 +-
 .../jogamp/graph/font/typecast/TypecastGlyph.java  |    2 +-
 .../graph/font/typecast/TypecastHMetrics.java      |    2 +-
 .../jogamp/graph/font/typecast/ot/OTGlyph.java     |    2 +-
 .../jogamp/graph/geom/plane/AffineTransform.java   |   16 +-
 .../graph/{math => geom}/plane/Crossing.java       |   23 +-
 .../classes/jogamp/graph/geom/plane/Path2D.java    |    3 +-
 src/jogl/classes/jogamp/graph/math/MathFloat.java  |   45 -
 src/jogl/classes/jogamp/opengl/Debug.java          |   25 +-
 .../opengl/DesktopGLDynamicLibraryBundleInfo.java  |    4 +-
 .../opengl/DesktopGLDynamicLookupHelper.java       |    4 +-
 .../jogamp/opengl/ExtensionAvailabilityCache.java  |   11 +-
 src/jogl/classes/jogamp/opengl/FPSCounterImpl.java |    1 +
 .../classes/jogamp/opengl/GLAutoDrawableBase.java  |  252 +++-
 .../jogamp/opengl/GLBufferStateTracker.java        |    2 +
 src/jogl/classes/jogamp/opengl/GLContextImpl.java  | 1007 +++++++++----
 .../jogamp/opengl/GLDebugMessageHandler.java       |   24 +-
 .../jogamp/opengl/GLDrawableFactoryImpl.java       |  139 +-
 .../classes/jogamp/opengl/GLDrawableHelper.java    |  881 +++++++----
 src/jogl/classes/jogamp/opengl/GLDrawableImpl.java |  177 ++-
 .../jogamp/opengl/GLDynamicLibraryBundleInfo.java  |   25 +-
 .../jogamp/opengl/GLDynamicLookupHelper.java       |    2 +-
 .../classes/jogamp/opengl/GLFBODrawableImpl.java   |  119 +-
 .../jogamp/opengl/GLGraphicsConfigurationUtil.java |   55 +-
 .../jogamp/opengl/GLOffscreenAutoDrawableImpl.java |   24 +-
 src/jogl/classes/jogamp/opengl/GLPbufferImpl.java  |   47 +-
 .../classes/jogamp/opengl/GLVersionNumber.java     |  157 +-
 src/jogl/classes/jogamp/opengl/GLWorkerThread.java |    4 +-
 src/jogl/classes/jogamp/opengl/MemoryObject.java   |   50 +-
 src/jogl/classes/jogamp/opengl/ProjectFloat.java   |    2 +-
 .../jogamp/opengl/SharedResourceRunner.java        |   46 +-
 .../jogamp/opengl/awt/AWTThreadingPlugin.java      |    9 +-
 src/jogl/classes/jogamp/opengl/awt/Java2D.java     |  254 ++--
 .../classes/jogamp/opengl/awt/Java2DGLContext.java |   52 -
 .../egl/DesktopES2DynamicLibraryBundleInfo.java    |   16 +-
 src/jogl/classes/jogamp/opengl/egl/EGLContext.java |   40 +-
 .../classes/jogamp/opengl/egl/EGLDisplayUtil.java  |   76 +-
 .../classes/jogamp/opengl/egl/EGLDrawable.java     |    4 +-
 .../jogamp/opengl/egl/EGLDrawableFactory.java      |  124 +-
 .../opengl/egl/EGLDynamicLibraryBundleInfo.java    |   20 +-
 .../opengl/egl/EGLES1DynamicLibraryBundleInfo.java |    4 +-
 .../opengl/egl/EGLES2DynamicLibraryBundleInfo.java |    4 +-
 .../jogamp/opengl/egl/EGLExternalContext.java      |   27 +-
 .../opengl/egl/EGLGraphicsConfiguration.java       |   11 +-
 .../egl/EGLGraphicsConfigurationFactory.java       |   14 +-
 .../jogamp/opengl/egl/EGLOnscreenContext.java      |   45 -
 .../jogamp/opengl/egl/EGLOnscreenDrawable.java     |    2 +-
 .../jogamp/opengl/egl/EGLPbufferContext.java       |   50 -
 .../jogamp/opengl/egl/EGLPbufferDrawable.java      |    3 +-
 .../jogamp/opengl/egl/EGLUpstreamSurfaceHook.java  |   60 +-
 .../jogamp/opengl/egl/EGLWrappedSurface.java       |    8 +
 .../classes/jogamp/opengl/glu/GLUquadricImpl.java  |   42 +-
 .../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java |  655 ++++++---
 .../opengl/macosx/cgl/MacOSXCGLDrawable.java       |   11 +-
 .../macosx/cgl/MacOSXCGLDrawableFactory.java       |  101 +-
 .../cgl/MacOSXCGLDynamicLibraryBundleInfo.java     |    4 +-
 .../macosx/cgl/MacOSXCGLGraphicsConfiguration.java |   10 +-
 .../macosx/cgl/MacOSXExternalCGLContext.java       |   22 +-
 .../macosx/cgl/MacOSXOffscreenCGLContext.java      |   66 -
 .../macosx/cgl/MacOSXOffscreenCGLDrawable.java     |    2 +-
 .../macosx/cgl/MacOSXOnscreenCGLContext.java       |  115 --
 .../macosx/cgl/MacOSXOnscreenCGLDrawable.java      |    2 +-
 .../opengl/macosx/cgl/MacOSXPbufferCGLContext.java |   95 --
 .../macosx/cgl/MacOSXPbufferCGLDrawable.java       |   34 +-
 .../cgl/awt/MacOSXAWTCGLDrawableFactory.java       |   60 -
 .../macosx/cgl/awt/MacOSXJava2DCGLContext.java     |  121 --
 .../jogamp/opengl/openal/av/ALDummyUsage.java      |   19 +
 .../classes/jogamp/opengl/util/GLArrayHandler.java |    6 +-
 .../av/impl/FFMPEGDynamicLibraryBundleInfo.java    |   45 +-
 .../opengl/util/av/impl/FFMPEGMediaPlayer.java     |   37 +-
 .../jogamp/opengl/util/glsl/GLSLArrayHandler.java  |   66 +-
 .../opengl/util/glsl/GLSLArrayHandlerFlat.java     |   31 +-
 .../util/glsl/GLSLArrayHandlerInterleaved.java     |    2 +-
 .../jogamp/opengl/util/glsl/GLSLTextureRaster.java |  195 +++
 .../util/glsl/fixedfunc/FixedFuncPipeline.java     |    4 +-
 .../jogamp/opengl/util/jpeg/JPEGDecoder.java       | 1542 ++++++++++++++++++++
 .../jogamp/opengl/util/pngj/FilterType.java        |   49 +-
 .../opengl/util/pngj/FilterWriteStrategy.java      |    4 +-
 .../classes/jogamp/opengl/util/pngj/ImageInfo.java |   38 +-
 .../classes/jogamp/opengl/util/pngj/ImageLine.java |  355 +++--
 .../jogamp/opengl/util/pngj/ImageLineHelper.java   |  318 ++++
 .../jogamp/opengl/util/pngj/ImageLines.java        |  101 ++
 .../jogamp/opengl/util/pngj/PngDeinterlacer.java   |  277 ++++
 .../{PngHelper.java => PngHelperInternal.java}     |  139 +-
 .../opengl/util/pngj/PngIDatChunkInputStream.java  |   63 +-
 .../opengl/util/pngj/PngIDatChunkOutputStream.java |   10 +-
 .../classes/jogamp/opengl/util/pngj/PngReader.java |  959 +++++++++---
 .../classes/jogamp/opengl/util/pngj/PngWriter.java |  677 ++++++---
 .../opengl/util/pngj/PngjExceptionInternal.java    |   23 +
 .../opengl/util/pngj/ProgressiveOutputStream.java  |    8 +-
 .../util/pngj/chunks/ChunkCopyBehaviour.java       |    3 +-
 .../opengl/util/pngj/chunks/ChunkHelper.java       |  151 +-
 .../jogamp/opengl/util/pngj/chunks/ChunkList.java  |  282 ----
 .../util/pngj/chunks/ChunkLoadBehaviour.java       |   27 +-
 .../opengl/util/pngj/chunks/ChunkPredicate.java    |   14 +
 .../jogamp/opengl/util/pngj/chunks/ChunkRaw.java   |   97 +-
 .../jogamp/opengl/util/pngj/chunks/ChunksList.java |  174 +++
 .../util/pngj/chunks/ChunksListForWrite.java       |  171 +++
 .../jogamp/opengl/util/pngj/chunks/PngChunk.java   |  239 ++-
 .../opengl/util/pngj/chunks/PngChunkBKGD.java      |   44 +-
 .../opengl/util/pngj/chunks/PngChunkCHRM.java      |   58 +-
 .../opengl/util/pngj/chunks/PngChunkGAMA.java      |   30 +-
 .../opengl/util/pngj/chunks/PngChunkHIST.java      |   32 +-
 .../opengl/util/pngj/chunks/PngChunkICCP.java      |   35 +-
 .../opengl/util/pngj/chunks/PngChunkIDAT.java      |   28 +-
 .../opengl/util/pngj/chunks/PngChunkIEND.java      |   20 +-
 .../opengl/util/pngj/chunks/PngChunkIHDR.java      |   41 +-
 .../opengl/util/pngj/chunks/PngChunkITXT.java      |   36 +-
 .../opengl/util/pngj/chunks/PngChunkMultiple.java  |   27 +
 .../opengl/util/pngj/chunks/PngChunkOFFS.java      |   89 ++
 .../opengl/util/pngj/chunks/PngChunkPHYS.java      |   30 +-
 .../opengl/util/pngj/chunks/PngChunkPLTE.java      |   23 +-
 .../opengl/util/pngj/chunks/PngChunkSBIT.java      |   40 +-
 .../opengl/util/pngj/chunks/PngChunkSPLT.java      |   55 +-
 .../opengl/util/pngj/chunks/PngChunkSRGB.java      |   28 +-
 .../opengl/util/pngj/chunks/PngChunkSTER.java      |   60 +
 .../opengl/util/pngj/chunks/PngChunkSingle.java    |   43 +
 .../opengl/util/pngj/chunks/PngChunkSkipped.java   |   41 +
 .../opengl/util/pngj/chunks/PngChunkTEXT.java      |   32 +-
 .../opengl/util/pngj/chunks/PngChunkTIME.java      |   38 +-
 .../opengl/util/pngj/chunks/PngChunkTRNS.java      |   60 +-
 .../opengl/util/pngj/chunks/PngChunkTextVar.java   |   10 +-
 .../opengl/util/pngj/chunks/PngChunkUNKNOWN.java   |   21 +-
 .../opengl/util/pngj/chunks/PngChunkZTXT.java      |   28 +-
 .../opengl/util/pngj/chunks/PngMetadata.java       |  198 ++-
 .../classes/jogamp/opengl/util/pngj/package.html   |    5 +-
 .../opengl/windows/wgl/WGLGLCapabilities.java      |   53 +-
 .../windows/wgl/WindowsBitmapWGLContext.java       |   67 -
 .../windows/wgl/WindowsBitmapWGLDrawable.java      |   77 +-
 .../windows/wgl/WindowsExternalWGLContext.java     |   24 +-
 .../windows/wgl/WindowsOnscreenWGLContext.java     |   49 -
 .../windows/wgl/WindowsOnscreenWGLDrawable.java    |    2 +-
 .../windows/wgl/WindowsPbufferWGLContext.java      |  156 --
 .../windows/wgl/WindowsPbufferWGLDrawable.java     |   49 +-
 .../opengl/windows/wgl/WindowsWGLContext.java      |  121 +-
 .../opengl/windows/wgl/WindowsWGLDrawable.java     |    2 +-
 .../windows/wgl/WindowsWGLDrawableFactory.java     |  176 +--
 .../wgl/WindowsWGLDynamicLibraryBundleInfo.java    |    4 +-
 .../wgl/WindowsWGLGraphicsConfiguration.java       |  126 +-
 .../WindowsWGLGraphicsConfigurationFactory.java    |   53 +-
 .../opengl/x11/glx/X11ExternalGLXContext.java      |   22 +-
 .../jogamp/opengl/x11/glx/X11GLXContext.java       |  109 +-
 .../jogamp/opengl/x11/glx/X11GLXDrawable.java      |    2 +-
 .../opengl/x11/glx/X11GLXDrawableFactory.java      |  139 +-
 .../x11/glx/X11GLXDynamicLibraryBundleInfo.java    |   13 +-
 .../x11/glx/X11GLXGraphicsConfiguration.java       |   18 +-
 .../glx/X11GLXGraphicsConfigurationFactory.java    |    2 +-
 .../opengl/x11/glx/X11OnscreenGLXContext.java      |   48 -
 .../opengl/x11/glx/X11OnscreenGLXDrawable.java     |    6 +-
 .../opengl/x11/glx/X11PbufferGLXContext.java       |   67 -
 .../opengl/x11/glx/X11PbufferGLXDrawable.java      |   26 +-
 .../jogamp/opengl/x11/glx/X11PixmapGLXContext.java |   73 -
 .../opengl/x11/glx/X11PixmapGLXDrawable.java       |    6 +-
 src/jogl/native/JoglCommon.c                       |   22 +
 .../jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c |    8 +-
 .../macosx/MacOSXWindowSystemInterface-calayer.m   |  394 +++--
 .../native/macosx/MacOSXWindowSystemInterface.m    |   98 +-
 src/jogl/native/timespec.c                         |    5 +
 src/jogl/native/timespec.h                         |    3 +
 .../nativewindow/MutableGraphicsConfiguration.java |    7 +
 .../jogamp/nativewindow/NativeWindowVersion.java   |    8 +-
 .../nativewindow/awt/AWTGraphicsConfiguration.java |    6 +-
 .../nativewindow/awt/AWTWindowClosingProtocol.java |   78 +-
 .../com/jogamp/nativewindow/awt/JAWTWindow.java    |  202 ++-
 .../jogamp/nativewindow/egl/EGLGraphicsDevice.java |   20 +-
 .../com/jogamp/nativewindow/swt/SWTAccessor.java   |  453 ++++--
 .../jogamp/nativewindow/x11/X11GraphicsDevice.java |   22 +-
 .../AbstractGraphicsConfiguration.java             |    3 +-
 .../media/nativewindow/AbstractGraphicsDevice.java |   24 +-
 .../media/nativewindow/AbstractGraphicsScreen.java |    2 +
 .../javax/media/nativewindow/Capabilities.java     |   19 +-
 .../nativewindow/DefaultGraphicsConfiguration.java |   17 +-
 .../media/nativewindow/DefaultGraphicsDevice.java  |   66 +-
 .../media/nativewindow/DefaultGraphicsScreen.java  |    6 +-
 .../javax/media/nativewindow/NativeSurface.java    |    2 +-
 .../javax/media/nativewindow/NativeWindow.java     |    3 +-
 .../media/nativewindow/NativeWindowFactory.java    |  145 +-
 .../media/nativewindow/OffscreenLayerSurface.java  |   12 +
 .../javax/media/nativewindow/ProxySurface.java     |   18 +-
 .../media/nativewindow/WindowClosingProtocol.java  |    4 +
 .../javax/media/nativewindow/util/Dimension.java   |    5 +
 .../javax/media/nativewindow/util/Insets.java      |    8 +
 .../javax/media/nativewindow/util/Point.java       |    4 +
 .../javax/media/nativewindow/util/Rectangle.java   |   86 +-
 .../nativewindow/util/RectangleImmutable.java      |   20 +
 .../javax/media/nativewindow/util/SurfaceSize.java |    4 +-
 .../classes/jogamp/nativewindow/Debug.java         |   24 +-
 .../jogamp/nativewindow/ProxySurfaceImpl.java      |   32 +-
 .../classes/jogamp/nativewindow/awt/AWTMisc.java   |   28 +
 .../classes/jogamp/nativewindow/jawt/JAWTUtil.java |  127 +-
 .../nativewindow/jawt/macosx/MacOSXJAWTWindow.java |  172 ++-
 .../jawt/windows/WindowsJAWTWindow.java            |    7 -
 .../nativewindow/jawt/x11/X11JAWTWindow.java       |    7 -
 .../jogamp/nativewindow/macosx/OSXUtil.java        |  181 ++-
 .../jogamp/nativewindow/windows/GDIUtil.java       |   15 +-
 .../nativewindow/windows/RegisteredClass.java      |    5 +-
 .../windows/RegisteredClassFactory.java            |   26 +-
 .../x11/X11DummyUpstreamSurfaceHook.java           |    4 +-
 .../classes/jogamp/nativewindow/x11/X11Util.java   |   69 +-
 src/nativewindow/native/NativewindowCommon.c       |    9 +-
 src/nativewindow/native/NativewindowCommon.h       |    2 +-
 .../native/macosx/NativeWindowProtocols.h}         |   17 +-
 src/nativewindow/native/macosx/OSXmisc.m           |  466 ++++--
 .../native/win32/DeviceDriverQuery.txt             |   41 +
 src/nativewindow/native/win32/GDImisc.c            |   26 +
 src/nativewindow/native/win32/WindowsDWM.h         |    2 +
 src/nativewindow/native/x11/Xmisc.c                |  184 ++-
 src/nativewindow/native/x11/Xmisc.h                |    2 -
 src/newt/classes/com/jogamp/newt/Display.java      |   14 +-
 .../classes/com/jogamp/newt/MonitorDevice.java     |  235 +++
 src/newt/classes/com/jogamp/newt/MonitorMode.java  |  355 +++++
 src/newt/classes/com/jogamp/newt/NewtFactory.java  |   17 +-
 src/newt/classes/com/jogamp/newt/NewtVersion.java  |    7 +-
 src/newt/classes/com/jogamp/newt/Screen.java       |   91 +-
 src/newt/classes/com/jogamp/newt/ScreenMode.java   |  208 ---
 src/newt/classes/com/jogamp/newt/Window.java       |   80 +-
 .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java |  440 +++---
 .../jogamp/newt/awt/applet/JOGLNewtApplet1Run.java |   37 +-
 .../jogamp/newt/awt/applet/JOGLNewtAppletBase.java |   29 +-
 .../classes/com/jogamp/newt/event/InputEvent.java  |   19 +-
 .../classes/com/jogamp/newt/event/KeyAdapter.java  |    2 -
 .../classes/com/jogamp/newt/event/KeyEvent.java    | 1258 +++++++++-------
 .../classes/com/jogamp/newt/event/KeyListener.java |   24 +-
 .../{WindowUpdateEvent.java => MonitorEvent.java}  |   53 +-
 ...nModeListener.java => MonitorModeListener.java} |   12 +-
 .../classes/com/jogamp/newt/event/MouseEvent.java  |  302 +++-
 .../com/jogamp/newt/event/MouseListener.java       |   15 +-
 .../classes/com/jogamp/newt/event/NEWTEvent.java   |  122 +-
 .../com/jogamp/newt/event/OutputEvent.java}        |   36 +-
 .../com/jogamp/newt/event/TraceKeyAdapter.java     |    4 -
 .../classes/com/jogamp/newt/event/WindowEvent.java |   18 +-
 .../com/jogamp/newt/event/WindowListener.java      |   16 +-
 .../com/jogamp/newt/event/WindowUpdateEvent.java   |    2 +-
 .../com/jogamp/newt/event/awt/AWTAdapter.java      |    7 +-
 .../com/jogamp/newt/event/awt/AWTKeyAdapter.java   |   18 +-
 .../jogamp/newt/event/awt/AWTWindowAdapter.java    |   20 +-
 .../classes/com/jogamp/newt/opengl/GLWindow.java   |  113 +-
 .../classes/com/jogamp/newt/swt/NewtCanvasSWT.java |   95 +-
 src/newt/classes/com/jogamp/newt/util/EDTUtil.java |   17 +-
 .../classes/com/jogamp/newt/util/MonitorMode.java  |  102 --
 .../com/jogamp/newt/util/MonitorModeUtil.java      |  247 ++++
 .../com/jogamp/newt/util/ScreenModeUtil.java       |  341 -----
 src/newt/classes/jogamp/newt/Debug.java            |   25 +-
 src/newt/classes/jogamp/newt/DefaultEDTUtil.java   |  127 +-
 src/newt/classes/jogamp/newt/DisplayImpl.java      |  122 +-
 .../classes/jogamp/newt/MonitorDeviceImpl.java     |  147 ++
 src/newt/classes/jogamp/newt/MonitorModeProps.java |  355 +++++
 src/newt/classes/jogamp/newt/OffscreenWindow.java  |   13 +-
 src/newt/classes/jogamp/newt/ScreenImpl.java       |  637 ++++----
 src/newt/classes/jogamp/newt/ScreenModeStatus.java |  231 ---
 .../classes/jogamp/newt/ScreenMonitorState.java    |  195 +++
 src/newt/classes/jogamp/newt/WindowImpl.java       |  847 +++++++----
 .../jogamp/newt/awt/event/AWTNewtEventFactory.java |  649 +++++++-
 .../newt/awt/event/AWTParentWindowAdapter.java     |    8 +-
 .../jogamp/newt/driver/DriverUpdatePosition.java   |   10 +-
 .../newt/driver/android/NewtBaseActivity.java      |  243 ++-
 .../newt/driver/android/NewtVersionActivity.java   |   13 +-
 .../android/NewtVersionActivityLauncher.java       |    2 +-
 .../jogamp/newt/driver/android/ScreenDriver.java   |  101 +-
 .../jogamp/newt/driver/android/WindowDriver.java   |  486 ++++--
 .../android/event/AndroidNewtEventFactory.java     |  612 ++++++--
 .../android/event/AndroidNewtEventTranslator.java  |   53 +
 .../classes/jogamp/newt/driver/awt/AWTCanvas.java  |   46 +-
 .../classes/jogamp/newt/driver/awt/AWTEDTUtil.java |  114 +-
 .../jogamp/newt/driver/awt/DisplayDriver.java      |    1 -
 .../jogamp/newt/driver/awt/ScreenDriver.java       |   65 +-
 .../jogamp/newt/driver/awt/WindowDriver.java       |  199 ++-
 .../jogamp/newt/driver/bcm/egl/ScreenDriver.java   |   56 +-
 .../jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java |   56 +-
 .../jogamp/newt/driver/bcm/vc/iv/WindowDriver.java |   20 +-
 .../jogamp/newt/driver/intel/gdl/ScreenDriver.java |   56 +-
 .../jogamp/newt/driver/kd/ScreenDriver.java        |   54 +-
 .../newt/driver/linux/LinuxEventDeviceTracker.java |  959 ++++++++++++
 .../newt/driver/linux/LinuxMouseTracker.java       |   17 +-
 .../jogamp/newt/driver/macosx/MacKeyUtil.java      |  264 +++-
 .../jogamp/newt/driver/macosx/ScreenDriver.java    |  129 +-
 .../jogamp/newt/driver/macosx/WindowDriver.java    |  436 ++++--
 .../jogamp/newt/driver/windows/DisplayDriver.java  |   13 +-
 .../jogamp/newt/driver/windows/ScreenDriver.java   |  146 +-
 .../jogamp/newt/driver/windows/WindowDriver.java   |  129 +-
 .../jogamp/newt/driver/x11/DisplayDriver.java      |   22 +-
 src/newt/classes/jogamp/newt/driver/x11/RandR.java |   76 +
 .../classes/jogamp/newt/driver/x11/RandR11.java    |  361 +++++
 .../classes/jogamp/newt/driver/x11/RandR13.java    |  309 ++++
 .../jogamp/newt/driver/x11/ScreenDriver.java       |  338 ++---
 .../jogamp/newt/driver/x11/WindowDriver.java       |   80 +-
 .../{com => }/jogamp/newt/swt/SWTEDTUtil.java      |  130 +-
 .../jogamp/newt/swt/event/SWTNewtEventFactory.java |  375 +++++
 src/newt/native/KDWindow.c                         |   12 +-
 src/newt/native/KeyEvent.h                         |  388 ++---
 src/newt/native/MacWindow.m                        |  636 ++++----
 src/newt/native/NewtCommon.c                       |    9 +-
 src/newt/native/NewtCommon.h                       |    2 +-
 src/newt/native/NewtMacWindow.h                    |   30 +-
 src/newt/native/NewtMacWindow.m                    |  416 ++++--
 src/newt/native/ScreenMode.h                       |   15 +-
 src/newt/native/Window.h                           |   17 +-
 src/newt/native/WindowsWindow.c                    | 1349 +++++++++--------
 src/newt/native/X11Common.h                        |    4 +-
 src/newt/native/X11Display.c                       |  247 ++--
 src/newt/native/X11Event.c                         |   26 +-
 .../native/{X11ScreenRandR11.c => X11RandR11.c}    |  203 ++-
 src/newt/native/X11RandR13.c                       |  515 +++++++
 src/newt/native/X11Screen.c                        |  429 +-----
 .../event/KeyAdapter.java => native/X11Screen.h}   |   23 +-
 src/newt/native/X11ScreenRandR13.c                 |  372 -----
 src/newt/native/X11Window.c                        |   28 +-
 src/newt/native/XCBEvent.c                         |   18 +-
 src/newt/native/bcm_vc_iv.c                        |    8 +-
 src/test-native/displayMultiple02_mch.c            |  130 ++
 src/test-native/displayMultiple02_new_mch.c        |  199 +++
 src/test-native/make.sh                            |    2 +
 .../jogamp/opengl/test/android/LauncherUtil.java   |  172 ++-
 .../opengl/test/android/MovieCubeActivity0.java    |    3 +-
 .../test/android/MovieCubeActivityLauncher0.java   |   14 +-
 .../opengl/test/android/MovieSimpleActivity0.java  |    1 -
 .../opengl/test/android/MovieSimpleActivity1.java  |    1 -
 .../android/MovieSimpleActivityLauncher00a.java    |   13 +-
 .../android/MovieSimpleActivityLauncher00b.java    |   13 +-
 .../android/MovieSimpleActivityLauncher01a.java    |   13 +-
 .../android/MovieSimpleActivityLauncher01b.java    |   13 +-
 .../android/MovieSimpleActivityLauncher02.java     |   13 +-
 .../opengl/test/android/NEWTElektronActivity.java  |   17 +-
 .../test/android/NEWTElektronActivityLauncher.java |   12 +-
 .../opengl/test/android/NEWTGearsES1Activity.java  |   17 +-
 .../test/android/NEWTGearsES1ActivityLauncher.java |   12 +-
 .../opengl/test/android/NEWTGearsES2Activity.java  |   74 +-
 .../test/android/NEWTGearsES2ActivityLauncher.java |   24 +-
 ...r.java => NEWTGearsES2ECTActivityLauncher.java} |   23 +-
 ...ava => NEWTGearsES2RGB565ActivityLauncher.java} |   23 +-
 .../test/android/NEWTGearsES2TransActivity.java    |   17 +-
 .../android/NEWTGearsES2TransActivityLauncher.java |   14 +-
 .../opengl/test/android/NEWTGraphUI1pActivity.java |   17 +-
 .../android/NEWTGraphUI1pActivityLauncher.java     |   13 +-
 .../opengl/test/android/NEWTGraphUI2pActivity.java |   17 +-
 .../android/NEWTGraphUI2pActivityLauncher.java     |   13 +-
 .../test/android/NEWTRedSquareES1Activity.java     |   17 +-
 .../android/NEWTRedSquareES1ActivityLauncher.java  |   13 +-
 .../test/android/NEWTRedSquareES2Activity.java     |   17 +-
 .../android/NEWTRedSquareES2ActivityLauncher.java  |    2 +-
 .../opengl/test/bugs/Bug427GLJPanelTest1.java      |   24 +-
 .../aaaa-m1-sync0-flush-wait-finish.log            |  751 ++++++++++
 .../aaaa-m1-sync1-flush-wait-finish.log            |  745 ++++++++++
 .../aaaa-m2-sync0-finish-wait-exclctx.log          |  751 ++++++++++
 .../aaaa-m2-sync0-finish-wait.log                  |  751 ++++++++++
 .../aaaa-m2-sync1-finish-wait.log                  |  745 ++++++++++
 .../opengl/test/bugs/Bug735Inv0AppletAWT.java      |  430 ++++++
 .../opengl/test/bugs/Bug735Inv1AppletAWT.java      |  429 ++++++
 .../opengl/test/bugs/Bug735Inv2AppletAWT.java      |  272 ++++
 .../opengl/test/bugs/Bug735Inv3AppletAWT.java      |  218 +++
 .../com/jogamp/opengl/test/bugs/Bug735Inv4AWT.java |  202 +++
 .../com/jogamp/opengl/test/bugs/Issue344Base.java  |   11 +-
 .../test/junit/graph/TestTextRendererNEWT00.java   |    2 +-
 .../test/junit/graph/TestTextRendererNEWT01.java   |    0
 .../test/junit/graph/TestTextRendererNEWT10.java   |   21 +-
 .../junit/graph/demos/GPURegionNewtDemo01.java     |    0
 .../graph/demos/GPURendererListenerBase01.java     |    1 -
 .../graph/demos/GPUTextRendererListenerBase01.java |   12 +-
 .../junit/graph/demos/GPUUISceneGLListener0A.java  |    5 +-
 .../opengl/test/junit/graph/demos/ui/RIButton.java |    2 +-
 .../junit/graph/demos/ui/SceneUIController.java    |    1 +
 .../junit/graph/demos/ui/UIListenerBase01.java     |    1 -
 .../opengl/test/junit/graph/demos/ui/UIShape.java  |    2 +-
 .../junit/jogl/acore/InitConcurrentBaseNEWT.java   |    2 +-
 .../jogl/acore/TestAWTCloseX11DisplayBug565.java   |   17 +-
 .../acore/TestAddRemove01GLCanvasSwingAWT.java     |  287 ++++
 .../TestAddRemove02GLWindowNewtCanvasAWT.java      |  285 ++++
 .../jogl/acore/TestAddRemove03GLWindowNEWT.java    |  144 ++
 .../acore/TestBug669RecursiveGLContext01NEWT.java  |  135 ++
 .../acore/TestBug669RecursiveGLContext02NEWT.java  |  132 ++
 .../test/junit/jogl/acore/TestBug692GL3VAO.java    |  352 +++++
 .../jogl/acore/TestFBOAutoDrawableDeadlockAWT.java |    2 +-
 .../junit/jogl/acore/TestFBOMix2DemosES2NEWT.java  |    5 +-
 ...tFBOOffThreadSharedContextMix2DemosES2NEWT.java |    3 +
 .../TestFBOOnThreadSharedContext1DemoES2NEWT.java  |    2 +
 .../jogl/acore/TestGLAutoDrawableDelegateNEWT.java |  160 ++
 ...estGLAutoDrawableDelegateOnOffscrnCapsNEWT.java |   38 +-
 ...stGLAutoDrawableFactoryES2OffscrnCapsNEWT.java} |  138 +-
 ...stGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java} |  177 ++-
 ...estGLAutoDrawableFactoryGLnBitmapCapsNEWT.java} |  162 +-
 ...TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java |   63 +-
 ...estGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java |  136 +-
 ...LAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java |   53 +-
 .../junit/jogl/acore/TestGLMesaBug651NEWT.java     |  222 +++
 .../junit/jogl/acore/TestGLMesaBug658NEWT.java     |  200 +++
 .../{TestPointsNEWT.java => TestGLPointsNEWT.java} |    4 +-
 .../jogl/acore/TestGLVersionParsing00NEWT.java     |  201 +++
 .../junit/jogl/acore/TestInitConcurrent01NEWT.java |    6 +-
 .../junit/jogl/acore/TestInitConcurrent02NEWT.java |    6 +-
 .../acore/TestOffscreenLayer01GLCanvasAWT.java     |   15 +-
 .../acore/TestOffscreenLayer02NewtCanvasAWT.java   |   16 +-
 .../junit/jogl/acore/TestPBufferDeadlockAWT.java   |    2 +-
 .../jogl/acore/TestSharedContextNewtAWTBug523.java |    5 +-
 .../junit/jogl/acore/TestShutdownCompleteAWT.java  |    7 +-
 .../TestX11DefaultDisplay.java}                    |  133 +-
 .../jogl/acore/ect/ExclusiveContextBase00.java     |  420 ++++++
 .../jogl/acore/ect/ExclusiveContextBase00AWT.java  |  161 ++
 .../jogl/acore/ect/ExclusiveContextBase00NEWT.java |   94 ++
 .../jogl/acore/ect/ExclusiveContextBase10.java     |  213 +++
 .../jogl/acore/ect/ExclusiveContextBase10AWT.java  |  161 ++
 .../jogl/acore/ect/ExclusiveContextBase10NEWT.java |   94 ++
 .../TestExclusiveContext01VSyncAnimAWT.java}       |   66 +-
 .../ect/TestExclusiveContext01VSyncAnimNEWT.java}  |   53 +-
 .../TestExclusiveContext02FPSAnimAWT.java}         |   68 +-
 .../ect/TestExclusiveContext02FPSAnimNEWT.java}    |   55 +-
 .../ect/TestExclusiveContext11VSyncAnimNEWT.java}  |   52 +-
 .../TestExclusiveContext12FPSAnimNEWT.java}        |   65 +-
 .../acore/glels/GLContextDrawableSwitchBase.java   |  291 ++++
 .../TestBug722GLContextDrawableSwitchNewt2AWT.java |  143 ++
 .../TestGLContextDrawableSwitch01NEWT.java}        |  178 ++-
 .../glels/TestGLContextDrawableSwitch10NEWT.java   |  274 ++++
 .../TestGLContextDrawableSwitch11NewtAWT.java      |  118 ++
 .../glels/TestGLContextDrawableSwitch12AWT.java    |  144 ++
 .../TestGLContextDrawableSwitch21Newt2AWT.java     |  192 +++
 .../opengl/test/junit/jogl/awt/TestAWT01GLn.java   |   12 +-
 .../junit/jogl/awt/TestAWT02WindowClosing.java     |   11 +-
 .../jogl/awt/TestAWT03GLCanvasRecreate01.java      |    2 +-
 .../TestAWTCardLayoutAnimatorStartStopBug532.java  |    5 +-
 .../awt/TestBug461FBOSupersamplingSwingAWT.java    |   43 +-
 .../opengl/test/junit/jogl/awt/TestBug572AWT.java  |  109 +-
 ....java => TestBug642JSplitPaneMixHwLw01AWT.java} |  112 +-
 .../awt/TestBug664GLCanvasSetVisibleSwingAWT.java  |  283 ++++
 .../jogl/awt/TestBug675BeansInDesignTimeAWT.java   |  111 ++
 .../awt/TestGLCanvasAWTActionDeadlock00AWT.java    |  241 +++
 .../awt/TestGLCanvasAWTActionDeadlock01AWT.java    |  348 +++++
 .../awt/TestGLCanvasAWTActionDeadlock02AWT.java    |  687 +++++++++
 .../jogl/awt/TestIsRealizedConcurrency01AWT.java   |  101 ++
 .../jogl/awt/TestJScrollPaneMixHwLw01AWT.java      |    7 +-
 .../TestAWTTextRendererUseVertexArrayBug464.java   |   14 +-
 .../jogl/caps/TestBug605FlippedImageNEWT.java      |    2 +-
 .../junit/jogl/caps/TestMultisampleES1AWT.java     |    4 +-
 .../junit/jogl/caps/TestMultisampleES1NEWT.java    |    0
 .../test/junit/jogl/caps/TestTranslucencyAWT.java  |   11 +-
 .../test/junit/jogl/caps/TestTranslucencyNEWT.java |    5 +-
 .../test/junit/jogl/demos/GLFinishOnDisplay.java   |   40 +
 .../opengl/test/junit/jogl/demos/GearsObject.java  |   10 +-
 .../opengl/test/junit/jogl/demos/es1/GearsES1.java |   23 +-
 .../test/junit/jogl/demos/es1/GearsObjectES1.java  |    8 +-
 .../test/junit/jogl/demos/es1/OlympicES1.java      |  357 +++++
 .../test/junit/jogl/demos/es1/RedSquareES1.java    |    2 +-
 .../jogl/demos/es1/newt/TestGearsES1NEWT.java      |   14 +-
 ...stGearsES1NEWT.java => TestOlympicES1NEWT.java} |   82 +-
 .../jogl/demos/es1/newt/TestRedSquareES1NEWT.java  |    5 +-
 .../opengl/test/junit/jogl/demos/es2/GearsES2.java |  316 +++-
 .../test/junit/jogl/demos/es2/GearsObjectES2.java  |   43 +-
 .../test/junit/jogl/demos/es2/LandscapeES2.java    |  182 +++
 .../test/junit/jogl/demos/es2/Mix2TexturesES2.java |   37 +-
 .../junit/jogl/demos/es2/MultisampleDemoES2.java   |    2 +-
 .../test/junit/jogl/demos/es2/PointsDemoES2.java   |    6 +-
 .../test/junit/jogl/demos/es2/RedSquareES2.java    |   65 +-
 .../jogl/demos/es2/TextureDraw01ES2Listener.java   |    4 +-
 .../jogl/demos/es2/TextureSequenceCubeES2.java     |    1 -
 .../test/junit/jogl/demos/es2/av/MovieCube.java    |    5 +-
 .../test/junit/jogl/demos/es2/av/MovieSimple.java  |    0
 .../junit/jogl/demos/es2/awt/TestGearsES2AWT.java  |  275 +++-
 .../demos/es2/awt/TestGearsES2GLJPanelAWT.java     |  361 +++++
 .../demos/es2/awt/TestGearsES2GLJPanelsAWT.java    |  419 ++++++
 .../es2/newt/TestElektronenMultipliziererNEWT.java |    5 +-
 .../jogl/demos/es2/newt/TestGearsES2NEWT.java      |  185 ++-
 .../demos/es2/newt/TestGearsES2NewtCanvasAWT.java  |  511 +++++++
 ...ES2NEWT.java => TestGearsES2NewtCanvasSWT.java} |  287 ++--
 ...quareES2NEWT.java => TestLandscapeES2NEWT.java} |  123 +-
 .../es2/newt/TestLandscapeES2NewtCanvasAWT.java    |  261 ++++
 .../jogl/demos/es2/newt/TestRedSquareES2NEWT.java  |   25 +-
 .../test/junit/jogl/demos/es2/shader/landscape.fp  |  339 +++++
 .../test/junit/jogl/demos/es2/shader/landscape.vp  |   11 +
 .../junit/jogl/demos/es2/swt/TestGearsES2SWT.java  |  341 +++++
 .../opengl/test/junit/jogl/demos/gl2/Gears.java    |   11 +-
 .../opengl/test/junit/jogl/demos/gl2/Teapot.java   |  124 ++
 .../jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java  |   22 +-
 .../junit/jogl/demos/gl2/awt/TestGearsAWT.java     |    5 +-
 .../demos/gl2/awt/TestGearsAWTAnalyzeBug455.java   |    7 +-
 .../jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java   |  175 ++-
 .../junit/jogl/demos/gl2/newt/TestGearsNEWT.java   |    5 +-
 .../demos/gl2/newt/TestGearsNewtAWTWrapper.java    |   68 +-
 .../{TestGearsNEWT.java => TestTeapotNEWT.java}    |  100 +-
 .../jogl/demos/gl3/GeomShader01TextureGL3.java     |  293 ++++
 .../newt/TestGeomShader01TextureGL3NEWT.java}      |  145 +-
 .../junit/jogl/demos/gl3/shader/flipXYZ01_xxx.gp   |   32 +
 .../jogl/demos/gl3/shader/passthrough01_xxx.gp     |   31 +
 .../junit/jogl/demos/gl3/shader/texture01_xxx.fp   |   20 +
 .../junit/jogl/demos/gl3/shader/texture01_xxx.vp   |   20 +
 .../test/junit/jogl/glsl/GLSLMiscHelper.java       |  167 ++-
 .../junit/jogl/glsl/TestGLSLShaderState01NEWT.java |  190 ++-
 .../junit/jogl/glsl/TestGLSLShaderState02NEWT.java |   57 +-
 .../test/junit/jogl/glsl/TestRulerNEWT01.java      |   20 +-
 .../jogl/glsl/TestShaderCompilationBug459AWT.java  |   11 +-
 .../TestBug694ScaleImageUnpackBufferSizeAWT.java   |  160 ++
 .../TestFloatUtil01MatrixMatrixMultNOUI.java       |    4 +-
 .../{glu => math}/TestGluUnprojectDoubleNOUI.java  |    2 +-
 .../{glu => math}/TestGluUnprojectFloatNOUI.java   |    2 +-
 .../jogl/{acore => math}/TestPMVMatrix01NEWT.java  |   46 +-
 .../TestPMVMatrix02NOUI.java}                      |    6 +-
 .../test/junit/jogl/math/TestPMVMatrix03NOUI.java  |  125 ++
 ...TestSwingAWTRobotUsageBeforeJOGLInitBug411.java |   29 +-
 .../TestNewtCanvasSWTBug628ResizeDeadlockAWT.java  |  405 +++++
 .../test/junit/jogl/swt/TestNewtCanvasSWTGLn.java  |   21 +-
 .../junit/jogl/swt/TestSWTAccessor03AWTGLn.java    |   21 +-
 .../junit/jogl/swt/TestSWTBug643AsyncExec.java     |  342 +++++
 .../junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java   |   45 +-
 .../junit/jogl/util/DemoGL2ES1ImmModeSink.java     |   35 +-
 .../test/junit/jogl/util/DemoGL2ES1Plain.java      |   27 +
 .../junit/jogl/util/DemoGL2ES2ImmModeSink.java     |  207 +++
 .../junit/jogl/util/TestImmModeSinkES2NEWT.java    |  119 ++
 .../test/junit/jogl/util/TestPNGImage01NEWT.java   |   41 -
 .../jogl/util/texture/TestJPEGImage01NEWT.java     |  124 ++
 .../texture/TestJPEGJoglAWTBenchmarkNewtAWT.java   |  151 ++
 .../texture/TestJPEGJoglAWTCompareNewtAWT.java     |  267 ++++
 .../util/texture/TestJPEGTextureFromFileNEWT.java  |  281 ++++
 .../jogl/util/texture/TestPNGImage01NEWT.java      |   62 +
 .../util/texture/TestPNGTextureFromFileAWT.java    |   10 +-
 .../util/texture/TestPNGTextureFromFileNEWT.java   |  134 +-
 .../junit/jogl/util/texture/TestTexture01AWT.java  |   93 +-
 ...TestTexture01AWT.java => TestTexture02AWT.java} |  139 +-
 .../util/texture/TestTextureSequence01AWT.java     |   12 +-
 .../jogl/util/texture/bug745_qttdef_post_frame.jpg |  Bin 0 -> 8415 bytes
 .../junit/jogl/util/texture/grayscale_texture.png  |  Bin
 .../test/junit/jogl/util/texture/j1-baseline.jpg   |  Bin 0 -> 21257 bytes
 .../junit/jogl/util/texture/j2-progressive.jpg     |  Bin 0 -> 22306 bytes
 .../junit/jogl/util/texture/j3-baseline_gray.jpg   |  Bin 0 -> 17776 bytes
 .../test/junit/jogl/util/texture/test-cmyk-01.jpg  |  Bin 0 -> 10445 bytes
 .../jogl/util/texture/test-ntscIG3-01-160x90.png   |  Bin 0 -> 3745 bytes
 .../jogl/util/texture/test-ntscIG4-01-160x90.png   |  Bin 0 -> 4240 bytes
 .../jogl/util/texture/test-ntscI_3-01-160x90.png   |  Bin 0 -> 3729 bytes
 .../jogl/util/texture/test-ntscI_4-01-160x90.png   |  Bin 0 -> 4224 bytes
 .../jogl/util/texture/test-ntscNG4-01-160x90.png   |  Bin 0 -> 4240 bytes
 .../test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg  |  Bin 0 -> 2628 bytes
 .../test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg  |  Bin 0 -> 2376 bytes
 .../test-ntscN_3-01-160x90-90pct-yuv444-base.jpg   |  Bin 0 -> 4122 bytes
 .../test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg   |  Bin 0 -> 4411 bytes
 .../jogl/util/texture/test-ntscN_3-01-160x90.png   |  Bin 0 -> 2785 bytes
 .../jogl/util/texture/test-ntscN_4-01-160x90.png   |  Bin 0 -> 3177 bytes
 .../jogl/util/texture/test-ntscP_3-01-160x90.png   |  Bin 0 -> 1898 bytes
 .../jogl/util/texture/test-ntscP_4-01-160x90.png   |  Bin 0 -> 1911 bytes
 .../test/junit/jogl/util/texture/test-ycck-01.jpg  |  Bin 0 -> 62492 bytes
 .../test/junit/newt/ManualScreenMode03NEWT.java    |   32 +-
 .../opengl/test/junit/newt/TestCloseNewtAWT.java   |    7 +-
 .../junit/newt/TestDisplayLifecycle01NEWT.java     |    4 +-
 .../test/junit/newt/TestFocus01SwingAWTRobot.java  |   19 +-
 .../test/junit/newt/TestFocus02SwingAWTRobot.java  |   57 +-
 .../newt/TestGLWindowInvisiblePointer01NEWT.java   |  114 ++
 .../junit/newt/TestGLWindowWarpPointer01NEWT.java  |  171 +++
 .../junit/newt/TestGLWindows02NEWTAnimated.java    |   46 +-
 .../test/junit/newt/TestScreenMode00NEWT.java      |  119 +-
 .../test/junit/newt/TestScreenMode00bNEWT.java     |   26 +-
 .../test/junit/newt/TestScreenMode01NEWT.java      |  135 +-
 ...Mode01bNEWT.java => TestScreenMode01aNEWT.java} |   95 +-
 .../test/junit/newt/TestScreenMode01bNEWT.java     |  210 ++-
 .../test/junit/newt/TestScreenMode01cNEWT.java     |  249 ++++
 .../test/junit/newt/TestScreenMode02NEWT.java      |   76 +-
 .../junit/newt/TestWindowClosingProtocol01AWT.java |   48 +-
 .../newt/TestWindowClosingProtocol02NEWT.java      |   14 +-
 .../newt/TestWindowClosingProtocol03NewtAWT.java   |   48 +-
 .../junit/newt/event/BaseNewtEventModifiers.java   |  781 ++++++++++
 .../event/TestNewtEventModifiersAWTCanvas.java     |  103 ++
 .../event/TestNewtEventModifiersNEWTWindowAWT.java |   84 ++
 .../event/TestNewtEventModifiersNewtCanvasAWT.java |  118 ++
 .../TestNewtEventModifiersNewtCanvasSWTAWT.java    |  180 +++
 .../{ => event}/TestNewtKeyCodeModifiersAWT.java   |  152 +-
 .../newt/{ => event}/TestNewtKeyCodesAWT.java      |  112 +-
 .../{ => event}/TestNewtKeyEventAutoRepeatAWT.java |   72 +-
 .../newt/{ => event}/TestNewtKeyEventOrderAWT.java |   47 +-
 .../TestNewtKeyPressReleaseUnmaskRepeatAWT.java    |   36 +-
 .../test/junit/newt/parenting/KeyAction.java       |    5 +-
 .../parenting/NewtAWTReparentingKeyAdapter.java    |    5 +-
 .../junit/newt/parenting/TestParenting01NEWT.java  |    6 +
 .../junit/newt/parenting/TestParenting01aAWT.java  |   32 +-
 .../junit/newt/parenting/TestParenting01bAWT.java  |    8 +-
 .../junit/newt/parenting/TestParenting01cAWT.java  |   20 +-
 .../newt/parenting/TestParenting01cSwingAWT.java   |   27 +-
 .../junit/newt/parenting/TestParenting02AWT.java   |   11 +-
 .../junit/newt/parenting/TestParenting03AWT.java   |    4 +-
 .../junit/newt/parenting/TestParenting04AWT.java   |   12 +-
 .../TestParentingFocusTraversal01AWT.java          |   10 +-
 .../TestTranslucentChildWindowBug632NEWT.java      |  132 ++
 .../parenting/TestTranslucentParentingAWT.java     |   21 +-
 .../opengl/test/junit/util/AWTKeyAdapter.java      |   19 +-
 .../opengl/test/junit/util/AWTRobotUtil.java       |  449 ++++--
 .../test/junit/util/GLEventListenerCounter.java}   |   50 +-
 .../test/junit/util/KeyEventCountAdapter.java      |    4 +-
 .../jogamp/opengl/test/junit/util/MiscUtils.java   |   34 +
 .../opengl/test/junit/util/NEWTKeyAdapter.java     |   30 +-
 .../jogamp/opengl/test/junit/util/NEWTKeyUtil.java |  130 +-
 .../jogamp/opengl/test/junit/util/QuitAdapter.java |   25 +-
 .../jogamp/opengl/test/junit/util/UITestCase.java  |   21 +-
 www/index.html                                     | 1038 +++++++------
 www/media/Java3d.png                               |  Bin 0 -> 8675 bytes
 www/media/ardor3d.png                              |  Bin 0 -> 3007 bytes
 www/media/dyn4j.png                                |  Bin 0 -> 5373 bytes
 www/media/jmonkeyengine.png                        |  Bin 0 -> 38087 bytes
 www/media/nifty-logo-new.png                       |  Bin 0 -> 10305 bytes
 www/media/ticket2ride_picture4.jpg                 |  Bin 0 -> 71952 bytes
 776 files changed, 57618 insertions(+), 19275 deletions(-)

diff --git a/.classpath b/.classpath
index 064f059..41f50c0 100644
--- a/.classpath
+++ b/.classpath
@@ -32,5 +32,6 @@
 	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Ant"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/SWT"/>
 	<classpathentry kind="lib" path="/gluegen/make/lib/android-sdk/15/android.jar" sourcepath="/gluegen/make/lib/android-sdk/15/android-java-src.zip"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/joal"/>
 	<classpathentry kind="output" path="build/eclipse-classes"/>
 </classpath>
diff --git a/LICENSE.txt b/LICENSE.txt
index 3550ab2..6da9f54 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -45,7 +45,9 @@ L.1) The JOGL source tree contains code from the JogAmp Community
    You can address the JogAmp Community via:
        Web                http://jogamp.org/
        Forum/Mailinglist  http://forum.jogamp.org
-       JogAmp Channel     server: conference.jabber.org room: jogamp
+       Chatrooms
+         IRC              irc.freenode.net #jogamp 
+         Jabber           conference.jabber.org room: jogamp (deprecated!)
        Repository         http://jogamp.org/git/
        Email              mediastream _at_ jogamp _dot_ org
 
@@ -344,7 +346,7 @@ A.6) The JOGL source tree contains code from Hernan J. Gonzalez and Shawn Hartso
 
    PNGJ: Java library for reading and writing PNG images.
 
-   Version 0.85  (1 April 2012)
+   Version 1.12  (3 Dec 2012)
 
    <http://code.google.com/p/pngj/>
 
diff --git a/README.txt b/README.txt
index 0cf1417..7d9e1de 100644
--- a/README.txt
+++ b/README.txt
@@ -22,7 +22,9 @@ Contact Us
 
 Web                http://jogamp.org/
 Forum/Mailinglist  http://forum.jogamp.org/
-JogAmp Channel     server: conference.jabber.org room: jogamp
+Chatrooms
+  IRC              irc.freenode.net #jogamp 
+  Jabber           conference.jabber.org room: jogamp (deprecated!)
 Repository         http://jogamp.org/git/
 Email              mediastream _at_ jogamp _dot_ org
 
diff --git a/doc/HowToBuild.html b/doc/HowToBuild.html
index ad965e1..529d100 100644
--- a/doc/HowToBuild.html
+++ b/doc/HowToBuild.html
@@ -76,7 +76,7 @@
                         <li> <b>GNU Linux</b> x86, 32- and 64-bit<br/>
                             You may have to install a few developer packages ...
                             <ul>
-                                <li> <b>[K]Ubuntu</b> 10.04 or later
+                                <li> <b>Debian</b> 5.00 or later
                                     <ul>
                                         <li>git</li>
                                         <li>gcc</li>
diff --git a/etc/profile.jogl b/etc/profile.jogl
index 7dd5191..16b3a3d 100755
--- a/etc/profile.jogl
+++ b/etc/profile.jogl
@@ -7,15 +7,15 @@ function print_usage()
 
 function concat_jogl_list()
 {
-    ITEMDIR=$1
+    ITEMDIR="$1"
     shift
-    for j in $ITEMDIR $ITEMDIR/jar ; do
+    for j in "$ITEMDIR" "$ITEMDIR"/jar ; do
         for i in $* ; do
-            if [ -e $j/$i ] ; then 
+            if [ -e "$j"/$i ] ; then 
                 if [ -z "$JOGL_LIST" ] ; then
-                    JOGL_LIST=$j/$i
+                    JOGL_LIST="$j"/$i
                 else
-                    JOGL_LIST=$JOGL_LIST:$j/$i
+                    JOGL_LIST="$JOGL_LIST":"$j"/$i
                 fi
             fi
         done
@@ -24,6 +24,10 @@ function concat_jogl_list()
 }
 
 ARCH=`uname -m`
+if [ "$ARCH" = "i86pc" ] ; then
+    ARCH="x86"
+fi
+
 KERNEL=`uname -s | awk ' { printf "%s",tolower($0) ; } '`
 if [ "$KERNEL" = "sunos" ] ; then
     KERNEL="solaris"
@@ -64,23 +68,23 @@ AUTOBUILD=0
 
 if [ ! -z "$JOGL_BUILD_DIR" -a -e "$JOGL_BUILD_DIR" ] ; then
     AUTOBUILD=0
-elif [ -e $THISDIR/jar ] ; then
+elif [ -e "$THISDIR"/jar ] ; then
     # Autobuild
-    JOGL_BUILD_DIR=$THISDIR/jar
+    JOGL_BUILD_DIR="$THISDIR"/jar
     AUTOBUILD=1
 else
-    echo invalid JOGL_BUILD_DIR $JOGL_BUILD_DIR and no AUTOBUILD
+    echo invalid JOGL_BUILD_DIR "$JOGL_BUILD_DIR" and no AUTOBUILD
     print_usage
 fi 
 export JOGL_BUILD_DIR
 
-JOGL_LIB_DIR=$JOGL_BUILD_DIR/lib
+JOGL_LIB_DIR="$JOGL_BUILD_DIR"/lib
 export JOGL_LIB_DIR
 
-JOGL_ALL_AWT_CLASSPATH=$(concat_jogl_list $JOGL_BUILD_DIR $JOGL_JAR_ALL $JOGL_TEST)
-JOGL_ALL_NOAWT_CLASSPATH=$(concat_jogl_list $JOGL_BUILD_DIR $JOGL_JAR_ALL_NOAWT $JOGL_TEST)
-JOGL_MOBILE_CLASSPATH=$(concat_jogl_list $JOGL_BUILD_DIR $JOGL_JAR_ALL_MOBILE $JOGL_TEST)
-JOGL_SWT_CLASSPATH=$(concat_jogl_list $JOGL_BUILD_DIR $JOGL_JAR_SWT $JOGL_TEST)
+JOGL_ALL_AWT_CLASSPATH=$(concat_jogl_list "$JOGL_BUILD_DIR" $JOGL_JAR_ALL $JOGL_TEST)
+JOGL_ALL_NOAWT_CLASSPATH=$(concat_jogl_list "$JOGL_BUILD_DIR" $JOGL_JAR_ALL_NOAWT $JOGL_TEST)
+JOGL_MOBILE_CLASSPATH=$(concat_jogl_list "$JOGL_BUILD_DIR" $JOGL_JAR_ALL_MOBILE $JOGL_TEST)
+JOGL_SWT_CLASSPATH=$(concat_jogl_list "$JOGL_BUILD_DIR" $JOGL_JAR_SWT $JOGL_TEST)
 export JOGL_ALL_AWT_CLASSPATH JOGL_ALL_NOAWT_CLASSPATH JOGL_MOBILE_CLASSPATH JOGL_SWT_CLASSPATH
 
 if [ ! -z "$JOGL_PROFILE" ] ; then
diff --git a/etc/test_dbg.sh b/etc/test_dbg.sh
index f7d0fd2..72b2b3f 100755
--- a/etc/test_dbg.sh
+++ b/etc/test_dbg.sh
@@ -12,7 +12,7 @@ echo LIBGL_DRIVERS_PATH: $LIBGL_DRIVERS_PATH 2>&1 | tee -a $logfile
 echo LIBGL_DEBUG: $LIBGL_DEBUG 2>&1 | tee -a $logfile
 echo java $X_ARGS $D_ARGS $* 2>&1 | tee -a $logfile
 
-CLASSPATH=jar/gluegen-rt.jar:jar/jogl.all.jar
+CLASSPATH=jar/gluegen-rt.jar:jar/jogl-all.jar
 export CLASSPATH
 
 echo CLASSPATH: $CLASSPATH
diff --git a/jnlp-files/jogl-applet-runner-newt-gears-gl3-napplet.html b/jnlp-files/jogl-applet-runner-newt-gears-gl3-napplet.html
index 13d8919..cb2375e 100644
--- a/jnlp-files/jogl-applet-runner-newt-gears-gl3-napplet.html
+++ b/jnlp-files/jogl-applet-runner-newt-gears-gl3-napplet.html
@@ -1,7 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 <html>
 <head>
-<title>JOGL NEWT Applet Runner - GearsES2 - GL3 Core - Normal Applet</title>
+<title>JOGL NEWT Applet Runner - GearsES2 - GL3 Core - (NApplet) </title>
 </head>
 <body  BGCOLOR="#ffffff">
 
diff --git a/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet.html b/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet.html
index 37473be..9b44839 100644
--- a/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet.html
+++ b/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet.html
@@ -1,7 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 <html>
 <head>
-<title>JOGL NEWT Applet Runner - GearsES2 - normal - Normal Applet</title>
+<title>JOGL NEWT Applet Runner - GearsES2 - normal - (NApplet) </title>
 </head>
 <body  BGCOLOR="#ffffff">
 
diff --git a/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet2.html b/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet2.html
index 63df4ed..8970aea 100644
--- a/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet2.html
+++ b/jnlp-files/jogl-applet-runner-newt-gears-normal-napplet2.html
@@ -1,7 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 <html>
 <head>
-<title>JOGL NEWT Applet Runner - GearsES2 - normal - Normal Applet - Closeable</title>
+<title>JOGL NEWT Applet Runner - GearsES2 - normal - (NApplet)  - Closeable</title>
 </head>
 <body  BGCOLOR="#ffffff">
 
diff --git a/make/build-common.xml b/make/build-common.xml
index a718ae0..2061d55 100644
--- a/make/build-common.xml
+++ b/make/build-common.xml
@@ -19,6 +19,9 @@
     <import file="${gluegen.root}/make/jogamp-androidtasks.xml" />
     <import file="${gluegen.root}/make/jogamp-env.xml" />
 
+    <!-- Add JOAL (optional) -->
+    <property name="joal.root" value="../../joal" />
+
     <property name="ant-contrib.jar"  value="${gluegen.root}/make/lib/ant-contrib-1.0b3.jar" />
 
     <condition property="rootrel.build" value="build">
@@ -27,8 +30,6 @@
       </not>
     </condition>
 
-    <import file="versions.xml" />
-
     <!-- ================================================================== -->
     <!-- 
        - Base initialization of properties and detection of operating system.
@@ -63,10 +64,6 @@
         <property name="stub.includes.gluegen.gg"  value="${gluegen.root}/make/stub_includes/gluegen" />
         <property name="stub.includes.gluegen.cc"  value="${gluegen.root}/make/stub_includes/platform" />
 
-        <tstamp>
-             <format property="version.timestamp" pattern="yyyyMMdd"/>
-        </tstamp>
-
         <property name="jogl.build.number" value="manual"/>
         <property name="jogl.build.id"     value="${version.timestamp}"/>
         <mkdir dir="${tempdir}" />
@@ -85,10 +82,7 @@
         </exec>
         <property name="jogl.build.commit" value="manual"/> <!-- fallback -->
 
-        <property name="nativewindow.version" value="${nativewindow_base_version}-b${jogl.build.number}-${version.timestamp}" />
-        <property name="jogl.version"         value="${jogl_base_version}-b${jogl.build.number}-${version.timestamp}" />
-        <property name="newt.version"         value="${newt_base_version}-b${jogl.build.number}-${version.timestamp}" />
-        <property name="jogl.version.plus"    value="${jogl_base_version}-${jogl.build.branch}-b${jogl.build.number}-${version.timestamp}" />
+        <property name="jogl.version"         value="${jogamp.version.base}-b${jogl.build.number}-${version.timestamp}" />
 
         <property name="archive.name"         value="jogl-${jogl.version}-${os.and.arch}" />
         <property name="archive"              value="${build}/${archive.name}" />
@@ -211,6 +205,8 @@
         <property name="ant.jar"                    value="${ant.home}/lib/ant.jar" />
         <property name="ant-junit.jar"              value="${ant.home}/lib/ant-junit.jar" />
 
+        <property name="build.joal"                 value="${joal.root}/${rootrel.build}" /> <!-- optional -->
+
         <property name="nativewindow.make"          value="." />
         <property name="nativewindow.build.xml"     value="${nativewindow.make}/build-nativewindow.xml" />
         <property name="build.nativewindow"         value="${build}/nativewindow" />
@@ -279,8 +275,6 @@
         <property name="jogl-glmobile-dbg.jar"          value="${build.jogl}/jogl-glmobile-dbg.jar" />
         <property name="jogl-util.jar"                  value="${build.jogl}/jogl-util.jar" />
         <property name="jogl-util-graph.jar"            value="${build.jogl}/jogl-util-graph.jar" />
-        <property name="jogl-glutess.jar"               value="${build.jogl}/jogl-glu-tess.jar" />
-        <property name="jogl-glumipmap.jar"             value="${build.jogl}/jogl-glu-mipmap.jar" />
         <property name="jogl-util-fixedfuncemu.jar"     value="${build.jogl}/jogl-util-fixedfuncemu.jar" />
         <property name="jogl-awt.jar"                   value="${build.jogl}/jogl-awt.jar" />
         <property name="jogl-swt.jar"                   value="${build.jogl}/jogl-swt.jar" />
@@ -291,6 +285,7 @@
         <property name="jogl-os-android.jar"            value="${build.jogl}/jogl-os-android.jar" />
         <property name="jogl-gldesktop.jar"             value="${build.jogl}/jogl-gldesktop.jar" />
         <property name="jogl-gldesktop-dbg.jar"         value="${build.jogl}/jogl-gldesktop-dbg.jar" />
+        <property name="jogl-glu.jar"                   value="${build.jogl}/jogl-glu.jar" />
         <property name="jogl-glu-gldesktop.jar"         value="${build.jogl}/jogl-glu-gldesktop.jar" />
         <property name="jogl-util-gldesktop.jar"        value="${build.jogl}/jogl-util-gldesktop.jar" />
         <property name="jogl-omx.jar"                   value="${build.jogl}/jogl-omx.jar" />
@@ -303,8 +298,6 @@
             <pathelement location="${jogl-glmobile-dbg.jar}" />
             <pathelement location="${jogl-util.jar}" />
             <pathelement location="${jogl-util-graph.jar}" />
-            <pathelement location="${jogl-glutess.jar}" />
-            <pathelement location="${jogl-glumipmap.jar}" />
             <pathelement location="${jogl-util-fixedfuncemu.jar}" />
             <pathelement location="${jogl-awt.jar}" />
             <pathelement location="${jogl-swt.jar}" />
@@ -314,6 +307,7 @@
             <pathelement location="${jogl-os-osx.jar}" />
             <pathelement location="${jogl-gldesktop.jar}" />
             <pathelement location="${jogl-gldesktop-dbg.jar}" />
+            <pathelement location="${jogl-glu.jar}" />
             <pathelement location="${jogl-glu-gldesktop.jar}" />
             <pathelement location="${jogl-util-gldesktop.jar}" />
             <pathelement location="${jogl-omx.jar}" />
@@ -325,14 +319,13 @@
             <pathelement location="${jogl-glmobile-dbg.jar}" />
             <pathelement location="${jogl-util.jar}" />
             <pathelement location="${jogl-util-graph.jar}" />
-            <pathelement location="${jogl-glutess.jar}" />
-            <pathelement location="${jogl-glumipmap.jar}" />
             <pathelement location="${jogl-util-fixedfuncemu.jar}" />
             <pathelement location="${jogl-os-x11.jar}" />
             <pathelement location="${jogl-os-win.jar}" />
             <pathelement location="${jogl-os-osx.jar}" />
             <pathelement location="${jogl-gldesktop.jar}" />
             <pathelement location="${jogl-gldesktop-dbg.jar}" />
+            <pathelement location="${jogl-glu.jar}" />
             <pathelement location="${jogl-glu-gldesktop.jar}" />
             <pathelement location="${jogl-util-gldesktop.jar}" />
             <pathelement location="${jogl-omx.jar}" />
@@ -343,8 +336,7 @@
             <pathelement location="${jogl-glmobile-dbg.jar}" />
             <pathelement location="${jogl-util.jar}" />
             <pathelement location="${jogl-util-graph.jar}" />
-            <pathelement location="${jogl-glutess.jar}" />
-            <pathelement location="${jogl-glumipmap.jar}" />
+            <pathelement location="${jogl-glu.jar}" />
             <pathelement location="${jogl-util-fixedfuncemu.jar}" />
             <pathelement location="${jogl-os-x11.jar}" />
             <pathelement location="${jogl-omx.jar}" />
@@ -355,14 +347,13 @@
             <pathelement location="${jogl-glmobile-dbg.jar}" />
             <pathelement location="${jogl-util.jar}" />
             <pathelement location="${jogl-util-graph.jar}" />
-            <pathelement location="${jogl-glutess.jar}" />
-            <pathelement location="${jogl-glumipmap.jar}" />
+            <pathelement location="${jogl-glu.jar}" />
             <pathelement location="${jogl-util-fixedfuncemu.jar}" />
             <pathelement location="${jogl-os-android.jar}" />
             <pathelement location="${jogl-omx.jar}" />
         </path>
         <!-- 
-            ${jogl-core.jar} ${jogl-glutess.jar} ${jogl-glumipmap.jar} ${jogl-glu-gldesktop.jar} ${jogl-os-x11.jar} ${jogl-os-win.jar} ${jogl-os-osx.jar} ${jogl-gldesktop.jar} ${jogl-gldesktop-dbg.jar} ${jogl-glmobile.jar} ${jogl-glmobile-dbg.jar} ${jogl-omx.jar} ${jogl-util.jar} ${jogl-util-graph.jar} ${jogl-util-gldesktop.jar} ${jogl-util-awt.jar} ${jogl-util-fixedfuncemu.jar} ${jogl-sdk.jar} -->
+            ${jogl-core.jar} ${jogl-glu.jar} ${jogl-glu-gldesktop.jar} ${jogl-os-x11.jar} ${jogl-os-win.jar} ${jogl-os-osx.jar} ${jogl-gldesktop.jar} ${jogl-gldesktop-dbg.jar} ${jogl-glmobile.jar} ${jogl-glmobile-dbg.jar} ${jogl-omx.jar} ${jogl-util.jar} ${jogl-util-graph.jar} ${jogl-util-gldesktop.jar} ${jogl-util-awt.jar} ${jogl-util-fixedfuncemu.jar} ${jogl-sdk.jar} -->
 
         <property name="newt-core.jar"                  value="${build.newt}/newt-core.jar" />
         <property name="newt-ogl.jar"                   value="${build.newt}/newt-ogl.jar" />
@@ -428,6 +419,14 @@
         <property name="jogl-all-android.jar"           value="${jar}/jogl-all-android.jar" />
         <property name="jogl-all-android.apk"           value="${jar}/jogl-all-android-${android.abi}.apk" />
 
+        <!-- JavaSE combinations . JOAL (optional) -->
+        <property name="joal.jar"                       value="${build.joal}/joal.jar" />
+        <condition property="joal-jars.available">
+            <available file="${joal.jar}"/>
+        </condition>
+        <echo message="joal-jars.available: ${joal-jars.available} ${joal.jar}" />
+
+        <!-- NativeWindow Compilation .. -->
         <path id="swt_gluegen.classpath">
             <pathelement location="${gluegen-rt.jar}" />
             <pathelement location="${swt.jar}" />
@@ -440,6 +439,13 @@
             <path refid="nativewindow_all_atoms.classpath" />
         </path>
 
+        <path id="nativewindow_gluegen_joal.classpath">
+            <pathelement location="${gluegen-rt.jar}" />
+            <pathelement location="${swt.jar}" />
+            <pathelement location="${joal.jar}" />
+            <path refid="nativewindow_all_atoms.classpath" />
+        </path>
+
         <path id="nativewindow_gluegen_android.classpath">
             <pathelement location="${android.jar}" />
             <pathelement location="${gluegen-rt-android.jar}" />
diff --git a/make/build-jogl.xml b/make/build-jogl.xml
index 3c6f0fc..9c017ed 100644
--- a/make/build-jogl.xml
+++ b/make/build-jogl.xml
@@ -88,9 +88,12 @@
         <property name="java.part.gluegen-gl-rt" 
                   value="com/jogamp/gluegen/runtime/opengl/*"/>
 
+        <property name="java.part.core.util"
+                  value="com/jogamp/opengl/util/* jogamp/opengl/util/* com/jogamp/opengl/util/glsl/* jogamp/opengl/util/glsl/* jogamp/opengl/shader/**"/>
+
         <property name="java.part.core" 
-                  value="${java.part.gluegen-gl-rt} javax/media/opengl/* javax/media/opengl/fixedfunc/* javax/media/opengl/glu/* javax/media/opengl/glu/gl2es1/* com/jogamp/opengl/* jogamp/opengl/* jogamp/opengl/glu/* jogamp/opengl/glu/error/* jogamp/opengl/shader/**"/>
-        <property name="java.part.core.exclude" value="javax/media/opengl/Debug* javax/media/opengl/Trace*"/>
+                  value="${java.part.gluegen-gl-rt} javax/media/opengl/* javax/media/opengl/fixedfunc/* com/jogamp/opengl/* com/jogamp/opengl/math/** jogamp/opengl/* ${java.part.core.util}"/>
+        <property name="java.part.core.exclude" value="javax/media/opengl/Debug* javax/media/opengl/Trace* com/jogamp/opengl/util/AWTAnimatorImpl*"/>
 
         <property name="java.part.nv-cg"
                   value="com/jogamp/opengl/cg com/jogamp/opengl/cg/* jogamp/opengl/cg/*"/>
@@ -98,13 +101,10 @@
         <property name="java.part.egl"
                   value="jogamp/opengl/egl/*"/>
 
-        <property name="java.part.glutess"
-                  value="jogamp/opengl/glu/tessellator/**"/>
-
-        <property name="java.part.glumipmap"
-                  value="jogamp/opengl/glu/mipmap/**"/>
+        <property name="java.part.glu"
+                  value="javax/media/opengl/glu/* javax/media/opengl/glu/gl2es1/* jogamp/opengl/glu/* jogamp/opengl/glu/error/* jogamp/opengl/glu/tessellator/** jogamp/opengl/glu/mipmap/**"/>
 
-        <property name="java.part.glugldesktop"
+        <property name="java.part.glu.gldesktop"
                   value="jogamp/opengl/glu/gl2/** jogamp/opengl/glu/nurbs/** jogamp/opengl/glu/registry/** javax/media/opengl/glu/gl2/**"/>
 
         <property name="java.part.openmax"
@@ -125,41 +125,44 @@
         <property name="java.part.android"
                   value="jogamp/opengl/android/**"/>
 
+        <property name="java.part.openal"
+                  value="jogamp/opengl/openal/**"/>
+
         <property name="java.part.gldesktop"
                   value="jogamp/opengl/**/gl2/** jogamp/opengl/**/gl3/** jogamp/opengl/**/gl4/**"/>
 
         <property name="java.part.gldesktop.dbg"
-                  value="javax/media/opengl/TraceGL2.* javax/media/opengl/DebugGL2.* javax/media/opengl/TraceGL2GL3.* javax/media/opengl/DebugGL2GL3.* javax/media/opengl/TraceGL3.* javax/media/opengl/DebugGL3.* javax/media/opengl/TraceGL3bc.* javax/media/opengl/DebugGL3bc.* javax/media/opengl/TraceGL4.* javax/media/opengl/DebugGL4.* javax/media/opengl/TraceGL4bc.* javax/media/opengl/DebugGL4bc.*"/>
+                  value="javax/media/opengl/TraceGL2.* javax/media/opengl/DebugGL2.* javax/media/opengl/TraceGL3.* javax/media/opengl/DebugGL3.* javax/media/opengl/TraceGL3bc.* javax/media/opengl/DebugGL3bc.* javax/media/opengl/TraceGL4.* javax/media/opengl/DebugGL4.* javax/media/opengl/TraceGL4bc.* javax/media/opengl/DebugGL4bc.*"/>
 
         <property name="java.part.es1"
                   value="javax/media/opengl/**/es1/** com/jogamp/opengl/**/es1/** jogamp/opengl/**/es1/**"/>
 
         <property name="java.part.es1.dbg"
-                  value="javax/media/opengl/TraceGLES1.* javax/media/opengl/DebugGLES1.* javax/media/opengl/TraceGL2ES1.* javax/media/opengl/DebugGL2ES1.*"/>
+                  value="javax/media/opengl/TraceGLES1.* javax/media/opengl/DebugGLES1.*"/>
 
         <property name="java.part.es2"
                   value="javax/media/opengl/**/es2/** com/jogamp/opengl/**/es2/** jogamp/opengl/**/es2/**"/>
 
         <property name="java.part.es2.dbg"
-                  value="javax/media/opengl/TraceGLES2.* javax/media/opengl/DebugGLES2.* javax/media/opengl/TraceGL2ES2.* javax/media/opengl/DebugGL2ES2.*"/>
+                  value="javax/media/opengl/TraceGLES2.* javax/media/opengl/DebugGLES2.*"/>
 
         <property name="java.part.awt"
-                  value="javax/media/opengl/awt/** jogamp/opengl/**/awt/**"/>
+                  value="javax/media/opengl/awt/** jogamp/opengl/**/awt/** com/jogamp/opengl/util/AWTAnimatorImpl*"/>
         
         <property name="java.part.swt"
                   value="com/jogamp/opengl/**/swt/**"/>
 
         <property name="java.part.util"
-                  value="com/jogamp/opengl/util/* com/jogamp/opengl/util/texture/** com/jogamp/opengl/util/av/* com/jogamp/opengl/util/packrect/** jogamp/opengl/util/* jogamp/opengl/util/av/** jogamp/opengl/util/pngj/**"/>
+                  value="com/jogamp/opengl/util/texture/** com/jogamp/opengl/util/av/* com/jogamp/opengl/util/packrect/** jogamp/opengl/util/av/** jogamp/opengl/util/jpeg/** jogamp/opengl/util/pngj/**"/>
 
         <property name="java.part.util.awt"
-                  value="com/jogamp/opengl/util/**/awt/** com/jogamp/opengl/util/AWTAnimatorImpl*"/>
+                  value="com/jogamp/opengl/util/**/awt/**"/>
 
         <property name="java.part.util.gldesktop"
                   value="com/jogamp/opengl/util/**/gl2/**"/>
 
         <property name="java.part.util.glsl"
-                  value="com/jogamp/opengl/util/glsl/* com/jogamp/opengl/util/glsl/fixedfunc/* jogamp/opengl/util/glsl/*"/>
+                  value="com/jogamp/opengl/util/glsl/fixedfunc/*"/>
 
         <property name="java.part.util.graph"
                   value="com/jogamp/graph/** jogamp/graph/**"/>
@@ -183,7 +186,7 @@
                   value="${java.part.core.shadercode} ${java.part.util.fixedfuncemu.shadercode} ${java.part.util.graph.shadercode} ${java.part.util.graph.fonts}"/>
 
         <property name="java.part.all-desktop" 
-                  value="${java.part.sdk} ${java.part.glx} ${java.part.wgl} ${java.part.cgl} ${java.part.gldesktop} ${java.part.glugldesktop} ${java.part.util.gldesktop}"/>
+                  value="${java.part.sdk} ${java.part.glx} ${java.part.wgl} ${java.part.cgl} ${java.part.gldesktop} ${java.part.glu.gldesktop} ${java.part.util.gldesktop}"/>
 
         <!-- condition excludes -->
 
@@ -224,8 +227,9 @@
         <property name="rootrel.generated.c.cg"   value="${rootrel.src.generated}/native/jogl_cg" />
 
         <!-- The source directories. -->
-        <property name="src.java" value="${project.root}/${rootrel.src.java}" />
-        <property name="src.c"    value="${project.root}/${rootrel.src.c}" />
+        <property name="src.java"            value="${project.root}/${rootrel.src.java}" />
+        <property name="src.c"               value="${project.root}/${rootrel.src.c}" />
+        <property name="nativewindow.src.c"  value="${project.root}/src/nativewindow/native" />
         
         <!-- The generated source directories. -->
         <property name="src.generated"            value="${build.jogl}/gensrc" />
@@ -297,7 +301,7 @@
         <property name="javadoc" value="${project.root}/javadoc_jogl_public" />
         <property name="javadoc.spec" value="${project.root}/javadoc_jogl_spec" />
         <property name="javadoc.dev" value="${project.root}/javadoc_jogl_dev" />
-        <property name="javadoc.windowtitle" value="JOGL API -- JSR-231 ${jogl_base_version} Specification" />
+        <property name="javadoc.windowtitle" value="JOGL API -- JSR-231 ${jogamp.version.base} Specification" />
         <property name="javadoc.overview" value="doc/jogl/spec-overview.html" />
         <property name="javadoc.spec.packagenames" value="javax.media.opengl.*" />
 
@@ -472,7 +476,7 @@
     </target>
 
     <target name="java.generate.gl2">
-        <echo message="Generating GL2 interface and implementation" />
+        <echo message="Generating GL2 interface" />
         <antcall target="java.generate.copy2temp" inheritRefs="true" />
         <gluegen src="${stub.includes.opengl}/gl2.c" 
                  outputRootDir="${build.jogl}"
@@ -485,7 +489,7 @@
     </target>
 
     <target name="java.generate.gl3">
-        <echo message="Generating GL3 interface and implementation" />
+        <echo message="Generating GL3 interface" />
         <antcall target="java.generate.copy2temp" inheritRefs="true" />
         <gluegen src="${stub.includes.opengl}/gl3.c" 
                  outputRootDir="${build.jogl}"
@@ -498,7 +502,7 @@
     </target>
 
     <target name="java.generate.gl3bc">
-        <echo message="Generating GL3bc implementation" />
+        <echo message="Generating GL3bc interface" />
         <antcall target="java.generate.copy2temp" inheritRefs="true" />
         <gluegen src="${stub.includes.opengl}/gl3bc.c" 
                  outputRootDir="${build.jogl}"
@@ -511,7 +515,7 @@
     </target>
 
     <target name="java.generate.gl4">
-        <echo message="Generating GL4 interface and implementation" />
+        <echo message="Generating GL4 interface" />
         <antcall target="java.generate.copy2temp" inheritRefs="true" />
         <gluegen src="${stub.includes.opengl}/gl4.c" 
                  outputRootDir="${build.jogl}"
@@ -922,11 +926,6 @@
             <arg value="${src.generated.java}/javax/media/opengl" />
             <classpath refid="pipeline.classpath" />
         </java>
-        <java classname="com.jogamp.gluegen.opengl.BuildComposablePipeline" fork="yes" failonerror="true">
-            <arg value="javax.media.opengl.GL2ES1" />
-            <arg value="${src.generated.java}/javax/media/opengl" />
-            <classpath refid="pipeline.classpath" />
-        </java>
     </target>          
 
     <target name="java.generate.composable.pipeline.es2" depends="java.generate.composable.pipeline.check.es2" unless="java.generate.composable.pipeline.skip.es2">
@@ -935,11 +934,6 @@
             <arg value="${src.generated.java}/javax/media/opengl" />
             <classpath refid="pipeline.classpath" />
         </java>
-        <java classname="com.jogamp.gluegen.opengl.BuildComposablePipeline" fork="yes" failonerror="true">
-            <arg value="javax.media.opengl.GL2ES2" />
-            <arg value="${src.generated.java}/javax/media/opengl" />
-            <classpath refid="pipeline.classpath" />
-        </java>
     </target>          
 
     <target name="java.generate.composable.pipeline.gl2" depends="java.generate.composable.pipeline.check.gl2" unless="java.generate.composable.pipeline.skip.gl2">
@@ -948,11 +942,6 @@
             <arg value="${src.generated.java}/javax/media/opengl" />
             <classpath refid="pipeline.classpath" />
         </java>
-        <java classname="com.jogamp.gluegen.opengl.BuildComposablePipeline" fork="yes" failonerror="true">
-            <arg value="javax.media.opengl.GL2GL3" />
-            <arg value="${src.generated.java}/javax/media/opengl" />
-            <classpath refid="pipeline.classpath" />
-        </java>
     </target>          
 
     <target name="java.generate.composable.pipeline.gl3" depends="java.generate.composable.pipeline.check.gl3" unless="java.generate.composable.pipeline.skip.gl3">
@@ -1039,10 +1028,28 @@
         </javac>
     </target>
 
+    <target name="java.compile.secondpass.openal" if="joal-jars.available">
+        <!-- Perform the second pass Java compile; everything except portion of fixed function emulation depending on generated code. -->
+        <javac destdir="${classes}"
+               includes="${java.part.openal}"
+               fork="yes"
+               includeAntRuntime="false"
+               memoryMaximumSize="${javac.memorymax}"
+               encoding="UTF-8"
+               source="${target.sourcelevel}" 
+               target="${target.targetlevel}" 
+               bootclasspath="${target.rt.jar}"
+               debug="${javacdebug}" debuglevel="${javacdebuglevel}">
+            <classpath refid="nativewindow_gluegen_joal.classpath"/>
+            <src path="${src.java}" />
+            <src path="${src.generated.java}" />
+        </javac>
+    </target>
+
     <target name="java.compile.secondpass.javase">
         <!-- Perform the second pass Java compile; everything except portion of fixed function emulation depending on generated code. -->
         <javac destdir="${classes}"
-               excludes="com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java,${java.excludes.all},${java.part.android}"
+               excludes="com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java,${java.excludes.all},${java.part.android},${java.part.openal}"
                fork="yes"
                includeAntRuntime="false"
                memoryMaximumSize="${javac.memorymax}"
@@ -1076,12 +1083,12 @@
     </target>
 
         <!-- Perform the second pass Java compile; everything except portion of fixed function emulation depending on generated code. -->
-    <target name="java.compile.secondpass" depends="java.generate.composable.pipeline, java.compile.secondpass.javase, java.compile.secondpass.android" />
+    <target name="java.compile.secondpass" depends="java.generate.composable.pipeline, java.compile.secondpass.openal, java.compile.secondpass.javase, java.compile.secondpass.android" />
 
     <target name="java.compile.thirdpass.javase">
         <!-- Perform the third pass Java compile; everything including fixed function emulation. -->
         <javac destdir="${classes}"
-               excludes="${java.excludes.all},${java.part.android}"
+               excludes="${java.excludes.all},${java.part.android},${java.part.openal}"
                fork="yes"
                includeAntRuntime="false"
                memoryMaximumSize="${javac.memorymax}"
@@ -1454,12 +1461,13 @@
       
                 <!-- This is for the generated headers for handwritten C code -->
                 <includepath path="${src.c}"/>
+                <includepath path="${nativewindow.src.c}/macosx" if="isOSX"/>
                 <includepath path="${src.generated.c}" />
-                <includepath path="${src.generated.c}/X11" if="isX11"/>
-                <includepath path="${src.generated.c}/MacOSX" if="isOSX"/>
-                <includepath path="${src.generated.c}/Windows" if="isWindows"/>
+                <includepath path="${src.generated.c}/X11"       if="isX11"/>
+                <includepath path="${src.generated.c}/MacOSX"    if="isOSX"/>
+                <includepath path="${src.generated.c}/Windows"   if="isWindows"/>
                 <includepath path="${src.generated.c.libav}" />
-                <includepath path="${src.generated.c.openmax}" if="setup.addNativeOpenMAX"/>
+                <includepath path="${src.generated.c.openmax}"   if="setup.addNativeOpenMAX"/>
       
                 <!-- This must come last to not override real include paths -->
                 <!-- includepath path="stub_includes/macosx" if="isOSX" / -->
@@ -1564,10 +1572,12 @@
             tofile="${build.jogl}/manifest.mf"
             overwrite="true">
             <filterset>
-                <filter token="VERSION" value="${jogl.version}"/>
+                <filter token="VERSION" value="${jogamp.version}"/>
+                <filter token="BUILD_VERSION" value="${jogl.version}"/>
                 <filter token="SCM_BRANCH" value="${jogl.build.branch}"/>
                 <filter token="SCM_COMMIT" value="${jogl.build.commit}"/>
-                <filter token="BASEVERSION" value="${jogl_base_version}"/>
+                <filter token="BASEVERSION" value="${jogamp.version.base}"/>
+                <filter token="JAR_CODEBASE_TAG" value="${jogamp.jar.codebase}"/>
             </filterset>
         </copy>
     </target>
@@ -1625,7 +1635,7 @@
         <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-gldesktop.jar}" filesonly="true">
             <fileset dir="${classes}"
                      includes="${java.part.gldesktop}"
-                     excludes="${java.part.gldesktop.dbg} ${java.part.glugldesktop}"/>
+                     excludes="${java.part.gldesktop.dbg} ${java.part.glu.gldesktop}"/>
         </jar>
 
         <!-- misc -->
@@ -1635,7 +1645,7 @@
         </jar>
         <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-glu-gldesktop.jar}" filesonly="true">
             <fileset dir="${classes}"
-                     includes="${java.part.glugldesktop}"/>
+                     includes="${java.part.glu.gldesktop}"/>
         </jar>
         <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-util-gldesktop.jar}" filesonly="true">
             <fileset dir="${classes}"
@@ -1655,17 +1665,13 @@
             <fileset dir="${classes}"
                      includes="${java.part.sdk}"/>
         </jar>
-        <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-glutess.jar}" filesonly="true">
-            <fileset dir="${classes}"
-                     includes="${java.part.glutess}"/>
-        </jar>
-        <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-glumipmap.jar}" filesonly="true">
+        <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-glu.jar}" filesonly="true">
             <fileset dir="${classes}"
-                     includes="${java.part.glumipmap}"/>
+                     includes="${java.part.glu}"/>
         </jar>
         <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-util.jar}" filesonly="true">
             <fileset dir="${classes}"
-                     includes="${java.part.util} ${java.part.util.glsl}"
+                     includes="${java.part.util} ${java.part.util.glsl} ${java.part.openal}"
                      excludes="${java.part.util.awt} ${java.part.util.gldesktop} ${java.part.util.fixedfuncemu} ${java.part.util.graph}"/>
             <fileset dir="resources/assets" includes="jogl/util/**" />
         </jar>
diff --git a/make/build-nativewindow.xml b/make/build-nativewindow.xml
index 3c97d9d..49ef78b 100644
--- a/make/build-nativewindow.xml
+++ b/make/build-nativewindow.xml
@@ -149,7 +149,7 @@
         <property name="javadoc" value="${project.root}/javadoc_nativewindow_public" />
         <property name="javadoc.spec" value="${project.root}/javadoc_nativewindow_spec" />
         <property name="javadoc.dev" value="${project.root}/javadoc_nativewindow_dev" />
-        <property name="javadoc.windowtitle" value="Native Windowing Interface (NativeWindow) API -- ${nativewindow_base_version} Specification" />
+        <property name="javadoc.windowtitle" value="Native Windowing Interface (NativeWindow) API -- ${jogamp.version.base} Specification" />
         <property name="javadoc.overview" value="../src/nativewindow/classes/javax/media/nativewindow/package.html" />
         <property name="javadoc.spec.packagenames" value="javax.media.nativewindow.*" />
 
@@ -361,7 +361,6 @@
       </compiler>
 
       <compiler id="compiler.cfg.macosx.nativewindow" extends="compiler.cfg.macosx">
-        <compilerarg value="-I${java.osx.frameworks.dir}/JavaNativeFoundation.framework/Headers" />
       </compiler>
 
       <!-- linker configuration -->
@@ -446,9 +445,6 @@
         <linkerarg value="QuartzCore" />
         <linkerarg value="-weak_framework" />
         <linkerarg value="Cocoa" />
-        <linkerarg value="-weak_framework" />
-        <linkerarg value="JavaNativeFoundation" />
-        <linkerarg value="-F${java.osx.frameworks.dir}" />
       </linker>
 
       <linker id="linker.cfg.hpux.nativewindow" extends="linker.cfg.hpux">
@@ -695,8 +691,9 @@
                 <includepath path="${src.generated.c}/X11"     if="isX11"/>
                 <includepath path="${src.generated.c}/MacOSX"  if="isOSX"/>
                 <includepath path="${src.generated.c}/Windows" if="isWindows"/>
-                <includepath path="${src.c}/win32"             if="isWindows"/>
                 <includepath path="${src.c}/x11"               if="isX11"/>
+                <includepath path="${src.c}/macosx"            if="isOSX"/>
+                <includepath path="${src.c}/win32"             if="isWindows"/>
                 <includepath path="${src.c}"/>
       
                 <!-- This must come last to not override real include paths -->
@@ -735,20 +732,6 @@
       </sequential>
     </macrodef>  
 
-    <target name="c.fixup.jawt.version.macosx" if="isOSX" unless="setup.noNativeAWT">
-      <!-- Edit the link to the JAWT version in the resulting jnilib
-           file; this isn't strictly needed but seems to allow the
-           universal binaries to work on 10.3 machines as well, which
-           is desirable for some end users -->
-      <apply executable="install_name_tool">
-        <arg value="-change" />
-        <arg value="/System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Libraries/libjawt.dylib" />
-        <arg value="/System/Library/Frameworks/JavaVM.framework/Libraries/libjawt.dylib" />
-        <srcfile />
-        <fileset dir="${obj.nativewindow}" includes="libnativewindow_awt.jnilib" />
-      </apply>
-    </target>
-
     <target name="c.build.nativewindow.awt" unless="setup.noNativeAWT">
       <c.build c.compiler.src.files="c.src.files.awt"
                c.compiler.use-jawt="true"
@@ -796,7 +779,6 @@
     </target>
 
     <target name="c.build.nativewindow" depends="c.configure,c.build.nativewindow.windowlib,c.build.nativewindow.awt">
-      <antcall target="c.fixup.jawt.version.macosx" inheritrefs="true" />
       <antcall target="c.manifest" inheritRefs="true" />
     </target>
 
@@ -812,10 +794,12 @@
           tofile="${build.nativewindow}/manifest.mf"
           overwrite="true">
           <filterset>
-              <filter token="VERSION" value="${nativewindow.version}"/>
+              <filter token="VERSION" value="${jogamp.version}"/>
+              <filter token="BUILD_VERSION" value="${jogl.version}"/>
               <filter token="SCM_BRANCH" value="${jogl.build.branch}"/>
               <filter token="SCM_COMMIT" value="${jogl.build.commit}"/>
-              <filter token="BASEVERSION" value="${nativewindow_base_version}"/>
+              <filter token="BASEVERSION" value="${jogamp.version.base}"/>
+              <filter token="JAR_CODEBASE_TAG" value="${jogamp.jar.codebase}"/>
           </filterset>
         </copy>
     </target>
@@ -952,7 +936,7 @@
 
     <target name="generate.version.txt" depends="init">
         <!-- Create a version.txt file indicating which version we just built -->
-        <echo message="${nativewindow.version}" file="${build.nativewindow}/version.txt" />
+        <echo message="${jogl.version}" file="${build.nativewindow}/version.txt" />
     </target>
 
 </project>
diff --git a/make/build-newt.xml b/make/build-newt.xml
index 7b9a518..94a448d 100644
--- a/make/build-newt.xml
+++ b/make/build-newt.xml
@@ -112,7 +112,7 @@
                   value="com/jogamp/newt/awt/** com/jogamp/newt/event/awt/** jogamp/newt/awt/** ${java.part.driver.awt}"/>
 
         <property name="java.part.swt"
-                  value="com/jogamp/newt/swt/**"/>
+                  value="com/jogamp/newt/swt/** jogamp/newt/swt/**"/>
 
         <property name="java.part.driver.linux"
                   value="jogamp/newt/driver/linux/**"/>
@@ -188,7 +188,7 @@
         <property name="javadoc" value="${project.root}/javadoc_newt_public" />
         <property name="javadoc.spec" value="${project.root}/javadoc_newt_spec" />
         <property name="javadoc.dev" value="${project.root}/javadoc_newt_dev" />
-        <property name="javadoc.windowtitle" value="NEWT API -- ${newt_base_version} Specification" />
+        <property name="javadoc.windowtitle" value="NEWT API -- ${jogamp.version.base} Specification" />
         <property name="javadoc.overview" value="spec-overview.html" />
         <property name="javadoc.spec.packagenames" value="com.jogamp.newt, com.jogamp.newt.event, com.jogamp.newt.opengl, com.jogamp.newt.util" />
 
@@ -364,6 +364,8 @@
         <linkerarg value="-weak_framework" />
         <linkerarg value="AppKit" />
         <linkerarg value="-weak_framework" />
+        <linkerarg value="Carbon" />
+        <linkerarg value="-weak_framework" />
         <linkerarg value="Cocoa" />
       </linker>
 
@@ -582,18 +584,21 @@
         <patternset id="c.src.files.newt">
           <include name="${rootrel.src.c}/NewtCommon.c" />
           <!-- include name="${rootrel.src.c}/timespec.c"   /--> <!-- currently used for X11 and OSX with special PERF DEBUG MODE-->
-          <include name="${rootrel.src.c}/WindowsWindow.c" if="isWindows"/>
-          <include name="${rootrel.src.c}/*.m"             if="isOSX"/>
-          <include name="${rootrel.src.c}/AndroidWindow.c" if="isAndroid"/>
-          <include name="${rootrel.src.c}/X11Display.c"    if="isX11"/>
+          <include name="${rootrel.src.c}/WindowsWindow.c"    if="isWindows"/>
+          <include name="${rootrel.src.c}/MacWindow.m"        if="isOSX"/>
+          <include name="${rootrel.src.c}/NewtMacWindow.m"    if="isOSX"/>
+          <include name="${rootrel.src.c}/AndroidWindow.c"    if="isAndroid"/>
+          <include name="${rootrel.src.c}/X11Display.c"       if="isX11"/>
           <!-- include name="${rootrel.src.c}/X11Event.c"      if="isX11"/-->
           <!-- include name="${rootrel.src.c}/XCBEvent.c"      if="isX11"/-->
-          <include name="${rootrel.src.c}/X11Screen.c"     if="isX11"/>
-          <include name="${rootrel.src.c}/X11Window.c"     if="isX11"/>
-          <include name="${rootrel.src.c}/KDWindow.c"      if="setup.addNativeKD"/>
-          <include name="${rootrel.src.c}/IntelGDL.c"      if="setup.addNativeIntelGDL"/>
-          <include name="${rootrel.src.c}/bcm_egl.c"       if="setup.addNativeBroadcom"/>
-          <include name="${rootrel.src.c}/bcm_vc_iv.c"     if="setup.addNativeBroadcom"/>
+          <include name="${rootrel.src.c}/X11Screen.c"        if="isX11"/>
+          <include name="${rootrel.src.c}/X11RandR11.c"       if="isX11"/>
+          <include name="${rootrel.src.c}/X11RandR13.c"       if="isX11"/>
+          <include name="${rootrel.src.c}/X11Window.c"        if="isX11"/>
+          <include name="${rootrel.src.c}/KDWindow.c"         if="setup.addNativeKD"/>
+          <include name="${rootrel.src.c}/IntelGDL.c"         if="setup.addNativeIntelGDL"/>
+          <include name="${rootrel.src.c}/bcm_egl.c"          if="setup.addNativeBroadcom"/>
+          <include name="${rootrel.src.c}/bcm_vc_iv.c"        if="setup.addNativeBroadcom"/>
         </patternset>
 
         <echo message="Compiling @{output.lib.name}" />
@@ -697,6 +702,8 @@
       <javah destdir="${src.generated.c}/MacOSX"      classpath="${javah.classpath}" class="jogamp.newt.driver.macosx.DisplayDriver" />
       <javah destdir="${src.generated.c}/X11"         classpath="${javah.classpath}" class="jogamp.newt.driver.x11.WindowDriver" />
       <javah destdir="${src.generated.c}/X11"         classpath="${javah.classpath}" class="jogamp.newt.driver.x11.ScreenDriver" />
+      <javah destdir="${src.generated.c}/X11"         classpath="${javah.classpath}" class="jogamp.newt.driver.x11.RandR11" />
+      <javah destdir="${src.generated.c}/X11"         classpath="${javah.classpath}" class="jogamp.newt.driver.x11.RandR13" />
       <javah destdir="${src.generated.c}/X11"         classpath="${javah.classpath}" class="jogamp.newt.driver.x11.DisplayDriver" />
     </target>
 
@@ -733,10 +740,12 @@
           tofile="${build.newt}/manifest.mf"
           overwrite="true">
           <filterset>
-              <filter token="VERSION" value="${newt.version}"/>
+              <filter token="VERSION" value="${jogamp.version}"/>
+              <filter token="BUILD_VERSION" value="${jogl.version}"/>
               <filter token="SCM_BRANCH" value="${jogl.build.branch}"/>
               <filter token="SCM_COMMIT" value="${jogl.build.commit}"/>
-              <filter token="BASEVERSION" value="${newt_base_version}"/>
+              <filter token="BASEVERSION" value="${jogamp.version.base}"/>
+              <filter token="JAR_CODEBASE_TAG" value="${jogamp.jar.codebase}"/>
           </filterset>
         </copy>
     </target>
@@ -907,7 +916,7 @@
 
     <target name="generate.version.txt" depends="init">
         <!-- Create a version.txt file indicating which version we just built -->
-        <echo message="${newt.version}" file="${build.newt}/version.txt" />
+        <echo message="${jogl.version}" file="${build.newt}/version.txt" />
     </target>
 
 </project>
diff --git a/make/build-test.xml b/make/build-test.xml
index 3402b4d..e00348c 100644
--- a/make/build-test.xml
+++ b/make/build-test.xml
@@ -78,10 +78,11 @@
             tofile="${build.test}/manifest-test.mf"
             overwrite="true">
             <filterset>
-                <filter token="VERSION" value="${jogl.version}"/>
+                <filter token="VERSION" value="${jogamp.version}"/>
+                <filter token="BUILD_VERSION" value="${jogl.version}"/>
                 <filter token="SCM_BRANCH" value="${jogl.build.branch}"/>
                 <filter token="SCM_COMMIT" value="${jogl.build.commit}"/>
-                <filter token="BASEVERSION" value="${jogl_base_version}"/>
+                <filter token="BASEVERSION" value="${jogamp.version.base}"/>
             </filterset>
         </copy>
 
@@ -114,10 +115,11 @@
             tofile="${build.test}/manifest-test-android.mf"
             overwrite="true">
             <filterset>
-                <filter token="VERSION" value="${jogl.version}"/>
+                <filter token="VERSION" value="${jogamp.version}"/>
+                <filter token="BUILD_VERSION" value="${jogl.version}"/>
                 <filter token="SCM_BRANCH" value="${jogl.build.branch}"/>
                 <filter token="SCM_COMMIT" value="${jogl.build.commit}"/>
-                <filter token="BASEVERSION" value="${jogl_base_version}"/>
+                <filter token="BASEVERSION" value="${jogamp.version.base}"/>
             </filterset>
         </copy>
 
@@ -142,8 +144,8 @@
             androidmanifest.path="resources/android/AndroidManifest-test.xml"
             androidresources.path="resources/android/res-test"
             jarmanifest.path="${build.test}/manifest-test-android.mf"
-            version.code="${jogl_int_version}"
-            version.name="${jogl.version.plus}" />
+            version.code="${jogamp.version.int}"
+            version.name="${jogamp.version}" />
     </target>
 
     <target name="test.compile.check" depends="declare.common">
@@ -196,7 +198,7 @@
             </pathconvert>
             <var name="test.class.result.file" value="${results.test}/TEST-${test.class.fqn}.log"/>
             <echo message="Testing ${test.class.fqn} -- ${test.class.result.file}"/>
-            <apply dir="." executable="${java.home}/bin/java" 
+            <apply dir="." executable="${jvmJava.exe}"
                  parallel="false" 
                  timeout="${batchtest.timeout}"
                  vmlauncher="false"
@@ -225,7 +227,7 @@
 
     <target name="junit.run.noui" depends="test.compile">
         <!-- Test*NOUI* -->
-        <junit forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
+        <junit jvm="${jvmJava.exe}" forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
             <env key="${system.env.library.path}" path="${obj.all.paths}"/>
             <jvmarg value="${junit.run.arg0}"/>
             <jvmarg value="${junit.run.arg1}"/>
@@ -271,6 +273,8 @@
             <fileset dir="${classes}">
                 <include name="${java.dir.junit}/**/Test*NEWT*"/>
                 <exclude name="**/*$$*"/>
+                <exclude name="**/*AWT*"/>
+                <exclude name="**/*SWT*"/>
             </fileset>
           <sequential>
             <var name="test.class.path" unset="true"/>
@@ -285,7 +289,7 @@
             </pathconvert>
             <var name="test.class.result.file" value="${results.test}/TEST-${test.class.fqn}.xml"/>
             <echo message="Testing ${test.class.fqn} -- ${test.class.result.file}"/>
-            <apply dir="." executable="${java.home}/bin/java" 
+            <apply dir="." executable="${jvmJava.exe}"
                  parallel="false" 
                  timeout="${batchtest.timeout}"
                  vmlauncher="false"
@@ -298,6 +302,7 @@
                 <arg line="${jvmDataModel.arg}"/>
                 <arg value="-Djava.library.path=${obj.all.paths}"/>
                 <arg line="${jvmarg.headless}"/>
+                <arg line="${jvmarg.mainthrd}"/>
                 <!--
                 <arg line="-Dnewt.debug.EDT"/>
                 -->
@@ -328,7 +333,7 @@
       -->
     <target name="junit.run.newt" depends="test.compile">
         <!-- Test*NEWT* -->
-        <junit forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
+        <junit jvm="${jvmJava.exe}" forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
             <env key="${system.env.library.path}" path="${obj.all.paths}"/>
             <jvmarg value="${junit.run.arg0}"/>
             <jvmarg value="${junit.run.arg1}"/>
@@ -356,6 +361,8 @@
               <fileset dir="${classes}">
                   <include name="${java.dir.junit}/**/Test*NEWT*"/>
                   <exclude name="**/*$$*"/>
+                  <exclude name="**/*AWT*"/>
+                  <exclude name="**/*SWT*"/>
               </fileset>
               <formatter usefile="false" type="brief"/>
               <formatter usefile="true" type="xml"/>
@@ -365,7 +372,7 @@
 
     <target name="junit.run.awt" depends="test.compile">
         <!-- Test*AWT* -->
-        <junit forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
+        <junit jvm="${jvmJava.exe}" forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
             <env key="${system.env.library.path}" path="${obj.all.paths}"/>
             <jvmarg value="${junit.run.arg0}"/>
             <jvmarg value="${junit.run.arg1}"/>
@@ -400,9 +407,86 @@
         </junit>
     </target>
 
+    <target name="junit.run.newt.awt" depends="test.compile">
+        <!-- Test*AWT* -->
+        <junit jvm="${jvmJava.exe}" forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
+            <env key="${system.env.library.path}" path="${obj.all.paths}"/>
+            <jvmarg value="${junit.run.arg0}"/>
+            <jvmarg value="${junit.run.arg1}"/>
+            <jvmarg value="${jvmDataModel.arg}"/>
+            <jvmarg value="-Djava.library.path=${obj.all.paths}"/>
+
+            <!--
+            <jvmarg value="-Dnewt.debug.EDT"/>
+            <jvmarg value="-Djogl.debug=all"/>
+            <jvmarg value="-Dgluegen.debug.NativeLibrary=true"/>
+            <jvmarg value="-Dgluegen.debug.ProcAddressHelper=true"/>
+            <jvmarg value="-Djogl.debug.GLSLState"/>
+            <jvmarg value="-Dnativewindow.debug=all"/>
+            <jvmarg value="-Dnewt.debug=all"/>
+            <jvmarg value="-verbose:jni"/> 
+            <jvmarg value="-client"/>
+            <jvmarg value="-d32"/>
+            -->
+
+            <formatter usefile="false" type="plain"/>
+            <formatter usefile="true" type="xml"/>
+            <classpath refid="junit_jogl_awt.run.classpath"/>
+
+            <batchtest todir="${results.test}">
+              <fileset dir="${classes}">
+                  <include name="${java.dir.junit}/**/newt/**/Test*AWT*"/>
+                  <!--include name="${java.dir.junit}/**/newt/**/TestNewtEventModifiers*AWT*"/-->
+                  <!--include name="${java.dir.junit}/**/acore/glels/Test**"/-->
+                  <exclude name="**/*$$*"/>
+              </fileset>
+              <formatter usefile="false" type="brief"/>
+              <formatter usefile="true" type="xml"/>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="junit.run.newt.event" depends="test.compile">
+        <!-- Test*AWT* -->
+        <junit jvm="${jvmJava.exe}" forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
+            <env key="${system.env.library.path}" path="${obj.all.paths}"/>
+            <jvmarg value="${junit.run.arg0}"/>
+            <jvmarg value="${junit.run.arg1}"/>
+            <jvmarg value="${jvmDataModel.arg}"/>
+            <jvmarg value="-Djava.library.path=${obj.all.paths}"/>
+
+            <!--
+            <jvmarg value="-Dnewt.debug.EDT"/>
+            <jvmarg value="-Djogl.debug=all"/>
+            <jvmarg value="-Dgluegen.debug.NativeLibrary=true"/>
+            <jvmarg value="-Dgluegen.debug.ProcAddressHelper=true"/>
+            <jvmarg value="-Djogl.debug.GLSLState"/>
+            <jvmarg value="-Dnativewindow.debug=all"/>
+            <jvmarg value="-Dnewt.debug=all"/>
+            <jvmarg value="-verbose:jni"/> 
+            <jvmarg value="-client"/>
+            <jvmarg value="-d32"/>
+            -->
+
+            <formatter usefile="false" type="plain"/>
+            <formatter usefile="true" type="xml"/>
+            <!--classpath refid="junit_jogl_awt.run.classpath"/-->
+            <classpath refid="junit_jogl_swt.run.classpath"/>
+
+            <batchtest todir="${results.test}">
+              <fileset dir="${classes}">
+                  <include name="${java.dir.junit}/**/newt/event/Test**"/>
+                  <exclude name="**/*$$*"/>
+              </fileset>
+              <formatter usefile="false" type="brief"/>
+              <formatter usefile="true" type="xml"/>
+            </batchtest>
+        </junit>
+    </target>
+
     <target name="junit.run.awt.singletest" depends="test.compile">
         <!-- Test*AWT* -->
-        <junit forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
+        <junit jvm="${jvmJava.exe}" forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
             <env key="${system.env.library.path}" path="${obj.all.paths}"/>
             <jvmarg value="${junit.run.arg0}"/>
             <jvmarg value="${junit.run.arg1}"/>
@@ -438,7 +522,8 @@
         <for param="test.class.path.m" keepgoing="true">
             <!-- results in absolute path -->
             <fileset dir="${classes}">
-                <include name="${java.dir.junit}/**/Test*SWTHeadless*"/>
+                <include name="${java.dir.junit}/**/Test*SWT*"/>
+                <exclude name="**/*AWT*"/>
                 <exclude name="**/*$$*"/>
             </fileset>
           <sequential>
@@ -454,7 +539,7 @@
             </pathconvert>
             <var name="test.class.result.file" value="${results.test}/TEST-${test.class.fqn}.xml"/>
             <echo message="Testing ${test.class.fqn} -- ${test.class.result.file}"/>
-            <apply dir="." executable="${java.home}/bin/java" 
+            <apply dir="." executable="${jvmJava.exe}"
                  parallel="false" 
                  timeout="${batchtest.timeout}"
                  vmlauncher="false"
@@ -467,10 +552,10 @@
                 <arg line="${jvmDataModel.arg}"/>
                 <arg value="-Djava.library.path=${obj.all.paths}"/>
                 <arg line="${jvmarg.headless}"/>
+                <arg line="${jvmarg.mainthrd}"/>
                 <!--
                 <arg line="-Dnewt.debug.EDT"/>
                 -->
-                <!-- arg line="com.jogamp.newt.util.MainThread"/-->
                 <arg line="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner"/>
                 <srcfile/>
                 <arg line="filtertrace=true"/>
@@ -501,9 +586,8 @@
         <for param="test.class.path.m" keepgoing="true">
             <!-- results in absolute path -->
             <fileset dir="${classes}">
-                <include name="${java.dir.junit}/**/Test*SWT*"/>
+                <include name="${java.dir.junit}/**/Test*SWT*AWT*"/>
                 <exclude name="**/*$$*"/>
-                <exclude name="**/Test*SWTHeadless*"/>
             </fileset>
           <sequential>
             <var name="test.class.path" unset="true"/>
@@ -518,7 +602,7 @@
             </pathconvert>
             <var name="test.class.result.file" value="${results.test}/TEST-${test.class.fqn}.xml"/>
             <echo message="Testing ${test.class.fqn} -- ${test.class.result.file}"/>
-            <apply dir="." executable="${java.home}/bin/java" 
+            <apply dir="." executable="${jvmJava.exe}"
                  parallel="false" 
                  timeout="${batchtest.timeout}"
                  vmlauncher="false"
@@ -530,14 +614,12 @@
                 <arg line="${junit.run.arg1}"/>
                 <arg line="${jvmDataModel.arg}"/>
                 <arg value="-Djava.library.path=${obj.all.paths}"/>
-                <arg line="${jvmarg.mainthrd}"/>
                 <!--
                 <arg line="-Dnewt.debug.EDT"/>
                 <arg line="-Dnativewindow.debug=all"/>
                 <arg line="-Djogl.debug=all"/>
                 <arg line="-Dnewt.debug=all"/>
                 -->
-                <!-- arg line="com.jogamp.newt.util.MainThread"/-->
                 <arg line="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner"/>
                 <srcfile/>
                 <arg line="filtertrace=true"/>
@@ -558,43 +640,6 @@
         </for>
     </target>
 
-    <target name="junit.run.newt.awt" depends="test.compile">
-        <!-- Test*AWT* -->
-        <junit forkmode="perTest" showoutput="true" fork="true" haltonerror="off" timeout="${batchtest.timeout}">
-            <jvmarg value="${junit.run.arg0}"/>
-            <jvmarg value="${junit.run.arg1}"/>
-            <jvmarg value="${jvmDataModel.arg}"/>
-            <env key="${system.env.library.path}" path="${obj.all.paths}"/>
-            <jvmarg value="-Djava.library.path=${obj.all.paths}"/>
-
-            <!--
-            <jvmarg value="-Dnewt.debug.EDT"/>
-            <jvmarg value="-Djogl.debug=all"/>
-            <jvmarg value="-Dgluegen.debug.NativeLibrary=true"/>
-            <jvmarg value="-Dgluegen.debug.ProcAddressHelper=true"/>
-            <jvmarg value="-Djogl.debug.GLSLState"/>
-            <jvmarg value="-Dnativewindow.debug=all"/>
-            <jvmarg value="-Dnewt.debug=all"/>
-            <jvmarg value="-verbose:jni"/> 
-            <jvmarg value="-client"/>
-            <jvmarg value="-d32"/>
-            -->
-
-            <formatter usefile="false" type="plain"/>
-            <formatter usefile="true" type="xml"/>
-            <classpath refid="junit_jogl_awt.run.classpath"/>
-
-            <batchtest todir="${results.test}">
-              <fileset dir="${classes}">
-                  <include name="${java.dir.junit}/**/newt/**/Test*AWT*"/>
-                  <exclude name="**/*$$*"/>
-              </fileset>
-              <formatter usefile="false" type="brief"/>
-              <formatter usefile="true" type="xml"/>
-            </batchtest>
-        </junit>
-    </target>
-
     <target name="junit.run.local" unless="isCrosscompilation" >
         <antcall target="junit.run.noui"          inheritRefs="true" inheritAll="true"/>
         <antcall target="junit.run.newt.headless" inheritRefs="true" inheritAll="true"/>
@@ -604,7 +649,7 @@
         <antcall target="junit.run.swt.awt"       inheritRefs="true" inheritAll="true"/>
     </target>
 
-    <target name="junit.run.local.d32" if="isOSX">
+    <target name="junit.run.local.osx.d32" if="isOSX">
         <var name="jvmDataModel.arg" unset="true"/>
         <var name="jvmDataModel.arg" value="-d32"/>
         <var name="junit_extra_classpath" unset="true"/>
@@ -629,6 +674,29 @@
         <var name="junit_extra_classpath" value=""/>
     </target>
 
+    <target name="junit.run.local.java7" if="jvmJava7.exe">
+        <var name="jvmJavaOrig.exe" value="${jvmJava.exe}"/>
+        <var name="jvmJava.exe" unset="true"/>
+        <var name="jvmJava.exe" value="${jvmJava7.exe}"/>
+
+        <antcall target="junit.run.local" inheritRefs="true" inheritAll="true"/>
+
+        <mkdir dir="${build}/test/results-java7"/>
+        <move todir="${build}/test/results-java7">
+            <fileset dir="." includes="*.png" />
+            <fileset dir="." includes="*.pam" />
+            <fileset dir="." includes="*.tga" />
+        </move>
+        <move todir="${build}/test/results-java7">
+            <fileset dir="${results.test}" includes="**" />
+        </move>
+        <mkdir dir="${results.test}"/>
+
+        <var name="jvmJava.exe" unset="true"/>
+        <var name="jvmJava.exe" value="${jvmJavaOrig.exe}"/>
+        <var name="jvmJavaOrig.exe" unset="true"/>
+    </target>
+
     <target name="junit.run.remote.ssh.all" if="isCrosscompilation" unless="isAndroid">
         <echo message="#! /bin/sh${line.separator}" append="false" file="${build.test}/targetcommand.sh" />
         <echo message="${line.separator}
@@ -940,7 +1008,8 @@ ${line.separator}
         </exec>
     </target>
 
-    <target name="junit.run.tests" depends="junit.run.local.d32, junit.run.local, junit.run.remote.ssh.all, junit.run.remote.adb"/>
+    <!-- target name="junit.run.tests" depends="junit.run.local.osx.d32, junit.run.local, junit.run.remote.ssh.all, junit.run.remote.adb"/-->
+    <target name="junit.run.tests" depends="junit.run.local, junit.run.local.java7, junit.run.remote.ssh.all, junit.run.remote.adb"/>
 
     <target name="junit.run.settings" depends="declare.common">
         <delete quiet="true">
diff --git a/make/build.xml b/make/build.xml
index 44adf80..2eb5a86 100644
--- a/make/build.xml
+++ b/make/build.xml
@@ -96,10 +96,23 @@
             <fileset dir="${build.nativewindow}" includes="*.jar" />
             <fileset dir="${build.newt}" includes="*.jar" />
         </copy>
+
+        <copy file="joglversion-all"
+            tofile="${build}/manifest-all.mf"
+            overwrite="true">
+            <filterset>
+                <filter token="VERSION" value="${jogamp.version}"/>
+                <filter token="BUILD_VERSION" value="${jogl.version}"/>
+                <filter token="SCM_BRANCH" value="${jogl.build.branch}"/>
+                <filter token="SCM_COMMIT" value="${jogl.build.commit}"/>
+                <filter token="BASEVERSION" value="${jogamp.version.base}"/>
+                <filter token="JAR_CODEBASE_TAG" value="${jogamp.jar.codebase}"/>
+            </filterset>
+        </copy>
     </target>
 
     <target name="one.jar.dir.android" depends="one.jar.dir.prep" if="android-jars.available" unless="one.dir.skip">
-        <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-all-android.jar}" filesonly="true" excludes="META-INF/*">
+        <jar manifest="${build}/manifest-all.mf" destfile="${jogl-all-android.jar}" filesonly="true" excludes="META-INF/*">
             <archives>
                 <zips>
                     <path refid="nativewindow_core_atoms.classpath"/>
@@ -111,7 +124,7 @@
     </target>
 
     <target name="one.jar.dir" depends="one.jar.dir.prep,one.jar.dir.android" unless="one.dir.skip">
-        <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-all.jar}" filesonly="true" excludes="META-INF/*">
+        <jar manifest="${build}/manifest-all.mf" destfile="${jogl-all.jar}" filesonly="true" excludes="META-INF/*">
             <archives>
                 <zips>
                     <path refid="nativewindow_all_atoms.classpath"/>
@@ -120,7 +133,7 @@
                 </zips>
             </archives>
         </jar>
-        <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-all-noawt.jar}" filesonly="true" excludes="META-INF/*">
+        <jar manifest="${build}/manifest-all.mf" destfile="${jogl-all-noawt.jar}" filesonly="true" excludes="META-INF/*">
             <archives>
                 <zips>
                     <path refid="nativewindow_all-noawt_atoms.classpath"/>
@@ -129,7 +142,7 @@
                 </zips>
             </archives>
         </jar>
-        <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-all-mobile.jar}" filesonly="true" excludes="META-INF/*">
+        <jar manifest="${build}/manifest-all.mf" destfile="${jogl-all-mobile.jar}" filesonly="true" excludes="META-INF/*">
             <archives>
                 <zips>
                     <path refid="nativewindow_all-noawt_atoms.classpath"/>
@@ -138,7 +151,7 @@
                 </zips>
             </archives>
         </jar>
-        <jar manifest="${build.jogl}/manifest.mf" destfile="${jar}/jogl-all-natives-${os.and.arch}.jar" filesonly="true">
+        <jar manifest="${build}/manifest-all.mf" destfile="${jar}/jogl-all-natives-${os.and.arch}.jar" filesonly="true">
             <fileset dir="${lib}">
               <include name="*.${native.library.suffix}" />
               <exclude name="*jogl_cg.${native.library.suffix}" />
@@ -165,8 +178,8 @@
             androidmanifest.path="resources/android/AndroidManifest-jogl.xml"
             androidresources.path="resources/android/res-jogl"
             jarmanifest.path="${build.jogl}/manifest.mf"
-            version.code="${jogl_int_version}"
-            version.name="${jogl.version.plus}" />
+            version.code="${jogamp.version.int}"
+            version.name="${jogamp.version}" />
     </target>
 
     <target name="one.dir.skip.check" depends="init,gluegen.cpptasks.detect.os">
@@ -241,10 +254,12 @@
             tofile="${archive}/README.txt"
             overwrite="true">
             <filterset>
-                <filter token="VERSION"  value="${jogl.version}"/>
+                <filter token="VERSION" value="${jogamp.version}"/>
+                <filter token="BUILD_VERSION" value="${jogl.version}"/>
                 <filter token="SCM_BRANCH" value="${jogl.build.branch}"/>
                 <filter token="SCM_COMMIT" value="${jogl.build.commit}"/>
-                <filter token="BASEVERSION" value="${jogl_base_version}"/>
+                <filter token="BASEVERSION" value="${jogamp.version.base}"/>
+                <filter token="JAR_CODEBASE_TAG" value="${jogamp.jar.codebase}"/>
             </filterset>
         </copy>
         <mkdir dir="${archive}/jar" />
@@ -343,10 +358,10 @@
         <property name="javadoc.overview" value="doc/jogl/spec-overview.html" />
 
         <property name="javadoc.nw.overview" value="../src/nativewindow/classes/javax/media/nativewindow/package.html" />
-        <property name="javadoc.nw.spec.windowtitle" value="NativeWindow API -- ${nativewindow_base_version} Specification" />
+        <property name="javadoc.nw.spec.windowtitle" value="NativeWindow API -- ${jogamp.version.base} Specification" />
         <property name="javadoc.nw.spec.packagenames" value="javax.media.nativewindow.*" />
 
-        <property name="javadoc.spec.windowtitle" value="JOGL API -- JSR-231 ${jogl_base_version} Specification" />
+        <property name="javadoc.spec.windowtitle" value="JOGL API -- JSR-231 ${jogamp.version.base} Specification" />
         <property name="javadoc.spec.packagenames" value="javax.media.opengl.*" />
 
         <property name="javadoc.windowtitle" value="JOGL, NativeWindow and NEWT APIs" />
diff --git a/make/config/jogl/cg-common-CustomJavaCode.java b/make/config/jogl/cg-common-CustomJavaCode.java
index 31d1961..cc1fefd 100644
--- a/make/config/jogl/cg-common-CustomJavaCode.java
+++ b/make/config/jogl/cg-common-CustomJavaCode.java
@@ -6,7 +6,11 @@ static {
     if(null==cgProcAddressTable) {
       throw new RuntimeException("Couldn't instantiate CgProcAddressTable");
     }
-    cgDynamicLookupHelper = new DynamicLibraryBundle(new CgDynamicLibraryBundleInfo());
+
+    cgDynamicLookupHelper = AccessController.doPrivileged(new PrivilegedAction<DynamicLibraryBundle>() {
+                                public DynamicLibraryBundle run() {
+                                    return new DynamicLibraryBundle(new CgDynamicLibraryBundleInfo());
+                                } } );
     if(null==cgDynamicLookupHelper) {
       throw new RuntimeException("Null CgDynamicLookupHelper");
     }
diff --git a/make/config/jogl/cg-common.cfg b/make/config/jogl/cg-common.cfg
index 35805bf..d6a5367 100644
--- a/make/config/jogl/cg-common.cfg
+++ b/make/config/jogl/cg-common.cfg
@@ -105,6 +105,8 @@ Import jogamp.opengl.*
 Import com.jogamp.common.os.DynamicLookupHelper
 Import com.jogamp.common.os.DynamicLibraryBundle
 Import com.jogamp.opengl.cg.CgDynamicLibraryBundleInfo
+Import java.security.PrivilegedAction
+Import java.security.AccessController
 
 #
 # NIODirectOnly directives for routines requiring them for semantic reasons
diff --git a/make/config/jogl/cgl-macosx-CustomJavaCode.java b/make/config/jogl/cgl-macosx-CustomJavaCode.java
new file mode 100644
index 0000000..ab1d44b
--- /dev/null
+++ b/make/config/jogl/cgl-macosx-CustomJavaCode.java
@@ -0,0 +1,35 @@
+
+/**
+ * Creates the NSOpenGLLayer for FBO/PBuffer w/ optional GL3 shader program
+ * <p>
+ * The NSOpenGLLayer will immediatly create a OpenGL context sharing the given ctx,
+ * which will be used to render the texture offthread.
+ * </p>
+ * <p>
+ * The NSOpenGLLayer starts in enabled mode, 
+ * you may enable/disable it via {@link #setNSOpenGLLayerEnabled(long, boolean)}.
+ * </p>
+ */
+public static long createNSOpenGLLayer(final long ctx, final int gl3ShaderProgramName, final long fmt, final long p, 
+                                       final int texID, final boolean opaque, final int texWidth, final int texHeight) {
+   return createNSOpenGLLayerImpl(ctx, gl3ShaderProgramName, fmt, p, texID, opaque, texWidth, texHeight);
+}
+
+/**
+ * Enable or disable NSOpenGLLayer. 
+ *
+ * <p>
+ * If disabled, the NSOpenGLLayer will not be displayed, i.e. rendered.
+ * </p>
+ */
+public static void setNSOpenGLLayerEnabled(final long nsOpenGLLayer, final boolean enable) {
+  setNSOpenGLLayerEnabledImpl(nsOpenGLLayer, enable);
+}
+
+/**
+ * Releases the NSOpenGLLayer
+ */
+public static void releaseNSOpenGLLayer(final long nsOpenGLLayer) {
+  releaseNSOpenGLLayerImpl(nsOpenGLLayer);
+}
+
diff --git a/make/config/jogl/cgl-macosx.cfg b/make/config/jogl/cgl-macosx.cfg
index 203802d..edb5bfb 100644
--- a/make/config/jogl/cgl-macosx.cfg
+++ b/make/config/jogl/cgl-macosx.cfg
@@ -34,6 +34,15 @@ Opaque long NSOpenGLLayer *
 CustomCCode #include </usr/include/machine/types.h>
 CustomCCode #include "macosx-window-system.h"
 
+AccessControl createNSOpenGLLayerImpl PRIVATE
+AccessControl setNSOpenGLLayerEnabledImpl PRIVATE
+AccessControl releaseNSOpenGLLayerImpl PRIVATE
+RenameJavaMethod createNSOpenGLLayer createNSOpenGLLayerImpl
+RenameJavaMethod setNSOpenGLLayerEnabled setNSOpenGLLayerEnabledImpl
+RenameJavaMethod releaseNSOpenGLLayer releaseNSOpenGLLayerImpl
+
+IncludeAs CustomJavaCode CGL cgl-macosx-CustomJavaCode.java
+
 # Implement the first argument to getProcAddress as String instead
 # of byte[]
 ArgumentIsString getProcAddress 0
@@ -53,3 +62,5 @@ DropUniqVendorExtensions SGIX
 DropUniqVendorExtensions SUN
 DropUniqVendorExtensions WIN
 
+Import com.jogamp.common.util.Function
+Import jogamp.nativewindow.macosx.OSXUtil
diff --git a/make/config/jogl/gl-common.cfg b/make/config/jogl/gl-common.cfg
index f8f4f07..a574002 100644
--- a/make/config/jogl/gl-common.cfg
+++ b/make/config/jogl/gl-common.cfg
@@ -515,6 +515,7 @@ JavaPrologue glBegin inBeginEndPair = true;
 JavaEpilogue glEnd   inBeginEndPair = false;
 JavaEpilogue glBindBuffer       bufferStateTracker.setBoundBufferObject({0}, {1});
 JavaEpilogue glBindBufferARB    bufferStateTracker.setBoundBufferObject({0}, {1});
+JavaEpilogue glBindVertexArray  bufferStateTracker.setBoundBufferObject(GL2GL3.GL_VERTEX_ARRAY_BINDING, {0});
 JavaEpilogue glPushClientAttrib bufferStateTracker.clearBufferObjectState();
 JavaEpilogue glPushClientAttrib glStateTracker.pushAttrib(mask);
 JavaEpilogue glPopClientAttrib  bufferStateTracker.clearBufferObjectState();
diff --git a/make/config/jogl/gl-impl-CustomJavaCode-common.java b/make/config/jogl/gl-impl-CustomJavaCode-common.java
index 283a4e6..8e8165f 100644
--- a/make/config/jogl/gl-impl-CustomJavaCode-common.java
+++ b/make/config/jogl/gl-impl-CustomJavaCode-common.java
@@ -113,3 +113,8 @@
       return _context.getDefaultReadFramebuffer();
     }
 
+    @Override
+    public final int getDefaultReadBuffer() {
+      return _context.getDefaultReadBuffer();
+    }
+
diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java
index e079a1a..bfe2759 100644
--- a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java
+++ b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java
@@ -51,133 +51,135 @@ private boolean haveEXTPixelBufferObject;
 private boolean haveGL15;
 private boolean haveGL21;
 private boolean haveARBVertexBufferObject;
+private boolean haveARBVertexArrayObject;
 
 private final void initBufferObjectExtensionChecks() {
-  if (bufferObjectExtensionsInitialized)
+  if ( bufferObjectExtensionsInitialized ) {
     return;
+  }
   bufferObjectExtensionsInitialized = true;
   haveARBPixelBufferObject  = isExtensionAvailable("GL_ARB_pixel_buffer_object");
   haveEXTPixelBufferObject  = isExtensionAvailable("GL_EXT_pixel_buffer_object");
   haveGL15                  = isExtensionAvailable("GL_VERSION_1_5");
   haveGL21                  = isExtensionAvailable("GL_VERSION_2_1");
   haveARBVertexBufferObject = isExtensionAvailable("GL_ARB_vertex_buffer_object");
+  haveARBVertexArrayObject  = _context.getGLVersionNumber().compareTo(GLContext.Version30) >= 0 ||
+                              isExtensionAvailable("GL_ARB_vertex_array_object");
 }
 
-private final boolean checkBufferObject(boolean extension1,
-                                        boolean extension2,
-                                        boolean extension3,
+private final boolean checkBufferObject(boolean extensionAvail,
+                                        boolean allowVAO,
                                         boolean enabled,
                                         int state,
                                         String kind, boolean throwException) {
-  if (inBeginEndPair) {
+  if ( inBeginEndPair ) {
     throw new GLException("May not call this between glBegin and glEnd");
   }
-  boolean avail = (extension1 || extension2 || extension3);
-  if (!avail) {
-    if (!enabled)
+  if ( !extensionAvail ) {
+    if ( !enabled ) {
       return true;
+    }
     if(throwException) {
         throw new GLException("Required extensions not available to call this function");
     }
     return false;
   }
   int buffer = bufferStateTracker.getBoundBufferObject(state, this);
-  if (enabled) {
-    if (buffer == 0) {
-      if(throwException) {
-          throw new GLException(kind + " must be enabled to call this method");
-      }
-      return false;
+  if ( enabled ) {
+    if ( 0 != buffer ) {
+        return true;
+    }
+    if ( allowVAO ) {
+        buffer = bufferStateTracker.getBoundBufferObject(GL2GL3.GL_VERTEX_ARRAY_BINDING, this);
+        if( 0 != buffer && !_context.isDefaultVAO(buffer) ) {
+            return true;
+        }
+    }
+    if ( throwException ) {
+        throw new GLException(kind + " must be enabled to call this method");
     }
+    return false;
   } else {
-    if (buffer != 0) {
-      if(throwException) {
-          throw new GLException(kind + " must be disabled to call this method");
-      }
-      return false;
+    if ( 0 == buffer ) {
+        return true;
     }
+    if ( throwException ) {
+        throw new GLException(kind + " must be disabled to call this method");
+    }
+    return false;
   }
-  return true;
 }  
 
 private final boolean checkArrayVBODisabled(boolean throwException) { 
   initBufferObjectExtensionChecks();
-  return checkBufferObject(haveGL15,
-                    haveARBVertexBufferObject,
-                    false,
-                    false,
-                    GL.GL_ARRAY_BUFFER,
-                    "array vertex_buffer_object", throwException);
+  return checkBufferObject(haveGL15 || haveARBVertexBufferObject,
+                           haveARBVertexArrayObject, // allowVAO
+                           false, // enable
+                           GL.GL_ARRAY_BUFFER,
+                           "array vertex_buffer_object", throwException);
 }
 
 private final boolean checkArrayVBOEnabled(boolean throwException) { 
   initBufferObjectExtensionChecks();
-  return checkBufferObject(haveGL15,
-                    haveARBVertexBufferObject,
-                    false,
-                    true,
-                    GL.GL_ARRAY_BUFFER,
-                    "array vertex_buffer_object", throwException);
+  return checkBufferObject(haveGL15 || haveARBVertexBufferObject,
+                           haveARBVertexArrayObject, // allowVAO
+                           true, // enable
+                           GL.GL_ARRAY_BUFFER,
+                           "array vertex_buffer_object", throwException);
 }
 
 private final boolean checkElementVBODisabled(boolean throwException) { 
   initBufferObjectExtensionChecks();
-  return checkBufferObject(haveGL15,
-                    haveARBVertexBufferObject,
-                    false,
-                    false,
-                    GL.GL_ELEMENT_ARRAY_BUFFER,
-                    "element vertex_buffer_object", throwException);
+  return checkBufferObject(haveGL15 || haveARBVertexBufferObject,
+                           haveARBVertexArrayObject, // allowVAO
+                           false, // enable
+                           GL.GL_ELEMENT_ARRAY_BUFFER,
+                           "element vertex_buffer_object", throwException);
 }
 
 private final boolean checkElementVBOEnabled(boolean throwException) { 
   initBufferObjectExtensionChecks();
-  return checkBufferObject(haveGL15,
-                    haveARBVertexBufferObject,
-                    false,
-                    true,
-                    GL.GL_ELEMENT_ARRAY_BUFFER,
-                    "element vertex_buffer_object", throwException);
+  return checkBufferObject(haveGL15 || haveARBVertexBufferObject,
+                           haveARBVertexArrayObject, // allowVAO
+                           true, // enable
+                           GL.GL_ELEMENT_ARRAY_BUFFER,
+                           "element vertex_buffer_object", throwException);
 }
 
 private final boolean checkUnpackPBODisabled(boolean throwException) { 
   initBufferObjectExtensionChecks();
-  return checkBufferObject(haveARBPixelBufferObject,
-                    haveEXTPixelBufferObject,
-                    haveGL21,
-                    false,
-                    GL2.GL_PIXEL_UNPACK_BUFFER,
-                    "unpack pixel_buffer_object", throwException);
+  return checkBufferObject(haveGL21 || haveARBPixelBufferObject || haveEXTPixelBufferObject,
+                           false, // allowVAO
+                           false, // enable
+                           GL2.GL_PIXEL_UNPACK_BUFFER,
+                           "unpack pixel_buffer_object", throwException);
 }
 
 private final boolean checkUnpackPBOEnabled(boolean throwException) { 
   initBufferObjectExtensionChecks();
-  return checkBufferObject(haveARBPixelBufferObject,
-                    haveEXTPixelBufferObject,
-                    haveGL21,
-                    true,
-                    GL2.GL_PIXEL_UNPACK_BUFFER,
-                    "unpack pixel_buffer_object", throwException);
+  return checkBufferObject(haveGL21 || haveARBPixelBufferObject || haveEXTPixelBufferObject,
+                           false, // allowVAO
+                           true, // enable
+                           GL2.GL_PIXEL_UNPACK_BUFFER,
+                           "unpack pixel_buffer_object", throwException);
 }
 
 private final boolean checkPackPBODisabled(boolean throwException) { 
   initBufferObjectExtensionChecks();
-  return checkBufferObject(haveARBPixelBufferObject,
-                    haveEXTPixelBufferObject,
-                    haveGL21,
-                    false,
-                    GL2.GL_PIXEL_PACK_BUFFER,
-                    "pack pixel_buffer_object", throwException);
+  return checkBufferObject(haveGL21 || haveARBPixelBufferObject || haveEXTPixelBufferObject,
+                           false, // allowVAO
+                           false, // enable
+                           GL2.GL_PIXEL_PACK_BUFFER,
+                           "pack pixel_buffer_object", throwException);
 }
 
 private final boolean checkPackPBOEnabled(boolean throwException) { 
   initBufferObjectExtensionChecks();
-  return checkBufferObject(haveARBPixelBufferObject,
-                    haveEXTPixelBufferObject,
-                    haveGL21,
-                    true,
-                    GL2.GL_PIXEL_PACK_BUFFER,
-                    "pack pixel_buffer_object", throwException);
+  return checkBufferObject(haveGL21 || haveARBPixelBufferObject || haveEXTPixelBufferObject,
+                           false, // allowVAO
+                           true, // enable
+                           GL2.GL_PIXEL_PACK_BUFFER,
+                           "pack pixel_buffer_object", throwException);
 }
 
 @Override
diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java
index 68eadc6..7042568 100644
--- a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java
+++ b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java
@@ -140,38 +140,19 @@ private final GLBufferSizeTracker  bufferSizeTracker;
 private final GLBufferStateTracker bufferStateTracker;
 private final GLStateTracker       glStateTracker;
 
-private boolean bufferObjectExtensionsInitialized = false;
-private boolean haveOESFramebufferObject;
-
-private final void initBufferObjectExtensionChecks() {
-  if (bufferObjectExtensionsInitialized)
-    return;
-  bufferObjectExtensionsInitialized = true;
-  haveOESFramebufferObject  = isExtensionAvailable("GL_OES_framebuffer_object");
-}
-
-private final boolean checkBufferObject(boolean avail,
-                                        boolean enabled,
+private final boolean checkBufferObject(boolean enabled,
                                         int state,
                                         String kind, boolean throwException) {
-  if (!avail) {
-    if (!enabled)
-      return true;
-    if(throwException) {
-        throw new GLException("Required extensions not available to call this function");
-    }
-    return false;
-  }
-  int buffer = bufferStateTracker.getBoundBufferObject(state, this);
+  final int buffer = bufferStateTracker.getBoundBufferObject(state, this);
   if (enabled) {
-    if (buffer == 0) {
+    if (0 == buffer) {
       if(throwException) {
           throw new GLException(kind + " must be enabled to call this method");
       }
       return false;
     }
   } else {
-    if (buffer != 0) {
+    if (0 != buffer) {
       if(throwException) {
           throw new GLException(kind + " must be disabled to call this method");
       }
@@ -182,35 +163,27 @@ private final boolean checkBufferObject(boolean avail,
 }  
 
 private final boolean checkArrayVBODisabled(boolean throwException) { 
-  initBufferObjectExtensionChecks();
-  return checkBufferObject(true,
-                    false,
-                    GL.GL_ARRAY_BUFFER,
-                    "array vertex_buffer_object", throwException);
+  return checkBufferObject(false, // enabled
+                           GL.GL_ARRAY_BUFFER,
+                           "array vertex_buffer_object", throwException);
 }
 
 private final boolean checkArrayVBOEnabled(boolean throwException) { 
-  initBufferObjectExtensionChecks();
-  return checkBufferObject(true,
-                    true,
-                    GL.GL_ARRAY_BUFFER,
-                    "array vertex_buffer_object", throwException);
+  return checkBufferObject(true, // enabled
+                           GL.GL_ARRAY_BUFFER,
+                           "array vertex_buffer_object", throwException);
 }
 
 private final boolean checkElementVBODisabled(boolean throwException) { 
-  initBufferObjectExtensionChecks();
-  return checkBufferObject(true,
-                    false,
-                    GL.GL_ELEMENT_ARRAY_BUFFER,
-                    "element vertex_buffer_object", throwException);
+  return checkBufferObject(false, // enabled
+                           GL.GL_ELEMENT_ARRAY_BUFFER,
+                           "element vertex_buffer_object", throwException);
 }
 
 private final boolean checkElementVBOEnabled(boolean throwException) { 
-  initBufferObjectExtensionChecks();
-  return checkBufferObject(true,
-                    true,
-                    GL.GL_ELEMENT_ARRAY_BUFFER,
-                    "element vertex_buffer_object", throwException);
+  return checkBufferObject(true, // enabled
+                           GL.GL_ELEMENT_ARRAY_BUFFER,
+                           "element vertex_buffer_object", throwException);
 }
 
 private final boolean checkUnpackPBODisabled(boolean throwException) { 
diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles2.java b/make/config/jogl/gl-impl-CustomJavaCode-gles2.java
index 7602873..37f3f33 100644
--- a/make/config/jogl/gl-impl-CustomJavaCode-gles2.java
+++ b/make/config/jogl/gl-impl-CustomJavaCode-gles2.java
@@ -140,38 +140,19 @@ private final GLBufferSizeTracker  bufferSizeTracker;
 private final GLBufferStateTracker bufferStateTracker;
 private final GLStateTracker       glStateTracker;
 
-private boolean bufferObjectExtensionsInitialized = false;
-private boolean haveOESFramebufferObject;
-
-private final void initBufferObjectExtensionChecks() {
-  if (bufferObjectExtensionsInitialized)
-    return;
-  bufferObjectExtensionsInitialized = true;
-  haveOESFramebufferObject  = isExtensionAvailable("GL_OES_framebuffer_object");
-}
-
-private final boolean checkBufferObject(boolean avail,
-                                        boolean enabled,
+private final boolean checkBufferObject(boolean enabled,
                                         int state,
                                         String kind, boolean throwException) {
-  if (!avail) {
-    if (!enabled)
-      return true;
-    if(throwException) {
-        throw new GLException("Required extensions not available to call this function");
-    }
-    return false;
-  }
-  int buffer = bufferStateTracker.getBoundBufferObject(state, this);
+  final int buffer = bufferStateTracker.getBoundBufferObject(state, this);
   if (enabled) {
-    if (buffer == 0) {
+    if (0 == buffer) {
       if(throwException) {
           throw new GLException(kind + " must be enabled to call this method");
       }
       return false;
     }
   } else {
-    if (buffer != 0) {
+    if (0 != buffer) {
       if(throwException) {
           throw new GLException(kind + " must be disabled to call this method");
       }
@@ -182,35 +163,27 @@ private final boolean checkBufferObject(boolean avail,
 }  
 
 private final boolean checkArrayVBODisabled(boolean throwException) { 
-  initBufferObjectExtensionChecks();
-  return checkBufferObject(true,
-                    false,
-                    GL.GL_ARRAY_BUFFER,
-                    "array vertex_buffer_object", throwException);
+  return checkBufferObject(false, // enabled
+                           GL.GL_ARRAY_BUFFER,
+                           "array vertex_buffer_object", throwException);
 }
 
 private final boolean checkArrayVBOEnabled(boolean throwException) { 
-  initBufferObjectExtensionChecks();
-  return checkBufferObject(true,
-                    true,
-                    GL.GL_ARRAY_BUFFER,
-                    "array vertex_buffer_object", throwException);
+  return checkBufferObject(true, // enabled
+                           GL.GL_ARRAY_BUFFER,
+                           "array vertex_buffer_object", throwException);
 }
 
 private final boolean checkElementVBODisabled(boolean throwException) { 
-  initBufferObjectExtensionChecks();
-  return checkBufferObject(true,
-                    false,
-                    GL.GL_ELEMENT_ARRAY_BUFFER,
-                    "element vertex_buffer_object", throwException);
+  return checkBufferObject(false, // enabled
+                           GL.GL_ELEMENT_ARRAY_BUFFER,
+                           "element vertex_buffer_object", throwException);
 }
 
 private final boolean checkElementVBOEnabled(boolean throwException) { 
-  initBufferObjectExtensionChecks();
-  return checkBufferObject(true,
-                    true,
-                    GL.GL_ELEMENT_ARRAY_BUFFER,
-                    "element vertex_buffer_object", throwException);
+  return checkBufferObject(true, // enabled
+                           GL.GL_ELEMENT_ARRAY_BUFFER,
+                           "element vertex_buffer_object", throwException);
 }
 
 private final boolean checkUnpackPBODisabled(boolean throwException) { 
diff --git a/make/config/jogl/glu-CustomJavaCode-base.java b/make/config/jogl/glu-CustomJavaCode-base.java
index 49722b4..21d6277 100644
--- a/make/config/jogl/glu-CustomJavaCode-base.java
+++ b/make/config/jogl/glu-CustomJavaCode-base.java
@@ -1250,16 +1250,24 @@ public final void gluDisk(GLUquadric quad, double inner, double outer, int slice
 
 /** Option (throws GLException if not available in profile). <br> Interface to C language function: <br> <code> GLUquadric *  gluNewQuadric(void); </code>    */
 public final GLUquadric gluNewQuadric() {
-  return gluNewQuadric(false);
+  return gluNewQuadric(false, null, 0);
 }
 
-public final GLUquadric gluNewQuadric(boolean useGLSL) {
+public final GLUquadric gluNewQuadric(boolean useGLSL, ShaderState st) {
+    return gluNewQuadric(useGLSL, st, 0);
+}
+
+public final GLUquadric gluNewQuadric(boolean useGLSL, int shaderProgram) {
+    return gluNewQuadric(useGLSL, null, shaderProgram);
+}
+
+private final GLUquadric gluNewQuadric(boolean useGLSL, ShaderState st, int shaderProgram) {
   GL gl = getCurrentGL();
   if(useGLSL && !gl.isGL2ES2()) {
     throw new GLException("GLUquadric GLSL implementation not supported for profile: "+gl);
   }
   validateGLUquadricImpl();
-  return new GLUquadricImpl(gl, useGLSL);
+  return new GLUquadricImpl(gl, useGLSL, st, shaderProgram);
 }
 
 /** Option (throws GLException if not available in profile). <br> Interface to C language function: <br> <code> void gluPartialDisk(GLUquadric *  quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops, GLdouble start, GLdouble sweep); </code>    */
diff --git a/make/config/jogl/glu-common.cfg b/make/config/jogl/glu-common.cfg
index 9271ec3..85d556b 100644
--- a/make/config/jogl/glu-common.cfg
+++ b/make/config/jogl/glu-common.cfg
@@ -11,6 +11,7 @@ TagNativeBinding true
 #
 Import javax.media.opengl.*
 Import javax.media.opengl.glu.*
+import com.jogamp.opengl.util.glsl.ShaderState
 Import jogamp.opengl.*
 Import jogamp.opengl.glu.*
 Import jogamp.opengl.glu.tessellator.GLUtessellatorImpl
diff --git a/make/config/jogl/glu-gl2.cfg b/make/config/jogl/glu-gl2.cfg
index 9387b4c..2dcc15a 100644
--- a/make/config/jogl/glu-gl2.cfg
+++ b/make/config/jogl/glu-gl2.cfg
@@ -24,9 +24,10 @@ CustomCCode   #include <inttypes.h>
 CustomCCode #endif
 
 EmitProcAddressTable true
-ProcAddressTablePackage   jogamp.opengl.glu.gl2
+ProcAddressTablePackage   javax.media.opengl.glu.gl2
 ProcAddressTableClassName GLUgl2ProcAddressTable
 GetProcAddressTableExpr   getGLUProcAddressTable()
+AccessControl javax.media.opengl.glu.gl2.GLUgl2ProcAddressTable PACKAGE_PRIVATE
 
 CustomCCode /* Include the OpenGL GLU header */
 CustomCCode #include <GL/glu.h>
diff --git a/make/config/jogl/glx-CustomJavaCode.java b/make/config/jogl/glx-CustomJavaCode.java
index ed126a5..f3e7439 100644
--- a/make/config/jogl/glx-CustomJavaCode.java
+++ b/make/config/jogl/glx-CustomJavaCode.java
@@ -6,10 +6,9 @@
     if (__addr_ == 0) {
         throw new GLException("Method \"glXGetVisualFromFBConfig\" not available");
     }
-    java.nio.ByteBuffer _res;
-    _res = dispatch_glXGetVisualFromFBConfig(dpy, config, __addr_);
+    final java.nio.ByteBuffer _res = dispatch_glXGetVisualFromFBConfig(dpy, config, __addr_);
     if (_res == null) return null;
-    return XVisualInfo.create(_res);
+    return XVisualInfo.create(Buffers.nativeOrder(_res));
   }
 
   /** Entry point to C language function: - Alias for: <br> <code> XVisualInfo *  glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig(Display *  dpy, GLXFBConfig config); </code>    */
@@ -29,11 +28,9 @@
     if (__addr_ == 0) {
       throw new GLException("Method \"glXChooseFBConfig\" not available");
     }
-    final ByteBuffer _res;
-    _res = dispatch_glXChooseFBConfig(dpy, screen, attribList, Buffers.getDirectBufferByteOffset(attribList), nitems, Buffers.getDirectBufferByteOffset(nitems), __addr_);
+    final ByteBuffer _res = dispatch_glXChooseFBConfig(dpy, screen, attribList, Buffers.getDirectBufferByteOffset(attribList), nitems, Buffers.getDirectBufferByteOffset(nitems), __addr_);
     if (_res == null) return null;
-    Buffers.nativeOrder(_res);
-    return PointerBuffer.wrap(_res);
+    return PointerBuffer.wrap(Buffers.nativeOrder(_res));
   }
 
   /** Entry point to C language function: <code> GLXFBConfig *  glXChooseFBConfig(Display *  dpy, int screen, const int *  attribList, int *  nitems); </code> <br>Part of CORE FUNC
@@ -52,8 +49,7 @@
     if (__addr_ == 0) {
       throw new GLException("Method \"glXChooseVisual\" not available");
     }
-    final ByteBuffer _res;
-    _res = dispatch_glXChooseVisual(dpy, screen, attribList, Buffers.getDirectBufferByteOffset(attribList), __addr_);
+    final ByteBuffer _res = dispatch_glXChooseVisual(dpy, screen, attribList, Buffers.getDirectBufferByteOffset(attribList), __addr_);
     if (_res == null) return null;
     return XVisualInfo.create(Buffers.nativeOrder(_res));
   }
diff --git a/make/config/nativewindow/x11-CustomJavaCode.java b/make/config/nativewindow/x11-CustomJavaCode.java
index 8e5da3b..4240c5e 100644
--- a/make/config/nativewindow/x11-CustomJavaCode.java
+++ b/make/config/nativewindow/x11-CustomJavaCode.java
@@ -28,8 +28,9 @@
 
   public static native int DefaultVisualID(long display, int screen);
 
-  public static native long CreateDummyWindow(long display, int screen_index, int visualID, int width, int height);
-  public static native void DestroyDummyWindow(long display, long window);
+  public static native long CreateWindow(long parent, long display, int screen_index, int visualID, int width, int height, boolean input, boolean visible);
+  public static native void DestroyWindow(long display, long window);
+  public static native void SetWindowPosSize(long display, long window, int x, int y, int width, int height);
 
   public static Point GetRelativeLocation(long display, int screen_index, long src_win, long dest_win, int src_x, int src_y) {
     return (Point) GetRelativeLocation0(display, screen_index, src_win, dest_win, src_x, src_y);
diff --git a/make/joglversion b/make/joglversion
index bf0220f..84a9836 100644
--- a/make/joglversion
+++ b/make/joglversion
@@ -4,6 +4,7 @@ Specification-Version: @BASEVERSION@
 Specification-Vendor: JogAmp Community
 Implementation-Title: Java Bindings for OpenGL Runtime Environment
 Implementation-Version: @VERSION@
+Implementation-Build: @BUILD_VERSION@
 Implementation-Branch: @SCM_BRANCH@
 Implementation-Commit: @SCM_COMMIT@
 Implementation-Vendor: JogAmp Community
@@ -11,3 +12,5 @@ Implementation-URL: http://jogamp.org/
 Extension-Name: javax.media.opengl
 Implementation-Vendor-Id: com.jogamp
 Trusted-Library: true
+Permissions: all-permissions
+ at JAR_CODEBASE_TAG@
diff --git a/make/joglversion b/make/joglversion-all
similarity index 85%
copy from make/joglversion
copy to make/joglversion-all
index bf0220f..84a9836 100644
--- a/make/joglversion
+++ b/make/joglversion-all
@@ -4,6 +4,7 @@ Specification-Version: @BASEVERSION@
 Specification-Vendor: JogAmp Community
 Implementation-Title: Java Bindings for OpenGL Runtime Environment
 Implementation-Version: @VERSION@
+Implementation-Build: @BUILD_VERSION@
 Implementation-Branch: @SCM_BRANCH@
 Implementation-Commit: @SCM_COMMIT@
 Implementation-Vendor: JogAmp Community
@@ -11,3 +12,5 @@ Implementation-URL: http://jogamp.org/
 Extension-Name: javax.media.opengl
 Implementation-Vendor-Id: com.jogamp
 Trusted-Library: true
+Permissions: all-permissions
+ at JAR_CODEBASE_TAG@
diff --git a/make/joglversion-test b/make/joglversion-test
index cee93db..b130bb2 100644
--- a/make/joglversion-test
+++ b/make/joglversion-test
@@ -2,8 +2,9 @@ Manifest-Version: 1.0
 Specification-Title: Test Java Bindings for OpenGL API Specification
 Specification-Version: @BASEVERSION@
 Specification-Vendor: JogAmp Community
-Implementation-Title: Test Java Bindings for OpenGL Runtime Environment
+Implementation-Title: Test JOGL Runtime Environment
 Implementation-Version: @VERSION@
+Implementation-Build: @BUILD_VERSION@
 Implementation-Branch: @SCM_BRANCH@
 Implementation-Commit: @SCM_COMMIT@
 Implementation-Vendor: JogAmp Community
diff --git a/make/joglversion-test-android b/make/joglversion-test-android
index 88c35be..153b3c3 100644
--- a/make/joglversion-test-android
+++ b/make/joglversion-test-android
@@ -2,8 +2,9 @@ Manifest-Version: 1.0
 Specification-Title: Test Java Bindings for OpenGL API Specification
 Specification-Version: @BASEVERSION@
 Specification-Vendor: JogAmp Community
-Implementation-Title: Test Java Bindings for OpenGL Runtime Environment on Android
+Implementation-Title: Test JOGL Android Runtime Environment
 Implementation-Version: @VERSION@
+Implementation-Build: @BUILD_VERSION@
 Implementation-Branch: @SCM_BRANCH@
 Implementation-Commit: @SCM_COMMIT@
 Implementation-Vendor: JogAmp Community
diff --git a/make/nativewindowversion b/make/nativewindowversion
index 3eb3bc2..3b3308a 100644
--- a/make/nativewindowversion
+++ b/make/nativewindowversion
@@ -4,6 +4,7 @@ Specification-Version: @BASEVERSION@
 Specification-Vendor: JogAmp Community
 Implementation-Title: Native Window Interface Runtime Environment
 Implementation-Version: @VERSION@
+Implementation-Build: @BUILD_VERSION@
 Implementation-Branch: @SCM_BRANCH@
 Implementation-Commit: @SCM_COMMIT@
 Implementation-Vendor: JogAmp Community
@@ -11,3 +12,5 @@ Implementation-URL: http://jogamp.org/
 Extension-Name: javax.media.nativewindow
 Implementation-Vendor-Id: com.jogamp
 Trusted-Library: true
+Permissions: all-permissions
+ at JAR_CODEBASE_TAG@
diff --git a/make/newtversion b/make/newtversion
index e8aa60c..8444a49 100644
--- a/make/newtversion
+++ b/make/newtversion
@@ -4,6 +4,7 @@ Specification-Version: @BASEVERSION@
 Specification-Vendor: JogAmp Community
 Implementation-Title: NEWT Runtime Environment
 Implementation-Version: @VERSION@
+Implementation-Build: @BUILD_VERSION@
 Implementation-Branch: @SCM_BRANCH@
 Implementation-Commit: @SCM_COMMIT@
 Implementation-Vendor: JogAmp Community
@@ -11,3 +12,5 @@ Implementation-URL: http://jogamp.org/
 Extension-Name: com.jogamp.newt
 Implementation-Vendor-Id: com.jogamp
 Trusted-Library: true
+Permissions: all-permissions
+ at JAR_CODEBASE_TAG@
diff --git a/make/resources/android/AndroidManifest-test.xml b/make/resources/android/AndroidManifest-test.xml
index 3c2046d..5357d0a 100644
--- a/make/resources/android/AndroidManifest-test.xml
+++ b/make/resources/android/AndroidManifest-test.xml
@@ -18,9 +18,9 @@
                  android:persistent="false"
                  >
 
-        <activity android:name="com.jogamp.opengl.test.android.NEWTRedSquareES1ActivityLauncher"
-                  android:label="@string/activity_redsquarees1_name"
-                  android:description="@string/activity_redsquarees1_descr"
+        <activity android:name="com.jogamp.opengl.test.android.NEWTGearsES2ActivityLauncher"
+                  android:label="@string/activity_gearses2_name"
+                  android:description="@string/activity_gearses2_descr"
                   android:theme="@android:style/Theme.NoDisplay"
                   >
             <intent-filter>
@@ -28,9 +28,19 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <activity android:name="com.jogamp.opengl.test.android.NEWTRedSquareES2ActivityLauncher"
-                  android:label="@string/activity_redsquarees2_name"
-                  android:description="@string/activity_redsquarees2_descr"
+        <activity android:name="com.jogamp.opengl.test.android.NEWTGearsES2RGB565ActivityLauncher"
+                  android:label="@string/activity_gearses2rgb565_name"
+                  android:description="@string/activity_gearses2rgb565_descr"
+                  android:theme="@android:style/Theme.NoDisplay"
+                  >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name="com.jogamp.opengl.test.android.NEWTGearsES2ECTActivityLauncher"
+                  android:label="@string/activity_gearses2ect_name"
+                  android:description="@string/activity_gearses2ect_descr"
                   android:theme="@android:style/Theme.NoDisplay"
                   >
             <intent-filter>
@@ -38,7 +48,6 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-
         <activity android:name="com.jogamp.opengl.test.android.NEWTGearsES1ActivityLauncher"
                   android:label="@string/activity_gearses1_name"
                   android:description="@string/activity_gearses1_descr"
@@ -49,9 +58,20 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <activity android:name="com.jogamp.opengl.test.android.NEWTGearsES2ActivityLauncher"
-                  android:label="@string/activity_gearses2_name"
-                  android:description="@string/activity_gearses2_descr"
+
+        <activity android:name="com.jogamp.opengl.test.android.NEWTRedSquareES2ActivityLauncher"
+                  android:label="@string/activity_redsquarees2_name"
+                  android:description="@string/activity_redsquarees2_descr"
+                  android:theme="@android:style/Theme.NoDisplay"
+                  >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name="com.jogamp.opengl.test.android.NEWTRedSquareES1ActivityLauncher"
+                  android:label="@string/activity_redsquarees1_name"
+                  android:description="@string/activity_redsquarees1_descr"
                   android:theme="@android:style/Theme.NoDisplay"
                   >
             <intent-filter>
diff --git a/make/resources/android/res-test/values/strings.xml b/make/resources/android/res-test/values/strings.xml
index fcaf102..0b7bd2d 100644
--- a/make/resources/android/res-test/values/strings.xml
+++ b/make/resources/android/res-test/values/strings.xml
@@ -11,6 +11,10 @@
     <string name="activity_gearses1_descr">GearsES1</string>
     <string name="activity_gearses2_name">GearsES2</string>
     <string name="activity_gearses2_descr">GearsES2</string>
+    <string name="activity_gearses2rgb565_name">Gears565</string>
+    <string name="activity_gearses2rgb565_descr">Gears565</string>
+    <string name="activity_gearses2ect_name">GearsECT</string>
+    <string name="activity_gearses2ect_descr">GearsECT</string>
     <string name="activity_gearses2t_name">GearsES2T</string>
     <string name="activity_gearses2t_descr">GearsES2T</string>
     <string name="activity_graphui1p_name">GraphUI1p</string>
diff --git a/make/scripts/adb-launch-junit.sh b/make/scripts/adb-launch-junit.sh
new file mode 100644
index 0000000..e53e764
--- /dev/null
+++ b/make/scripts/adb-launch-junit.sh
@@ -0,0 +1,82 @@
+#! /bin/bash
+
+export HOST_UID=jogamp
+# jogamp02 - 10.1.0.122
+export HOST_IP=10.1.0.122
+#export HOST_IP=10.1.0.52
+export HOST_RSYNC_ROOT=PROJECTS/JOGL
+
+export TARGET_UID=jogamp
+#export TARGET_IP=panda02
+export TARGET_IP=jautab03
+export TARGET_ADB_PORT=5555
+export TARGET_ROOT=jogamp-test
+
+export BUILD_DIR=../build-android-armv6
+
+if [ -e /opt-linux-x86/android-sdk-linux_x86 ] ; then
+    export ANDROID_HOME=/opt-linux-x86/android-sdk-linux_x86
+    export PATH=$ANDROID_HOME/platform-tools:$PATH
+fi 
+
+#TSTCLASS=jogamp.android.launcher.LauncherUtil
+#TSTCLASS=com.jogamp.opengl.test.android.LauncherUtil
+#TSTCLASS=com.jogamp.android.launcher.NEWTLauncherMain
+#TSTCLASS=com.jogamp.nativewindow.NativeWindowVersion
+#TSTCLASS=com.jogamp.opengl.JoglVersion
+#TSTCLASS=com.jogamp.newt.NewtVersion
+#TSTCLASS=com.jogamp.newt.opengl.GLWindow
+#TSTCLASS=com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen01GLPBufferNEWT
+#TSTCLASS=com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLSimple01NEWT
+#TSTCLASS=com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState01NEWT
+#TSTCLASS=com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT
+#TSTCLASS=com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01
+#TSTCLASS=com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo01
+#TSTCLASS=com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo02
+#TSTCLASS=com.jogamp.opengl.test.junit.jogl.demos.gl2es1.gears.newt.TestGearsGL2ES1NEWT
+TSTCLASS=com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT
+
+#D_FLAGS="\&newt.debug=all\&jogl.debug=all\&nativewindow.debug=all"
+#D_FLAGS="\&newt.debug=all\&jogl.debug=all"
+#D_FLAGS="\&newt.debug=all"
+
+         
+M_FLAGS="\&arg=$TSTCLASS\
+\&arg=filtertrace=true\
+\&arg=haltOnError=false\
+\&arg=haltOnFailure=false\
+\&arg=showoutput=true\
+\&arg=outputtoformatters=true\
+\&arg=logfailedtests=true\
+\&arg=logtestlistenerevents=true\
+\&arg=formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter\
+\&arg=formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,/sdcard/$TARGET_ROOT/$TSTCLASS.xml\
+"
+
+LOGFILE=`basename $0 .sh`.log
+
+#adb -s $TARGET_IP:$TARGET_ADB_PORT uninstall jogamp.android.launcher
+#adb -s $TARGET_IP:$TARGET_ADB_PORT uninstall com.jogamp.common
+#adb -s $TARGET_IP:$TARGET_ADB_PORT install $BUILD_DIR/jogamp-android-launcher.apk
+#adb -s $TARGET_IP:$TARGET_ADB_PORT install $BUILD_DIR/gluegen-rt-android-armeabi.apk
+
+#adb -s $TARGET_IP:$TARGET_ADB_PORT uninstall javax.media.opengl
+#adb -s $TARGET_IP:$TARGET_ADB_PORT install $BUILD_DIR/jar/jogl-all-android-armeabi.apk
+
+#adb -s $TARGET_IP:$TARGET_ADB_PORT uninstall com.jogamp.opengl.test
+#adb -s $TARGET_IP:$TARGET_ADB_PORT install $BUILD_DIR/jar/jogl-test-android.apk
+
+SHELL_CMD="\
+cd /sdcard ; \
+if [ -e $TARGET_ROOT ] ; then rm -r $TARGET_ROOT ; fi ; \
+mkdir $TARGET_ROOT ; cd $TARGET_ROOT ; \
+setprop log.redirect-stdio true ; setprop log.redirect-stderr true ; \
+am kill-all ; \
+am start -W -S -a android.intent.action.MAIN -n jogamp.android.launcher/jogamp.android.launcher.MainLauncher -d launch://jogamp.org/org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner/?pkg=com.jogamp.opengl.test$D_FLAGS$M_FLAGS \
+"
+
+adb connect $TARGET_IP:$TARGET_ADB_PORT
+adb -s $TARGET_IP:$TARGET_ADB_PORT logcat -c
+adb -s $TARGET_IP:$TARGET_ADB_PORT shell $SHELL_CMD 2>&1 | tee $LOGFILE
+adb -s $TARGET_IP:$TARGET_ADB_PORT logcat -d 2>&1 | tee -a $LOGFILE
+
diff --git a/make/scripts/adb-launch-main.sh b/make/scripts/adb-launch-main.sh
index 6d67192..12dcab1 100644
--- a/make/scripts/adb-launch-main.sh
+++ b/make/scripts/adb-launch-main.sh
@@ -2,21 +2,21 @@
 
 export HOST_UID=jogamp
 # jogamp02 - 10.1.0.122
-#export HOST_IP=10.1.0.122
-export HOST_IP=10.1.0.52
+export HOST_IP=10.1.0.122
+#export HOST_IP=10.1.0.52
 export HOST_RSYNC_ROOT=PROJECTS/JOGL
 
 export TARGET_UID=jogamp
 #export TARGET_IP=panda02
-export TARGET_IP=jautab01
+export TARGET_IP=jautab03
 export TARGET_ADB_PORT=5555
-export TARGET_ROOT=/data/projects
+export TARGET_ROOT=jogamp-test
 
 export BUILD_DIR=../build-android-armv6
 
 if [ -e /opt-linux-x86/android-sdk-linux_x86 ] ; then
-    export ANDROID_SDK_HOME=/opt-linux-x86/android-sdk-linux_x86
-    export PATH=$ANDROID_SDK_HOME/platform-tools:$PATH
+    export ANDROID_HOME=/opt-linux-x86/android-sdk-linux_x86
+    export PATH=$ANDROID_HOME/platform-tools:$PATH
 fi 
 
 #TSTCLASS=jogamp.android.launcher.LauncherUtil
@@ -36,42 +36,38 @@ fi
 #TSTCLASS=com.jogamp.opengl.test.junit.jogl.demos.gl2es1.gears.newt.TestGearsGL2ES1NEWT
 TSTCLASS=com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT
 
+#D_FLAGS="\&newt.debug=all\&jogl.debug=all\&nativewindow.debug=all"
+#D_FLAGS="\&newt.debug=all\&jogl.debug=all"
+D_FLAGS="\&newt.debug=all"
+
+#Screen: 1280 x 752
+#M_FLAGS="\&arg=-time\&arg=100000\&arg=-width\&arg=1280\&arg=-height\&arg=752"
+M_FLAGS="\&arg=-time\&arg=100000\&arg=-fullscreen"
+
 LOGFILE=`basename $0 .sh`.log
 
-RSYNC_EXCLUDES="--delete-excluded \
-                --exclude 'build-x86*/' --exclude 'build-linux*/' --exclude 'build-win*/' --exclude 'build-mac*/' \
-                --exclude 'classes/' --exclude 'src/' --exclude '.git/' --exclude '*-java-src.zip' \
-                --exclude 'gensrc/' --exclude 'doc/' --exclude 'jnlp-files' --exclude 'archive/' \
-                --exclude 'android-sdk/' --exclude 'resources/' --exclude 'scripts/' \
-                --exclude 'stub_includes/' --exclude 'nbproject/' --exclude '*.log' --exclude '*.zip' --exclude '*.7z' \
-                --exclude 'make/lib/external/'"
+#adb -s $TARGET_IP:$TARGET_ADB_PORT uninstall jogamp.android.launcher
+#adb -s $TARGET_IP:$TARGET_ADB_PORT uninstall com.jogamp.common
+#adb -s $TARGET_IP:$TARGET_ADB_PORT install $BUILD_DIR/jogamp-android-launcher.apk
+#adb -s $TARGET_IP:$TARGET_ADB_PORT install $BUILD_DIR/gluegen-rt-android-armeabi.apk
 
-echo "#! /system/bin/sh" > $BUILD_DIR/jogl-targetcommand.sh
+#adb -s $TARGET_IP:$TARGET_ADB_PORT uninstall javax.media.opengl
+#adb -s $TARGET_IP:$TARGET_ADB_PORT install $BUILD_DIR/jar/jogl-all-android-armeabi.apk
 
-echo "\
-rsync -av --delete --delete-after $RSYNC_EXCLUDES \
-   $HOST_UID@$HOST_IP::$HOST_RSYNC_ROOT/gluegen \
-   $HOST_UID@$HOST_IP::$HOST_RSYNC_ROOT/jogl \
-   $TARGET_ROOT ; \
-cd $TARGET_ROOT/jogl/make ;
-export LD_LIBRARY_PATH=/system/lib:$TARGET_ROOT/gluegen/make/$BUILD_DIR/obj:$TARGET_ROOT/jogl/make/$BUILD_DIR/lib ; \
-# export BOOTCLASSPATH=/system/framework/core.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar ;
-setprop log.redirect-stdio true ; setprop log.redirect-stderr true ; \
-am start -a android.intent.action.MAIN -n jogamp.android.launcher/jogamp.android.launcher.MainLauncher -d launch://jogamp.org/$TSTCLASS/?pkg=com.jogamp.opengl.test\&newt.debug=all\&jogl.debug=all\&nativewindow.debug=all \
-# \
-#dalvikvm \
-#  -Xjnigreflimit:2000 \
-#  -cp ../../gluegen/make/$BUILD_DIR/jogamp.android-launcher.apk:../../gluegen/make/lib/ant-junit-all.apk:../../gluegen/make/$BUILD_DIR/gluegen-rt-android-armeabi.apk:$BUILD_DIR/jar/jogl.all-android-armeabi.apk:$BUILD_DIR/jar/jogl.test.apk \
-#  -Dgluegen.root=../../gluegen \
-#  -Drootrel.build=build-android-armv6 \
-#  com.android.internal.util.WithFramework \
-#  $TSTCLASS \
-" >> $BUILD_DIR/jogl-targetcommand.sh
+#adb -s $TARGET_IP:$TARGET_ADB_PORT uninstall com.jogamp.opengl.test
+#adb -s $TARGET_IP:$TARGET_ADB_PORT install $BUILD_DIR/jar/jogl-test-android.apk
 
+SHELL_CMD="\
+cd /sdcard ; \
+if [ -e $TARGET_ROOT ] ; then rm -r $TARGET_ROOT ; fi ; \
+mkdir $TARGET_ROOT ; cd $TARGET_ROOT ; \
+setprop log.redirect-stdio true ; setprop log.redirect-stderr true ; \
+am kill-all ; \
+am start -W -S -a android.intent.action.MAIN -n jogamp.android.launcher/jogamp.android.launcher.MainLauncher -d launch://jogamp.org/$TSTCLASS/?pkg=com.jogamp.opengl.test$D_FLAGS$M_FLAGS \
+"
 
-chmod ugo+x $BUILD_DIR/jogl-targetcommand.sh
 adb connect $TARGET_IP:$TARGET_ADB_PORT
-adb -s $TARGET_IP:$TARGET_ADB_PORT push $BUILD_DIR/jogl-targetcommand.sh $TARGET_ROOT/jogl-targetcommand.sh
-adb -s $TARGET_IP:$TARGET_ADB_PORT shell su -c $TARGET_ROOT/jogl-targetcommand.sh 2>&1 | tee $LOGFILE
-
+adb -s $TARGET_IP:$TARGET_ADB_PORT logcat -c
+adb -s $TARGET_IP:$TARGET_ADB_PORT shell $SHELL_CMD 2>&1 | tee $LOGFILE
+adb -s $TARGET_IP:$TARGET_ADB_PORT logcat -d 2>&1 | tee -a $LOGFILE
 
diff --git a/make/scripts/check-junit.sh b/make/scripts/check-junit.sh
index 474d074..232b3c6 100755
--- a/make/scripts/check-junit.sh
+++ b/make/scripts/check-junit.sh
@@ -35,4 +35,5 @@ function checkresult() {
 }
 
 checkresult results
+checkresult results-java7
 checkresult results-x32
diff --git a/make/scripts/java-win.bat b/make/scripts/java-win.bat
new file mode 100755
index 0000000..47b8184
--- /dev/null
+++ b/make/scripts/java-win.bat
@@ -0,0 +1,4 @@
+
+%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %D_ARGS% %X_ARGS% %* > java-win.log 2>&1
+tail java-win.log
+
diff --git a/make/scripts/java-win32.bat b/make/scripts/java-win32.bat
deleted file mode 100755
index d357157..0000000
--- a/make/scripts/java-win32.bat
+++ /dev/null
@@ -1,25 +0,0 @@
-
-set BLD_SUB=build-win32
-set J2RE_HOME=c:\jre1.6.0_35_x32
-set JAVA_HOME=c:\jdk1.6.0_35_x32
-set ANT_PATH=C:\apache-ant-1.8.2
-
-set PROJECT_ROOT=D:\projects\jogamp\jogl
-set BLD_DIR=..\%BLD_SUB%
-
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PATH%
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\angle\win32\20120127;%PATH%
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\angle\win32\20121010-chrome;%PATH%
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH%
-
-set BLD_DIR=..\%BLD_SUB%
-REM set LIB_DIR=..\..\gluegen\%BLD_SUB%\obj;%BLD_DIR%\lib
-REM set FFMPEG_LIB=%PROJECT_ROOT%\make\lib\ffmpeg\x32
-REM set LIB_DIR=%FFMPEG_LIB%
-set LIB_DIR=
-
-set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluegen\%BLD_SUB%\gluegen-rt.jar;..\..\gluegen\make\lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar;%BLD_DIR%\..\make\lib\swt\win32-win32-x86\swt-debug.jar
-
-echo CP_ALL %CP_ALL%
-
-%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" "-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true" %* > java-win32.log 2>&1
diff --git a/make/scripts/java-win64.bat b/make/scripts/java-win64.bat
deleted file mode 100755
index 99f9bdc..0000000
--- a/make/scripts/java-win64.bat
+++ /dev/null
@@ -1,19 +0,0 @@
-
-set BLD_SUB=build-win64
-set J2RE_HOME=c:\jre1.6.0_35_x64
-set JAVA_HOME=c:\jdk1.6.0_35_x64
-set ANT_PATH=C:\apache-ant-1.8.2
-
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_64;%PATH%
-
-set BLD_DIR=..\%BLD_SUB%
-REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj
-set LIB_DIR=
-
-set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluegen\%BLD_SUB%\gluegen-rt.jar;..\..\gluegen\make\lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar;%BLD_DIR%\..\make\lib\swt\win32-win32-x86_64\swt-debug.jar
-echo CP_ALL %CP_ALL%
-
-set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true"
-
-%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %X_ARGS% %* > java-win64.log 2>&1
diff --git a/make/scripts/lstjars.sh b/make/scripts/lstjars.sh
index 5763e41..2cb4e1b 100755
--- a/make/scripts/lstjars.sh
+++ b/make/scripts/lstjars.sh
@@ -107,11 +107,12 @@ mv nope/*.jar .
 listdeployment jar
 
 if [ $pack200 -eq 1 ] ; then
-    for i in *.jar ; do
+    for i in *.jar atomic/*jar ; do
         fname=$i
+        dname=$(dirname $fname)
         bname=$(basename $fname .jar)
-        echo pack200 $bname.pack.gz $fname
-        pack200 $bname.pack.gz $fname
+        echo pack200 $dname/$bname.pack.gz $fname
+        pack200 $dname/$bname.pack.gz $fname
     done
     listdeployment pack.gz
 fi
diff --git a/make/scripts/make.jogl.all.android-armv6-cross.sh b/make/scripts/make.jogl.all.android-armv6-cross.sh
index 2625600..2b8f9a3 100755
--- a/make/scripts/make.jogl.all.android-armv6-cross.sh
+++ b/make/scripts/make.jogl.all.android-armv6-cross.sh
@@ -1,5 +1,9 @@
 #! /bin/sh
 
+if [ -e $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh ] ; then
+    . $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh
+fi
+
 export NODE_LABEL=.
 
 export HOST_UID=jogamp
@@ -16,7 +20,7 @@ export TARGET_ADB_PORT=5555
 export TARGET_ROOT=/data/projects
 export TARGET_ANT_HOME=/usr/share/ant
 
-echo ANDROID_SDK_HOME $ANDROID_SDK_HOME
+echo ANDROID_HOME $ANDROID_HOME
 echo NDK_ROOT $NDK_ROOT
 
 if [ -z "$NDK_ROOT" ] ; then
@@ -30,14 +34,14 @@ if [ -z "$NDK_ROOT" ] ; then
     elif [ -e /opt/android-ndk ] ; then
         NDK_ROOT=/opt/android-ndk
     #
-    # Specific android-ndk-r7b
+    # Specific android-ndk-r8d
     #
-    elif [ -e /usr/local/android-ndk-r7b ] ; then
-        NDK_ROOT=/usr/local/android-ndk-r7b
-    elif [ -e /opt-linux-x86/android-ndk-r7b ] ; then
-        NDK_ROOT=/opt-linux-x86/android-ndk-r7b
-    elif [ -e /opt/android-ndk-r7b ] ; then
-        NDK_ROOT=/opt/android-ndk-r7b
+    elif [ -e /usr/local/android-ndk-r8d ] ; then
+        NDK_ROOT=/usr/local/android-ndk-r8d
+    elif [ -e /opt-linux-x86/android-ndk-r8d ] ; then
+        NDK_ROOT=/opt-linux-x86/android-ndk-r8d
+    elif [ -e /opt/android-ndk-r8d ] ; then
+        NDK_ROOT=/opt/android-ndk-r8d
     else 
         echo NDK_ROOT is not specified and does not exist in default locations
         exit 1
@@ -48,29 +52,30 @@ elif [ ! -e $NDK_ROOT ] ; then
 fi
 export NDK_ROOT
 
-if [ -z "$ANDROID_SDK_HOME" ] ; then
+if [ -z "$ANDROID_HOME" ] ; then
     if [ -e /usr/local/android-sdk-linux_x86 ] ; then
-        ANDROID_SDK_HOME=/usr/local/android-sdk-linux_x86
+        ANDROID_HOME=/usr/local/android-sdk-linux_x86
     elif [ -e /opt-linux-x86/android-sdk-linux_x86 ] ; then
-        ANDROID_SDK_HOME=/opt-linux-x86/android-sdk-linux_x86
+        ANDROID_HOME=/opt-linux-x86/android-sdk-linux_x86
     elif [ -e /opt/android-sdk-linux_x86 ] ; then
-        ANDROID_SDK_HOME=/opt/android-sdk-linux_x86
+        ANDROID_HOME=/opt/android-sdk-linux_x86
     else 
-        echo ANDROID_SDK_HOME is not specified and does not exist in default locations
+        echo ANDROID_HOME is not specified and does not exist in default locations
         exit 1
     fi
-elif [ ! -e $ANDROID_SDK_HOME ] ; then
-    echo ANDROID_SDK_HOME $ANDROID_SDK_HOME does not exist
+elif [ ! -e $ANDROID_HOME ] ; then
+    echo ANDROID_HOME $ANDROID_HOME does not exist
     exit 1
 fi
-export ANDROID_SDK_HOME
+export ANDROID_HOME
 
 export ANDROID_VERSION=9
 export SOURCE_LEVEL=1.6
 export TARGET_LEVEL=1.6
 export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
 
-export GCC_VERSION=4.4.3
+#export GCC_VERSION=4.4.3
+export GCC_VERSION=4.7
 HOST_ARCH=linux-x86
 export TARGET_TRIPLE=arm-linux-androideabi
 
@@ -78,13 +83,16 @@ export NDK_TOOLCHAIN_ROOT=$NDK_ROOT/toolchains/${TARGET_TRIPLE}-${GCC_VERSION}/p
 export TARGET_PLATFORM_ROOT=${NDK_ROOT}/platforms/android-${ANDROID_VERSION}/arch-arm
 
 # Need to add toolchain bins to the PATH. 
-export PATH="$NDK_TOOLCHAIN_ROOT/$TARGET_TRIPLE/bin:$ANDROID_SDK_HOME/platform-tools:$PATH"
+export PATH="$NDK_TOOLCHAIN_ROOT/$TARGET_TRIPLE/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/17.0.0:$PATH"
 
 export GLUEGEN_CPPTASKS_FILE=`pwd`/../../gluegen/make/lib/gluegen-cpptasks-android-armv6.xml
 
 #export JUNIT_DISABLED="true"
 #export JUNIT_RUN_ARG0="-Dnewt.test.Screen.disableScreenMode"
 
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
 # BUILD_ARCHIVE=true \
 ant \
     -Drootrel.build=build-android-armv6 \
diff --git a/make/scripts/make.jogl.all.android-armv7-cross.sh b/make/scripts/make.jogl.all.android-armv7-cross.sh
index 4c4ea4c..fd7bf20 100755
--- a/make/scripts/make.jogl.all.android-armv7-cross.sh
+++ b/make/scripts/make.jogl.all.android-armv7-cross.sh
@@ -1,5 +1,9 @@
 #! /bin/sh
 
+if [ -e $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh ] ; then
+    . $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh
+fi
+
 export NODE_LABEL=.
 
 export HOST_UID=jogamp
@@ -16,7 +20,7 @@ export TARGET_ADB_PORT=5555
 export TARGET_ROOT=/data/projects
 export TARGET_ANT_HOME=/usr/share/ant
 
-echo ANDROID_SDK_HOME $ANDROID_SDK_HOME
+echo ANDROID_HOME $ANDROID_HOME
 echo NDK_ROOT $NDK_ROOT
 
 if [ -z "$NDK_ROOT" ] ; then
@@ -30,14 +34,14 @@ if [ -z "$NDK_ROOT" ] ; then
     elif [ -e /opt/android-ndk ] ; then
         NDK_ROOT=/opt/android-ndk
     #
-    # Specific android-ndk-r7b
+    # Specific android-ndk-r8d
     #
-    elif [ -e /usr/local/android-ndk-r7b ] ; then
-        NDK_ROOT=/usr/local/android-ndk-r7b
-    elif [ -e /opt-linux-x86/android-ndk-r7b ] ; then
-        NDK_ROOT=/opt-linux-x86/android-ndk-r7b
-    elif [ -e /opt/android-ndk-r7b ] ; then
-        NDK_ROOT=/opt/android-ndk-r7b
+    elif [ -e /usr/local/android-ndk-r8d ] ; then
+        NDK_ROOT=/usr/local/android-ndk-r8d
+    elif [ -e /opt-linux-x86/android-ndk-r8d ] ; then
+        NDK_ROOT=/opt-linux-x86/android-ndk-r8d
+    elif [ -e /opt/android-ndk-r8d ] ; then
+        NDK_ROOT=/opt/android-ndk-r8d
     else 
         echo NDK_ROOT is not specified and does not exist in default locations
         exit 1
@@ -48,29 +52,30 @@ elif [ ! -e $NDK_ROOT ] ; then
 fi
 export NDK_ROOT
 
-if [ -z "$ANDROID_SDK_HOME" ] ; then
+if [ -z "$ANDROID_HOME" ] ; then
     if [ -e /usr/local/android-sdk-linux_x86 ] ; then
-        ANDROID_SDK_HOME=/usr/local/android-sdk-linux_x86
+        ANDROID_HOME=/usr/local/android-sdk-linux_x86
     elif [ -e /opt-linux-x86/android-sdk-linux_x86 ] ; then
-        ANDROID_SDK_HOME=/opt-linux-x86/android-sdk-linux_x86
+        ANDROID_HOME=/opt-linux-x86/android-sdk-linux_x86
     elif [ -e /opt/android-sdk-linux_x86 ] ; then
-        ANDROID_SDK_HOME=/opt/android-sdk-linux_x86
+        ANDROID_HOME=/opt/android-sdk-linux_x86
     else 
-        echo ANDROID_SDK_HOME is not specified and does not exist in default locations
+        echo ANDROID_HOME is not specified and does not exist in default locations
         exit 1
     fi
-elif [ ! -e $ANDROID_SDK_HOME ] ; then
-    echo ANDROID_SDK_HOME $ANDROID_SDK_HOME does not exist
+elif [ ! -e $ANDROID_HOME ] ; then
+    echo ANDROID_HOME $ANDROID_HOME does not exist
     exit 1
 fi
-export ANDROID_SDK_HOME
+export ANDROID_HOME
 
 export ANDROID_VERSION=9
 export SOURCE_LEVEL=1.6
 export TARGET_LEVEL=1.6
 export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
 
-export GCC_VERSION=4.4.3
+#export GCC_VERSION=4.4.3
+export GCC_VERSION=4.7
 HOST_ARCH=linux-x86
 export TARGET_TRIPLE=arm-linux-androideabi
 
@@ -78,13 +83,16 @@ export NDK_TOOLCHAIN_ROOT=$NDK_ROOT/toolchains/${TARGET_TRIPLE}-${GCC_VERSION}/p
 export TARGET_PLATFORM_ROOT=${NDK_ROOT}/platforms/android-${ANDROID_VERSION}/arch-arm
 
 # Need to add toolchain bins to the PATH. 
-export PATH="$NDK_TOOLCHAIN_ROOT/$TARGET_TRIPLE/bin:$ANDROID_SDK_HOME/platform-tools:$PATH"
+export PATH="$NDK_TOOLCHAIN_ROOT/$TARGET_TRIPLE/bin:$ANDROID_HOME/platform-tools:$PATH"
 
 export GLUEGEN_CPPTASKS_FILE=`pwd`/../../gluegen/make/lib/gluegen-cpptasks-android-armv7.xml
 
 #export JUNIT_DISABLED="true"
 #export JUNIT_RUN_ARG0="-Dnewt.test.Screen.disableScreenMode"
 
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
 # BUILD_ARCHIVE=true \
 ant \
     -Drootrel.build=build-android-armv7 \
diff --git a/make/scripts/make.jogl.all.linux-armv6-cross.sh b/make/scripts/make.jogl.all.linux-armv6-cross.sh
index 9f31b79..acfc964 100755
--- a/make/scripts/make.jogl.all.linux-armv6-cross.sh
+++ b/make/scripts/make.jogl.all.linux-armv6-cross.sh
@@ -7,7 +7,7 @@ if [ -e $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh ] ; then
 fi
 
 # arm-linux-gnueabi == armel triplet
-PATH=`pwd`/../../gluegen/make/lib/linux/arm-linux-gnueabi/bin:$PATH
+PATH=`pwd`/../../gluegen/make/lib/toolchain/armsf-linux-gnueabi/bin:$PATH
 export PATH
 
 #    -Dc.compiler.debug=true 
@@ -38,6 +38,13 @@ export GLUEGEN_CPPTASKS_FILE="../../gluegen/make/lib/gluegen-cpptasks-linux-armv
 #export JUNIT_DISABLED="true"
 export JUNIT_RUN_ARG0="-Dnewt.test.Screen.disableScreenMode"
 
+export SOURCE_LEVEL=1.6
+export TARGET_LEVEL=1.6
+export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
+
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
 ant \
     -Drootrel.build=build-linux-armv6 \
     \
@@ -47,5 +54,3 @@ ant \
     $* 2>&1 | tee make.jogl.all.linux-armv6-cross.log
 
 
-
-
diff --git a/make/scripts/make.jogl.all.linux-armv6.sh b/make/scripts/make.jogl.all.linux-armv6.sh
index 3d526ea..561da23 100755
--- a/make/scripts/make.jogl.all.linux-armv6.sh
+++ b/make/scripts/make.jogl.all.linux-armv6.sh
@@ -1,7 +1,7 @@
 #! /bin/sh
 
 # arm-linux-gnueabi == armel triplet
-PATH=`pwd`/../../gluegen/make/lib/linux/arm-linux-gnueabi/bin:$PATH
+PATH=`pwd`/../../gluegen/make/lib/toolchain/armsf-linux-gnueabi/bin:$PATH
 export PATH
 
 #    -Dc.compiler.debug=true 
@@ -17,6 +17,9 @@ export TARGET_JAVA_LIBS=/usr/lib/jvm/default-java/jre/lib/arm
 
 export GLUEGEN_CPPTASKS_FILE="../../gluegen/make/lib/gluegen-cpptasks-linux-armv6.xml"
 
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
 ant \
     -Drootrel.build=build-linux-armv6 \
     -Dsetup.addNativeKD=true \
diff --git a/make/scripts/make.jogl.all.linux-armv6hf-cross.sh b/make/scripts/make.jogl.all.linux-armv6hf-cross.sh
index 6295a90..0592f9a 100755
--- a/make/scripts/make.jogl.all.linux-armv6hf-cross.sh
+++ b/make/scripts/make.jogl.all.linux-armv6hf-cross.sh
@@ -7,7 +7,7 @@ if [ -e $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh ] ; then
 fi
 
 # arm-linux-gnueabihf == armel triplet
-PATH=`pwd`/../../gluegen/make/lib/linux/arm-linux-gnueabihf/bin:$PATH
+PATH=`pwd`/../../gluegen/make/lib/toolchain/armhf-linux-gnueabi/bin:$PATH
 export PATH
 
 #    -Dc.compiler.debug=true 
@@ -38,6 +38,13 @@ export GLUEGEN_CPPTASKS_FILE="../../gluegen/make/lib/gluegen-cpptasks-linux-armv
 #export JUNIT_DISABLED="true"
 export JUNIT_RUN_ARG0="-Dnewt.test.Screen.disableScreenMode"
 
+export SOURCE_LEVEL=1.6
+export TARGET_LEVEL=1.6
+export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
+
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
 ant \
     -Drootrel.build=build-linux-armv6hf \
     \
diff --git a/make/scripts/make.jogl.all.linux-armv6hf.sh b/make/scripts/make.jogl.all.linux-armv6hf.sh
index 7d9480f..aeaea03 100755
--- a/make/scripts/make.jogl.all.linux-armv6hf.sh
+++ b/make/scripts/make.jogl.all.linux-armv6hf.sh
@@ -1,7 +1,7 @@
 #! /bin/sh
 
 # arm-linux-gnueabihf == armhf triplet
-PATH=`pwd`/../../gluegen/make/lib/linux/arm-linux-gnueabihf/bin:$PATH
+PATH=`pwd`/../../gluegen/make/lib/toolchain/armhf-linux-gnueabi/bin:$PATH
 export PATH
 
 #    -Dc.compiler.debug=true 
@@ -17,6 +17,9 @@ export TARGET_JAVA_LIBS=/usr/lib/jvm/java-6-openjdk-armhf/jre/lib/arm
 
 export GLUEGEN_CPPTASKS_FILE="../../gluegen/make/lib/gluegen-cpptasks-linux-armv6hf.xml"
 
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
 ant \
     -Drootrel.build=build-linux-armv6hf \
     -Dsetup.addNativeKD=true \
diff --git a/make/scripts/make.jogl.all.linux-x86.sh b/make/scripts/make.jogl.all.linux-x86.sh
index b79fffe..f3ae281 100755
--- a/make/scripts/make.jogl.all.linux-x86.sh
+++ b/make/scripts/make.jogl.all.linux-x86.sh
@@ -41,6 +41,14 @@ echo LIBGL_DEBUG: $LIBGL_DEBUG 2>&1 | tee -a $LOGF
 #    -Dgluegen-cpptasks.file=`pwd`/../../gluegen/make/lib/gluegen-cpptasks-linux-32bit.xml \
 #
 
+export SOURCE_LEVEL=1.6
+export TARGET_LEVEL=1.6
+export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
+
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
+
 ant \
     $CUSTOMLIBDIR \
     -Drootrel.build=build-x86 \
diff --git a/make/scripts/make.jogl.all.linux-x86_64.sh b/make/scripts/make.jogl.all.linux-x86_64.java7.sh
similarity index 80%
copy from make/scripts/make.jogl.all.linux-x86_64.sh
copy to make/scripts/make.jogl.all.linux-x86_64.java7.sh
index 4642326..17865bd 100755
--- a/make/scripts/make.jogl.all.linux-x86_64.sh
+++ b/make/scripts/make.jogl.all.linux-x86_64.java7.sh
@@ -6,6 +6,7 @@ if [ -e $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh ] ; then
     . $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh
 fi
 
+
 if [ "$1" = "-libdir" ] ; then
     shift
     if [ -z "$1" ] ; then
@@ -28,12 +29,15 @@ fi
 #    -Dtarget.sourcelevel=1.6 \
 #    -Dtarget.targetlevel=1.6 \
 #    -Dtarget.rt.jar=/opt-share/jre1.6.0_30/lib/rt.jar \
+#
+#    -Dsetup.addNativeOpenMAX=true \
+#    -Dsetup.addNativeKD=true \
 
 
 #LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64
 #export LD_LIBRARY_PATH
 
-LOGF=make.jogl.all.linux-x86_64.log
+LOGF=make.jogl.all.linux-x86_64.java7.log
 rm -f $LOGF
 
 # export LIBGL_DRIVERS_PATH=/usr/lib/fglrx/dri:/usr/lib32/fglrx/dri
@@ -42,6 +46,9 @@ echo LIBXCB_ALLOW_SLOPPY_LOCK: $LIBXCB_ALLOW_SLOPPY_LOCK 2>&1 | tee -a $LOGF
 echo LIBGL_DRIVERS_PATH: $LIBGL_DRIVERS_PATH 2>&1 | tee -a $LOGF
 echo LIBGL_DEBUG: $LIBGL_DEBUG 2>&1 | tee -a $LOGF
 
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
 #    -Dc.compiler.debug=true \
 #    -Djavacdebug="true" \
 #    -Djavacdebuglevel="source,lines,vars" \
@@ -49,12 +56,6 @@ echo LIBGL_DEBUG: $LIBGL_DEBUG 2>&1 | tee -a $LOGF
 # BUILD_ARCHIVE=true \
 ant  \
     $CUSTOMLIBDIR \
-    -Dtarget.sourcelevel=1.6 \
-    -Dtarget.targetlevel=1.6 \
-    -Dtarget.rt.jar=/opt-share/jre1.6.0_30/lib/rt.jar \
-    -Djavacdebuglevel="source,lines,vars" \
-    -Drootrel.build=build-x86_64 \
-    -Dsetup.addNativeOpenMAX=true \
-    -Dsetup.addNativeKD=true \
+    -Drootrel.build=build-x86_64.java7 \
     $* 2>&1 | tee -a $LOGF
 
diff --git a/make/scripts/make.jogl.all.linux-x86_64.sh b/make/scripts/make.jogl.all.linux-x86_64.sh
index 4642326..2488a7d 100755
--- a/make/scripts/make.jogl.all.linux-x86_64.sh
+++ b/make/scripts/make.jogl.all.linux-x86_64.sh
@@ -28,6 +28,9 @@ fi
 #    -Dtarget.sourcelevel=1.6 \
 #    -Dtarget.targetlevel=1.6 \
 #    -Dtarget.rt.jar=/opt-share/jre1.6.0_30/lib/rt.jar \
+#
+#    -Dsetup.addNativeOpenMAX=true \
+#    -Dsetup.addNativeKD=true \
 
 
 #LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64
@@ -42,19 +45,16 @@ echo LIBXCB_ALLOW_SLOPPY_LOCK: $LIBXCB_ALLOW_SLOPPY_LOCK 2>&1 | tee -a $LOGF
 echo LIBGL_DRIVERS_PATH: $LIBGL_DRIVERS_PATH 2>&1 | tee -a $LOGF
 echo LIBGL_DEBUG: $LIBGL_DEBUG 2>&1 | tee -a $LOGF
 
-#    -Dc.compiler.debug=true \
-#    -Djavacdebug="true" \
-#    -Djavacdebuglevel="source,lines,vars" \
+export SOURCE_LEVEL=1.6
+export TARGET_LEVEL=1.6
+export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
+
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
 
 # BUILD_ARCHIVE=true \
 ant  \
     $CUSTOMLIBDIR \
-    -Dtarget.sourcelevel=1.6 \
-    -Dtarget.targetlevel=1.6 \
-    -Dtarget.rt.jar=/opt-share/jre1.6.0_30/lib/rt.jar \
-    -Djavacdebuglevel="source,lines,vars" \
     -Drootrel.build=build-x86_64 \
-    -Dsetup.addNativeOpenMAX=true \
-    -Dsetup.addNativeKD=true \
     $* 2>&1 | tee -a $LOGF
 
diff --git a/make/scripts/make.jogl.all.macosx-java7.sh b/make/scripts/make.jogl.all.macosx-java7.sh
new file mode 100755
index 0000000..ee82bbc
--- /dev/null
+++ b/make/scripts/make.jogl.all.macosx-java7.sh
@@ -0,0 +1,22 @@
+#! /bin/sh
+
+if [ -e /opt-share/etc/profile.ant ] ; then
+    . /opt-share/etc/profile.ant
+fi
+
+
+#    -Dc.compiler.debug=true \
+#    -Djavacdebug="true" \
+#    -Djavacdebuglevel="source,lines,vars" \
+#
+
+JAVA_HOME=`/usr/libexec/java_home -version 1.7`
+PATH=$JAVA_HOME/bin:$PATH
+export JAVA_HOME PATH
+
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
+ant \
+    -Drootrel.build=build-macosx-java7 \
+    $* 2>&1 | tee make.jogl.all.macosx-java7.log
diff --git a/make/scripts/make.jogl.all.macosx.sh b/make/scripts/make.jogl.all.macosx.sh
index 23a276c..c80b41d 100755
--- a/make/scripts/make.jogl.all.macosx.sh
+++ b/make/scripts/make.jogl.all.macosx.sh
@@ -4,19 +4,23 @@ if [ -e /opt-share/etc/profile.ant ] ; then
     . /opt-share/etc/profile.ant
 fi
 
+JAVA_HOME=`/usr/libexec/java_home -version 1.7`
+PATH=$JAVA_HOME/bin:$PATH
+export JAVA_HOME PATH
+
 
 #    -Dc.compiler.debug=true \
 #    -Djavacdebug="true" \
 #    -Djavacdebuglevel="source,lines,vars" \
 #
-#    -Dtarget.sourcelevel=1.6 \
-#    -Dtarget.targetlevel=1.6 \
-#    -Dtarget.rt.jar=/opt-share/jre1.6.0_30/lib/rt.jar \
 
+export SOURCE_LEVEL=1.6
+export TARGET_LEVEL=1.6
+export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
+
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
 
 ant \
-    -Dtarget.sourcelevel=1.6 \
-    -Dtarget.targetlevel=1.6 \
-    -Dtarget.rt.jar=/opt-share/jre1.6.0_30/lib/rt.jar \
     -Drootrel.build=build-macosx \
     $* 2>&1 | tee make.jogl.all.macosx.log
diff --git a/make/scripts/make.jogl.all.sh b/make/scripts/make.jogl.all.sh
new file mode 100755
index 0000000..67d965d
--- /dev/null
+++ b/make/scripts/make.jogl.all.sh
@@ -0,0 +1,9 @@
+#! /bin/sh
+
+SDIR=`dirname $0` 
+
+$SDIR/make.jogl.all.linux-armv6-cross.sh \
+&& $SDIR/make.jogl.all.linux-armv6hf-cross.sh \
+&& $SDIR/make.jogl.all.linux-x86_64.sh \
+&& $SDIR/make.jogl.all.linux-x86.sh \
+&& $SDIR/make.jogl.all.android-armv6-cross.sh \
diff --git a/make/scripts/make.jogl.all.solaris-x86.sh b/make/scripts/make.jogl.all.solaris-x86.sh
index a5b99e4..d1a767c 100755
--- a/make/scripts/make.jogl.all.solaris-x86.sh
+++ b/make/scripts/make.jogl.all.solaris-x86.sh
@@ -41,6 +41,13 @@ echo LIBGL_DEBUG: $LIBGL_DEBUG 2>&1 | tee -a $LOGF
 #    -Djavacdebug="true" \
 #    -Djavacdebuglevel="source,lines,vars" \
 
+export SOURCE_LEVEL=1.6
+export TARGET_LEVEL=1.6
+export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
+
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
 # BUILD_ARCHIVE=true \
 ant  \
     $CUSTOMLIBDIR \
diff --git a/make/scripts/make.jogl.all.solaris-x86_64.sh b/make/scripts/make.jogl.all.solaris-x86_64.sh
index ff60319..9dc492e 100755
--- a/make/scripts/make.jogl.all.solaris-x86_64.sh
+++ b/make/scripts/make.jogl.all.solaris-x86_64.sh
@@ -41,6 +41,13 @@ echo LIBGL_DEBUG: $LIBGL_DEBUG 2>&1 | tee -a $LOGF
 #    -Djavacdebug="true" \
 #    -Djavacdebuglevel="source,lines,vars" \
 
+export SOURCE_LEVEL=1.6
+export TARGET_LEVEL=1.6
+export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
+
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
 # BUILD_ARCHIVE=true \
 ant  \
     $CUSTOMLIBDIR \
diff --git a/make/scripts/make.jogl.all.win32.bat b/make/scripts/make.jogl.all.win32.bat
index c4c80a7..7b0243f 100755
--- a/make/scripts/make.jogl.all.win32.bat
+++ b/make/scripts/make.jogl.all.win32.bat
@@ -1,7 +1,7 @@
 set THISDIR="C:\JOGL"
 
-set J2RE_HOME=c:\jre1.6.0_35_x32
-set JAVA_HOME=c:\jdk1.6.0_35_x32
+set J2RE_HOME=c:\jre1.7.0_25_x32
+set JAVA_HOME=c:\jdk1.7.0_25_x32
 set ANT_PATH=C:\apache-ant-1.8.2
 
 set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
@@ -12,4 +12,11 @@ REM    -Dc.compiler.debug=true
 REM    -Dsetup.addNativeOpenMAX=true 
 REM    -Dsetup.addNativeKD=true
 
+set SOURCE_LEVEL=1.6
+set TARGET_LEVEL=1.6
+set TARGET_RT_JAR=c:\jre1.6.0_30\lib\rt.jar
+
+REM set JOGAMP_JAR_CODEBASE=Codebase: *.jogamp.org
+set JOGAMP_JAR_CODEBASE=Codebase: *.goethel.localnet
+
 ant -Drootrel.build=build-win32 %1 %2 %3 %4 %5 %6 %7 %8 %9 > make.jogl.all.win32.log 2>&1
diff --git a/make/scripts/make.jogl.all.win64.bat b/make/scripts/make.jogl.all.win64.bat
index 7355c6a..c08c526 100755
--- a/make/scripts/make.jogl.all.win64.bat
+++ b/make/scripts/make.jogl.all.win64.bat
@@ -1,15 +1,22 @@
 set THISDIR="C:\JOGL"
 
-set J2RE_HOME=c:\jre1.6.0_35_x64
-set JAVA_HOME=c:\jdk1.6.0_35_x64
+set J2RE_HOME=c:\jre1.7.0_25_x64
+set JAVA_HOME=c:\jdk1.7.0_25_x64
 set ANT_PATH=C:\apache-ant-1.8.2
 
 set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw64\bin;%PATH%
 
-set LIB_GEN=%THISDIR%\lib
-set CLASSPATH=.;%THISDIR%\build-win64\classes
+REM set LIB_GEN=%THISDIR%\lib
+REM set CLASSPATH=.;%THISDIR%\build-win64\classes
 REM    -Dc.compiler.debug=true 
 REM    -Dsetup.addNativeOpenMAX=true 
 REM    -Dsetup.addNativeKD=true
 
+set SOURCE_LEVEL=1.6
+set TARGET_LEVEL=1.6
+set TARGET_RT_JAR=c:\jre1.6.0_30\lib\rt.jar
+
+REM set JOGAMP_JAR_CODEBASE=Codebase: *.jogamp.org
+set JOGAMP_JAR_CODEBASE=Codebase: *.goethel.localnet
+
 ant -Dc.compiler.debug=true -Drootrel.build=build-win64 %1 %2 %3 %4 %5 %6 %7 %8 %9 > make.jogl.all.win64.log 2>&1
diff --git a/make/scripts/setenv-jogl.sh b/make/scripts/setenv-jogl.sh
index 4067e65..5e4bb57 100755
--- a/make/scripts/setenv-jogl.sh
+++ b/make/scripts/setenv-jogl.sh
@@ -14,7 +14,7 @@ if [ -e /opt-share/etc/profile.ant ] ; then
     . /opt-share/etc/profile.ant
 fi
 
-JOGL_BUILDDIR=$1
+JOGL_BUILDDIR="$1"
 shift
 
 if [ -z "$1" ] ; then
@@ -27,17 +27,17 @@ fi
 THISDIR=`pwd`
 
 if [ -e "$JOGL_BUILDDIR" ] ; then
-    JOGL_DIR=$JOGL_BUILDDIR/..
-    JOGL_BUILDDIR_BASE=`basename $JOGL_BUILDDIR`
+    JOGL_DIR="$JOGL_BUILDDIR/.."
+    JOGL_BUILDDIR_BASE=`basename "$JOGL_BUILDDIR"`
 else
-    echo JOGL_BUILDDIR $JOGL_BUILDDIR not exist or not given
+    echo JOGL_BUILDDIR "$JOGL_BUILDDIR" not exist or not given
     print_usage
     exit
 fi
 
-gpf=`find ../../gluegen/make -name dynlink-unix.cfg`
+gpf=`find ../../gluegen/make -name jogamp-env.xml`
 if [ -z "$gpf" ] ; then
-    gpf=`find .. -name dynlink-unix.cfg`
+    gpf=`find .. -name jogamp-env.xml`
 fi
 if [ -z "$gpf" ] ; then
     echo GLUEGEN_BUILDDIR not found
@@ -46,15 +46,34 @@ if [ -z "$gpf" ] ; then
 fi
 
 GLUEGEN_DIR=`dirname $gpf`/..
-GLUEGEN_BUILDDIR=$GLUEGEN_DIR/$JOGL_BUILDDIR_BASE
+GLUEGEN_BUILDDIR="$GLUEGEN_DIR"/"$JOGL_BUILDDIR_BASE"
 if [ ! -e "$GLUEGEN_BUILDDIR" ] ; then
-    echo GLUEGEN_BUILDDIR $GLUEGEN_BUILDDIR does not exist
+    echo GLUEGEN_BUILDDIR "$GLUEGEN_BUILDDIR" does not exist
     print_usage
     exit
 fi
-GLUEGEN_JAR=$GLUEGEN_BUILDDIR/gluegen-rt.jar
-GLUEGEN_OS=$GLUEGEN_BUILDDIR/obj
-JUNIT_JAR=$GLUEGEN_DIR/make/lib/junit.jar
+GLUEGEN_JAR="$GLUEGEN_BUILDDIR"/gluegen-rt.jar
+GLUEGEN_OS="$GLUEGEN_BUILDDIR"/obj
+JUNIT_JAR="$GLUEGEN_DIR"/make/lib/junit.jar
+
+joalpf=`find ../../joal -name joal.iml`
+if [ -z "$joalpf" ] ; then
+    joalpf=`find .. -name joal.iml`
+fi
+if [ -z "$joalpf" ] ; then
+    echo JOAL_BUILDDIR not found
+    print_usage
+    exit
+fi
+
+JOAL_DIR=`dirname $joalpf`
+JOAL_BUILDDIR="$JOAL_DIR"/"$JOGL_BUILDDIR_BASE"
+if [ ! -e "$JOAL_BUILDDIR" ] ; then
+    echo JOAL_BUILDDIR "$JOAL_BUILDDIR" does not exist
+    print_usage
+    exit
+fi
+JOAL_JAR="$JOAL_BUILDDIR"/joal.jar
 
 if [ -z "$ANT_PATH" ] ; then
     ANT_PATH=$(dirname $(dirname $(which ant)))
@@ -70,36 +89,37 @@ if [ -z "$ANT_PATH" ] ; then
 fi
 ANT_JARS=$ANT_PATH/lib/ant.jar:$ANT_PATH/lib/ant-junit.jar
 
-echo GLUEGEN BUILDDIR: $GLUEGEN_BUILDDIR
-echo JOGL DIR: $JOGL_DIR
-echo JOGL BUILDDIR: $JOGL_BUILDDIR
-echo JOGL BUILDDIR BASE: $JOGL_BUILDDIR_BASE
-echo JOGL PROFILE: $JOGL_PROFILE
+echo GLUEGEN BUILDDIR: "$GLUEGEN_BUILDDIR"
+echo JOAL BUILDDIR: "$JOAL_BUILDDIR"
+echo JOGL DIR: "$JOGL_DIR"
+echo JOGL BUILDDIR: "$JOGL_BUILDDIR"
+echo JOGL BUILDDIR BASE: "$JOGL_BUILDDIR_BASE"
+echo JOGL PROFILE: "$JOGL_PROFILE"
 
 J2RE_HOME=$(dirname $(dirname $(which java)))
 JAVA_HOME=$(dirname $(dirname $(which javac)))
 CP_SEP=:
 
-. $JOGL_DIR/etc/profile.jogl $JOGL_PROFILE $JOGL_BUILDDIR 
+. "$JOGL_DIR"/etc/profile.jogl $JOGL_PROFILE "$JOGL_BUILDDIR"
 
 LIB=$THISDIR/lib
 
-JOGAMP_ALL_AWT_CLASSPATH=.:$GLUEGEN_JAR:$JOGL_ALL_AWT_CLASSPATH:$SWT_CLASSPATH:$JUNIT_JAR:$ANT_JARS
-JOGAMP_ALL_NOAWT_CLASSPATH=.:$GLUEGEN_JAR:$JOGL_ALL_NOAWT_CLASSPATH:$SWT_CLASSPATH:$JUNIT_JAR:$ANT_JARS
-JOGAMP_MOBILE_CLASSPATH=.:$GLUEGEN_JAR:$JOGL_MOBILE_CLASSPATH:$SWT_CLASSPATH:$JUNIT_JAR:$ANT_JARS
+JOGAMP_ALL_AWT_CLASSPATH=.:"$GLUEGEN_JAR":"$JOAL_JAR":"$JOGL_ALL_AWT_CLASSPATH":"$SWT_CLASSPATH":"$JUNIT_JAR":"$ANT_JARS"
+JOGAMP_ALL_NOAWT_CLASSPATH=.:"$GLUEGEN_JAR":"$JOAL_JAR":"$JOGL_ALL_NOAWT_CLASSPATH":"$SWT_CLASSPATH":"$JUNIT_JAR":"$ANT_JARS"
+JOGAMP_MOBILE_CLASSPATH=.:"$GLUEGEN_JAR":"$JOAL_JAR":"$JOGL_MOBILE_CLASSPATH":"$SWT_CLASSPATH":"$JUNIT_JAR":"$ANT_JARS"
 export JOGAMP_ALL_AWT_CLASSPATH JOGAMP_ALL_NOAWT_CLASSPATH JOGAMP_MOBILE_CLASSPATH
 
-CLASSPATH=.:$GLUEGEN_JAR:$JOGL_CLASSPATH:$SWT_CLASSPATH:$JUNIT_JAR:$ANT_JARS
+CLASSPATH=.:"$GLUEGEN_JAR":"$JOAL_JAR":"$JOGL_CLASSPATH":"$SWT_CLASSPATH":"$JUNIT_JAR":"$ANT_JARS"
 export CLASSPATH
 
 # We use TempJarCache per default now!
-export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GLUEGEN_OS:$JOGL_LIB_DIR
-export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$GLUEGEN_OS:$JOGL_LIB_DIR
+export LD_LIBRARY_PATH="$LD_LIBRARY_PATH":"$GLUEGEN_OS":"$JOGL_LIB_DIR"
+export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH":"$GLUEGEN_OS:"$JOGL_LIB_DIR"
 
-echo JOGAMP_ALL_AWT_CLASSPATH: $CLASSPATH
-echo JOGAMP_ALL_NOAWT_CLASSPATH: $CLASSPATH
-echo JOGAMP_MOBILE_CLASSPATH: $CLASSPATH
-echo CLASSPATH: $CLASSPATH
+echo JOGAMP_ALL_AWT_CLASSPATH: "$JOGAMP_ALL_AWT_CLASSPATH"
+echo JOGAMP_ALL_NOAWT_CLASSPATH: "$JOGAMP_ALL_NOAWT_CLASSPATH"
+echo JOGAMP_MOBILE_CLASSPATH: "$JOGAMP_MOBILE_CLASSPATH"
+echo CLASSPATH: "$CLASSPATH"
 echo
 echo MacOSX REMEMBER to add the JVM arguments "-XstartOnFirstThread -Djava.awt.headless=true" for running demos without AWT, e.g. NEWT
 echo MacOSX REMEMBER to add the JVM arguments "-XstartOnFirstThread -Djava.awt.headless=true com.jogamp.newt.util.MainThread" for running demos with NEWT
diff --git a/make/scripts/tests-javaws-x64.bat b/make/scripts/tests-javaws-x64.bat
index deef4ca..c14ea5f 100755
--- a/make/scripts/tests-javaws-x64.bat
+++ b/make/scripts/tests-javaws-x64.bat
@@ -1,4 +1,4 @@
-set JRE_PATH=C:\jre1.6.0_35_x64\bin
+set JRE_PATH=C:\jre1.7.0_25_x64\bin
 set LOG_PATH=%USERPROFILE%\AppData\LocalLow\Sun\Java\Deployment\log
 
 %JRE_PATH%\javaws -uninstall
diff --git a/make/scripts/tests-linux-x64-junit-swt.sh b/make/scripts/tests-linux-x64-junit-swt.sh
new file mode 100644
index 0000000..421791a
--- /dev/null
+++ b/make/scripts/tests-linux-x64-junit-swt.sh
@@ -0,0 +1,7 @@
+#! /bin/bash
+
+SDIR=`dirname $0` 
+
+. $SDIR/make.jogl.all.linux-x86_64.sh -f build-test.xml junit.run.settings junit.run.swt.awt
+
+
diff --git a/make/scripts/tests-macosx64-junit-java7.sh b/make/scripts/tests-macosx64-junit-java7.sh
new file mode 100644
index 0000000..12be91b
--- /dev/null
+++ b/make/scripts/tests-macosx64-junit-java7.sh
@@ -0,0 +1,8 @@
+#! /bin/bash
+
+export JAVA7_EXE=`/usr/libexec/java_home -version 1.7.0_12`/bin/java
+
+SDIR=`dirname $0` 
+
+. $SDIR/make.jogl.all.macosx.sh -f build-test.xml junit.run.settings junit.run.local.java7
+
diff --git a/make/scripts/tests-macosx64-junit-swt.sh b/make/scripts/tests-macosx64-junit-swt.sh
new file mode 100644
index 0000000..2a6ccd6
--- /dev/null
+++ b/make/scripts/tests-macosx64-junit-swt.sh
@@ -0,0 +1,7 @@
+#! /bin/bash
+
+SDIR=`dirname $0` 
+
+. $SDIR/make.jogl.all.macosx.sh -f build-test.xml junit.run.settings junit.run.swt.awt
+
+
diff --git a/make/scripts/tests-osx-x64.sh b/make/scripts/tests-osx-x64-custom.sh
similarity index 62%
copy from make/scripts/tests-osx-x64.sh
copy to make/scripts/tests-osx-x64-custom.sh
index 748cf39..88587f0 100755
--- a/make/scripts/tests-osx-x64.sh
+++ b/make/scripts/tests-osx-x64-custom.sh
@@ -4,6 +4,6 @@ export DYLD_LIBRARY_PATH=/usr/local/lib:$DYLD_LIBRARY_PATH
 
 spath=`dirname $0`
 
-. $spath/tests.sh  /usr/bin/java -d64 ../build-macosx $*
+. $spath/tests.sh  "`which java`" -d64 ../build-macosx $*
 
 
diff --git a/make/scripts/tests-osx-x64.sh b/make/scripts/tests-osx-x64-java6.sh
similarity index 61%
copy from make/scripts/tests-osx-x64.sh
copy to make/scripts/tests-osx-x64-java6.sh
index 748cf39..fe2d2c4 100755
--- a/make/scripts/tests-osx-x64.sh
+++ b/make/scripts/tests-osx-x64-java6.sh
@@ -2,8 +2,11 @@
 
 export DYLD_LIBRARY_PATH=/usr/local/lib:$DYLD_LIBRARY_PATH
 
+JAVA_HOME=`/usr/libexec/java_home -version 1.6`
+PATH=$JAVA_HOME/bin:$PATH
+export JAVA_HOME PATH
+
 spath=`dirname $0`
 
 . $spath/tests.sh  /usr/bin/java -d64 ../build-macosx $*
 
-
diff --git a/make/scripts/tests-osx-x64.sh b/make/scripts/tests-osx-x64.sh
index 748cf39..e1b0720 100755
--- a/make/scripts/tests-osx-x64.sh
+++ b/make/scripts/tests-osx-x64.sh
@@ -2,8 +2,11 @@
 
 export DYLD_LIBRARY_PATH=/usr/local/lib:$DYLD_LIBRARY_PATH
 
-spath=`dirname $0`
+JAVA_HOME=`/usr/libexec/java_home -version 1.7`
+PATH=$JAVA_HOME/bin:$PATH
+export JAVA_HOME PATH
 
-. $spath/tests.sh  /usr/bin/java -d64 ../build-macosx $*
+spath=`dirname $0`
 
+. $spath/tests.sh  $JAVA_HOME/bin/java -d64 ../build-macosx $*
 
diff --git a/make/scripts/tests-win.bat b/make/scripts/tests-win.bat
new file mode 100755
index 0000000..ed02410
--- /dev/null
+++ b/make/scripts/tests-win.bat
@@ -0,0 +1,163 @@
+REM scripts\java-win.bat jogamp.newt.awt.opengl.VersionApplet
+REM scripts\java-win.bat com.jogamp.newt.opengl.GLWindow
+REM scripts\java-win.bat javax.media.opengl.awt.GLCanvas
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLCapabilities01NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen01GLPBufferNEWT -time 5000
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListAWT -time 5000
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT -time 5000
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT2 %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile02NEWT %*
+REM scripts\java-win.bat  com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitch01NEWT %*
+REM scripts\java-win.bat  com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitch11NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext01NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext02NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestBug692GL3VAO %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext11VSyncAnimNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext12FPSAnimNEWT %*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryGLnBitmapCapsNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryES2OffscrnCapsNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableOffThreadSharedContextES2NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT %*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestSwingAWT01GLn
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock00AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock02AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWT01GLn
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug551AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWT03GLCanvasRecreate01
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayoutAnimatorStartStopBug532 %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestJScrollPaneMixHwLw01AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug642JSplitPaneMixHwLw01AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestIsRealizedConcurrency01AWT %*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 4000 -x 10 -y 10 -width 100 -height 100 -screen 0
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 40000 -width 100 -height 100 -screen 0 %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT -time 5000
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl3.newt.TestGeomShader01TextureGL3NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.newt.TestSwingAWTRobotUsageBeforeJOGLInitBug411
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.glsl.TestTransformFeedbackVaryingsBug407NEWT
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLSimple01NEWT -time 2000
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestParenting01AWT
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestListenerCom01AWT
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.event.TestNewtKeyEventOrderAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.event.TestNewtKeyCodeModifiersAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.event.TestNewtKeyEventAutoRepeatAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.event.TestNewtKeyPressReleaseUnmaskRepeatAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.event.TestNewtKeyCodesAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.event.TestNewtEventModifiersNEWTWindowAWT $*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.event.TestNewtEventModifiersAWTCanvas %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.event.TestNewtEventModifiersNewtCanvasAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.event.TestNewtEventModifiersNewtCanvasAWT $*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.event.TestNewtEventModifiersNewtCanvasSWTAWT $*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01bAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cAWT -time 50000
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03bAWT -time 100000
+scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentParentingAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentChildWindowBug632NEWT %*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTBug628ResizeDeadlock %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTBug643AsyncExec %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT %*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestWindows01NEWT
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestGLWindows02NEWTAnimated
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestGLWindowInvisiblePointer01NEWT $*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestFocus01SwingAWTRobot %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.nativewindow.TestRecursiveToolkitLockCORE
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestScreenMode00NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01aNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01bNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01cNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT %*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2 %*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT
+
+REM scripts\java-win.bat testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1AWT %*
+REM scripts\java-win.bat testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1NEWT %*
+REM scripts\java-win.bat testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT %*
+REM scripts\java-win.bat testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyAWT %*
+REM scripts\java-win.bat  com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyNEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentChildWindowBug632NEWT %*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug461OffscreenSupersamplingSwingAWT
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol03NewtAWT %*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT01GLn %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT02GLn %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAWT01GLn %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT -time 5000
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.graph.TestRegionRendererNEWT01
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.graph.TestTextRendererNEWT01
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.graph.demos.ui.UINewtDemo01
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo01
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo02
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo01
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo02
+
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01
+
diff --git a/make/scripts/tests-win64-junit-swt.bat b/make/scripts/tests-win64-junit-swt.bat
new file mode 100755
index 0000000..fbcc5d6
--- /dev/null
+++ b/make/scripts/tests-win64-junit-swt.bat
@@ -0,0 +1,7 @@
+set THISDIR=%cd%
+
+set SDIR=%~dp0%
+
+%SDIR%/make.jogl.all.win64.bat -f build-test.xml junit.run.settings junit.run.swt.awt
+
+
diff --git a/make/scripts/java-win32-dbg.bat b/make/scripts/tests-x32-dbg.bat
similarity index 87%
rename from make/scripts/java-win32-dbg.bat
rename to make/scripts/tests-x32-dbg.bat
index e0760d0..e5e6451 100755
--- a/make/scripts/java-win32-dbg.bat
+++ b/make/scripts/tests-x32-dbg.bat
@@ -1,7 +1,7 @@
 
 set BLD_SUB=build-win32
-set J2RE_HOME=c:\jre1.6.0_35_x32
-set JAVA_HOME=c:\jdk1.6.0_35_x32
+set J2RE_HOME=c:\jre1.7.0_25_x32
+set JAVA_HOME=c:\jdk1.7.0_25_x32
 set ANT_PATH=C:\apache-ant-1.8.2
 
 set PROJECT_ROOT=D:\projects\jogamp\jogl
@@ -21,7 +21,7 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluege
 
 echo CP_ALL %CP_ALL%
 
-set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.GLContext" "-Djogl.debug.FBObject" "-Djogl.enable.ANGLE"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.GLContext" "-Djogl.debug.FBObject" "-Djogl.enable.ANGLE"
 REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery"
 REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK"
 REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
@@ -36,9 +36,10 @@ REM set D_ARGS="-Djogl.debug=all"
 REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL"
 REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" "-Djogl.debug=all"
 REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" "-Dnewt.test.Window.reparent.incompatible=true"
+REM set D_ARGS="-Dnewt.debug.Window.MouseEvent"
+set D_ARGS="-Dnewt.debug.Window.KeyEvent"
 REM set D_ARGS="-Xcheck:jni" "-Xint" "-verbose:jni"
 
 set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true"
 
-%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %D_ARGS% %X_ARGS% %* > java-win32-dbg.log 2>&1
-
+scripts\tests-win.bat %*
diff --git a/make/scripts/tests-x32.bat b/make/scripts/tests-x32.bat
index ec6c41f..6f262eb 100755
--- a/make/scripts/tests-x32.bat
+++ b/make/scripts/tests-x32.bat
@@ -1,106 +1,25 @@
-REM scripts\java-win32-dbg.bat jogamp.newt.awt.opengl.VersionApplet
-scripts\java-win32-dbg.bat com.jogamp.newt.opengl.GLWindow
-REM scripts\java-win32-dbg.bat javax.media.opengl.awt.GLCanvas
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestInitConcurrentNEWT %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen01GLPBufferNEWT -time 5000
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWT01GLn
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.awt.TestSwingAWT01GLn
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListAWT -time 5000
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT -time 5000
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT2 %*
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT %*
-
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %*
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 4000 -x 10 -y 10 -width 100 -height 100 -screen 0
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayoutAnimatorStartStopBug532 %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT -time 5000
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWT -time 5000
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWT03GLCanvasRecreate01
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.newt.TestSwingAWTRobotUsageBeforeJOGLInitBug411
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestTransformFeedbackVaryingsBug407NEWT
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLSimple01NEWT -time 2000
-
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestParenting01AWT
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01bAWT %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cAWT -time 50000
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestListenerCom01AWT
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT %*
-
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestWindows01NEWT
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows02NEWTAnimated
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.TestFocus01SwingAWTRobot %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.nativewindow.TestRecursiveToolkitLockCORE
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT -time 100000
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01AWT %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03bAWT -time 100000
-
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode00NEWT
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01NEWT
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT
-
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2 %*
-
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT %*
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT
-
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleAWT -time 10000
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleNEWT -time 10000
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug461OffscreenSupersamplingSwingAWT
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT
-
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT $*
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $*
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol03NewtAWT $*
-
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT01GLn %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT02GLn %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAWT01GLn $*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $*
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT $*
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $*
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $*
-
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT -time 5000
-
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT
-
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.graph.TestRegionRendererNEWT01
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.graph.TestTextRendererNEWT01
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.graph.demos.ui.UINewtDemo01
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo01
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo02
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo01
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo02
-
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT $*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT $*
-
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $*
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT
-
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %*
-REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01
-
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %*
-
+
+set BLD_SUB=build-win32
+set J2RE_HOME=c:\jre1.7.0_25_x32
+set JAVA_HOME=c:\jdk1.7.0_25_x32
+set ANT_PATH=C:\apache-ant-1.8.2
+
+set PROJECT_ROOT=D:\projects\jogamp\jogl
+set BLD_DIR=..\%BLD_SUB%
+
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\angle\win32\20120127;%PATH%
+set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\angle\win32\20121010-chrome;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH%
+
+set BLD_DIR=..\%BLD_SUB%
+REM set LIB_DIR=..\..\gluegen\%BLD_SUB%\obj;%BLD_DIR%\lib
+REM set FFMPEG_LIB=%PROJECT_ROOT%\make\lib\ffmpeg\x32
+REM set LIB_DIR=%FFMPEG_LIB%
+set LIB_DIR=
+
+set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluegen\%BLD_SUB%\gluegen-rt.jar;..\..\gluegen\make\lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar;%BLD_DIR%\..\make\lib\swt\win32-win32-x86\swt-debug.jar
+
+echo CP_ALL %CP_ALL%
+
+scripts\tests-win.bat %*
diff --git a/make/scripts/tests-x32.sh b/make/scripts/tests-x32.sh
index a3aed84..858ed5f 100755
--- a/make/scripts/tests-x32.sh
+++ b/make/scripts/tests-x32.sh
@@ -6,6 +6,8 @@ if [ -e $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86.sh ] ; then
     . $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86.sh
 fi
 
+export SWT_CLASSPATH=`pwd`/lib/swt/gtk-linux-x86/swt-debug.jar
+
 . $SDIR/tests.sh  `which java` -d32 ../build-x86 $*
 
 
diff --git a/make/scripts/tests-x64-custom.sh b/make/scripts/tests-x64-custom.sh
new file mode 100755
index 0000000..482afbb
--- /dev/null
+++ b/make/scripts/tests-x64-custom.sh
@@ -0,0 +1,12 @@
+#! /bin/bash
+
+SDIR=`dirname $0` 
+
+#export LD_LIBRARY_PATH=/home/sven/libav/lib:$LD_LIBRARY_PATH
+
+#if [ -e $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh ] ; then
+#    . $SDIR/../../../gluegen/make/scripts/setenv-build-jogl-x86_64.sh
+#fi
+
+. $SDIR/tests.sh  `which java` -d64 ../build-x86_64 $*
+
diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/tests-x64-dbg.bat
similarity index 80%
rename from make/scripts/java-win64-dbg.bat
rename to make/scripts/tests-x64-dbg.bat
index 5dc34f4..cb40125 100755
--- a/make/scripts/java-win64-dbg.bat
+++ b/make/scripts/tests-x64-dbg.bat
@@ -1,7 +1,7 @@
 
 set BLD_SUB=build-win64
-set J2RE_HOME=c:\jre1.6.0_35_x64
-set JAVA_HOME=c:\jdk1.6.0_35_x64
+set J2RE_HOME=c:\jre1.7.0_25_x64
+set JAVA_HOME=c:\jdk1.7.0_25_x64
 set ANT_PATH=C:\apache-ant-1.8.2
 
 set PROJECT_ROOT=D:\projects\jogamp\jogl
@@ -22,15 +22,17 @@ REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject"
 REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery"
 REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK"
 REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.GLContext" "-Djogl.debug.GLCanvas"
 REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug=all" "-Djogl.debug.EGLDrawableFactory.DontQuery"
 REM set D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser -Djogl.debug.GLProfile"
 REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
 REM set D_ARGS="-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLSLCode"
+REM set D_ARGS="-Djogl.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper" "-Djogamp.debug.NativeLibrary" "-Djogamp.debug.NativeLibrary.Lookup" "-Djogamp.debug.JNILibLoader" "-Djogamp.debug.TempJarCache" "-Djogamp.debug.JarUtil"
 REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true"
 REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true"
 REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.ExtensionAvailabilityCache" "-Djogamp.debug.ProcAddressHelper=true"
-REM set D_ARGS="-Djogl.debug.GraphicsConfiguration"
-REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.GLDrawable" "-Dnativewindow.debug.GraphicsConfiguration"
+REM set D_ARGS="-Dnativewindow.debug.GraphicsConfiguration"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Dnativewindow.debug.GraphicsConfiguration" "-Djogl.debug.CapabilitiesChooser"
 REM set D_ARGS="-Djogamp.debug.JNILibLoader=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLProfile=true"
 REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.Lock" "-Djogamp.debug.Lock.TraceLock"
 REM set D_ARGS="-Djogl.debug=all" "-Dnativewindow.debug=all"
@@ -39,20 +41,25 @@ REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLC
 REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.windows.useWGLVersionOf5WGLGDIFuncSet"
 REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch"
 REM set D_ARGS="-Dnewt.debug.Window"
+set D_ARGS="-Dnewt.debug.Window.KeyEvent" "-Dnewt.debug.Window"
 REM set D_ARGS="-Dnewt.debug.Window.KeyEvent"
+REM set D_ARGS="-Dnewt.debug.Window.MouseEvent"
+REM set D_ARGS="-Dnewt.debug.Window.MouseEvent" "-Dnewt.debug.Window.KeyEvent"
 REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display"
 REM set D_ARGS="-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL"
 REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.GLSLCode"
 REM set D_ARGS="-Djogl.debug.GLContext" "-Dnewt.debug=all"
 REM set D_ARGS="-Dnewt.debug.Window" "-Dnativewindow.debug.TraceLock"
 REM set D_ARGS="-Dnativewindow.debug.TraceLock"
+REM set D_ARGS="-Dnewt.debug.Display" "-Dnewt.debug.EDT" "-Dnewt.debug.Window"
 REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" "-Dnewt.debug.EDT" "-Djogl.debug.GLContext"
 REM set D_ARGS="-Dnewt.debug.Screen" "-Dnewt.debug.EDT" "-Dnativewindow.debug=all"
+REM set D_ARGS="-Dnewt.debug.Screen"
 REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" "-Dnewt.test.Window.reparent.incompatible=true"
 
 REM set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.java2d.opengl=true" "-Dsun.awt.noerasebackground=true"
 REM set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.java2d.d3d=false" "-Dsun.java2d.ddoffscreen=false" "-Dsun.java2d.gdiblit=false" "-Dsun.java2d.opengl=false" "-Dsun.awt.noerasebackground=true" "-Xms512m" "-Xmx1024m"
 REM set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.java2d.d3d=false" "-Dsun.java2d.ddoffscreen=false" "-Dsun.java2d.gdiblit=false" "-Dsun.java2d.opengl=true" "-Dsun.awt.noerasebackground=true" "-Xms512m" "-Xmx1024m"
 
-REM %J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %D_ARGS% %X_ARGS% %* > java-win64-dbg.log 2>&1
-%J2RE_HOME%\bin\java -classpath %CP_ALL% "-Djava.library.path=%LIB_DIR%" %D_ARGS% %X_ARGS% %* 
+scripts\tests-win.bat %*
+
diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat
index c8bc030..899c694 100755
--- a/make/scripts/tests-x64.bat
+++ b/make/scripts/tests-x64.bat
@@ -1,126 +1,20 @@
-REM scripts\java-win64-dbg.bat jogamp.newt.awt.opengl.VersionApplet
-REM scripts\java-win64-dbg.bat com.jogamp.newt.opengl.GLWindow
-REM scripts\java-win64-dbg.bat javax.media.opengl.awt.GLCanvas
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLCapabilities01NEWT %*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT %*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteAWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen01GLPBufferNEWT -time 5000
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWT01GLn
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug551AWT %*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.awt.TestSwingAWT01GLn
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListAWT -time 5000
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT -time 5000
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT2 %*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT %*
-REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile02NEWT %*
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT %*
-scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 4000 -x 10 -y 10 -width 100 -height 100 -screen 0
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 40000 -width 100 -height 100 -screen 0 %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayoutAnimatorStartStopBug532 %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT -time 5000
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWT -time 5000
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWT03GLCanvasRecreate01
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.newt.TestSwingAWTRobotUsageBeforeJOGLInitBug411
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestTransformFeedbackVaryingsBug407NEWT
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLSimple01NEWT -time 2000
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestParenting01AWT
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestListenerCom01AWT
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestNewtKeyEventOrderAWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestNewtKeyEventAutoRepeatAWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestNewtKeyPressReleaseUnmaskRepeatAWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestNewtKeyCodesAWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestNewtKeyCodeModifiersAWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01bAWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cAWT -time 50000
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03bAWT -time 100000
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01AWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT %*
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn %*
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestWindows01NEWT
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows02NEWTAnimated
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestFocus01SwingAWTRobot %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.nativewindow.TestRecursiveToolkitLockCORE
-
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode00NEWT
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode01NEWT
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2 %*
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleAWT -time 10000
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleNEWT -time 10000
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug461OffscreenSupersamplingSwingAWT
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT
-
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT %*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT %*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol03NewtAWT %*
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT01GLn %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT02GLn %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAWT01GLn %*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT -time 5000
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT
-
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.TestRegionRendererNEWT01
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.TestTextRendererNEWT01
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.ui.UINewtDemo01
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo01
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo02
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo01
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo02
-
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT %*
-
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %*
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT
-
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT $*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryOffscrnCapsNEWT $*
-
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT $*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableOffThreadSharedContextES2NEWT $*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $*
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01
-
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %*
-
+
+set BLD_SUB=build-win64
+set J2RE_HOME=c:\jre1.7.0_25_x64
+set JAVA_HOME=c:\jdk1.7.0_25_x64
+set ANT_PATH=C:\apache-ant-1.8.2
+
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
+set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_64;%PATH%
+
+set BLD_DIR=..\%BLD_SUB%
+REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj
+set LIB_DIR=
+
+set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluegen\%BLD_SUB%\gluegen-rt.jar;..\..\gluegen\make\lib\junit.jar;%ANT_PATH%\lib\ant.jar;%ANT_PATH%\lib\ant-junit.jar;%BLD_DIR%\..\make\lib\swt\win32-win32-x86_64\swt-debug.jar
+echo CP_ALL %CP_ALL%
+
+set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true"
+
+scripts\tests-win.bat %*
+
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
old mode 100755
new mode 100644
index ef64aa7..c0ab5f4
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -5,19 +5,19 @@ if [ -z "$1" -o -z "$2" -o -z "$3" ] ; then
     exit 0
 fi
 
-javaexe=$1
+javaexe="$1"
 shift
 javaxargs=$1
 shift
-bdir=$1
+bdir="$1"
 shift
 
-if [ ! -x $javaexe ] ; then
-    echo java-exe $javaexe is not an executable
+if [ ! -x "$javaexe" ] ; then
+    echo java-exe "$javaexe" is not an executable
     exit 1
 fi
-if [ ! -d $bdir ] ; then
-    echo build-dir $bdir is not a directory
+if [ ! -d "$bdir" ] ; then
+    echo build-dir "$bdir" is not a directory
     exit 1
 fi
 
@@ -25,7 +25,7 @@ rm -f java-run.log
 
 spath=`dirname $0`
 
-. $spath/setenv-jogl.sh $bdir JOGL_ALL
+. $spath/setenv-jogl.sh "$bdir" JOGL_ALL
 unset CLASSPATH
 
 MOSX=0
@@ -33,7 +33,7 @@ MOSX_MT=0
 uname -a | grep -i Darwin && MOSX=1
 if [ $MOSX -eq 1 ] ; then
     echo setup OSX environment vars
-    export NSZombieEnabled=YES
+    #export NSZombieEnabled=YES
     export NSTraceEvents=YES
     #export OBJC_PRINT_EXCEPTIONS=YES
     echo NSZombieEnabled $NSZombieEnabled 2>&1 | tee -a java-run.log
@@ -42,15 +42,37 @@ if [ $MOSX -eq 1 ] ; then
     MOSX_MT=1
 fi
 
-which $javaexe 2>&1 | tee -a java-run.log
-$javaexe -version 2>&1 | tee -a java-run.log
+#export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_64:$LD_LIBRARY_PATH
+#export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_32:$LD_LIBRARY_PATH
+#export LD_LIBRARY_PATH=/usr/local/projects/Xorg.modular/build-x86_64/lib:$LD_LIBRARY_PATH
+#export LD_LIBRARY_PATH=/opt-linux-x86_64/x11lib-1.3:$LD_LIBRARY_PATH
+#export LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64:$LD_LIBRARY_PATH
+#export LD_LIBRARY_PATH=/usr/lib/mesa:/usr/lib32/mesa:$LD_LIBRARY_PATH
+#export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/mesa:/usr/lib/i386-linux-gnu/mesa:$LD_LIBRARY_PATH
+#export LIBGL_DRIVERS_PATH=/usr/lib/x86_64-linux-gnu/dri:/usr/lib/i386-linux-gnu/dri
+#export LD_LIBRARY_PATH=`pwd`/lib/external/mesa_git/x86_64-linux-gnu:$LD_LIBRARY_PATH
+#export LIBGL_DRIVERS_PATH=`pwd`/lib/external/mesa_git/x86_64-linux-gnu/dri
+#export LD_LIBRARY_PATH=`pwd`/lib/external/mesa_901/x86_64-linux-gnu:$LD_LIBRARY_PATH
+#export LIBGL_DRIVERS_PATH=`pwd`/lib/external/mesa_901/x86_64-linux-gnu/dri
+#export LD_LIBRARY_PATH=`pwd`/lib/external/mesa_900/x86_64-linux-gnu:$LD_LIBRARY_PATH
+#export LIBGL_DRIVERS_PATH=`pwd`/lib/external/mesa_900/x86_64-linux-gnu/dri
+
+#export LIBGL_DEBUG=verbose 
+#export MESA_DEBUG=true 
+#export LIBGL_ALWAYS_SOFTWARE=true
+#export INTEL_DEBUG="buf bat"
+#export INTEL_STRICT_CONFORMANCE=1 
+
+which "$javaexe" 2>&1 | tee -a java-run.log
+"$javaexe" -version 2>&1 | tee -a java-run.log
+echo LD_LIBRARY_PATH $LD_LIBRARY_PATH 2>&1 | tee -a java-run.log
 echo LIBXCB_ALLOW_SLOPPY_LOCK: $LIBXCB_ALLOW_SLOPPY_LOCK 2>&1 | tee -a java-run.log
 echo LIBGL_DRIVERS_PATH: $LIBGL_DRIVERS_PATH 2>&1 | tee -a java-run.log
 echo LIBGL_DEBUG: $LIBGL_DEBUG 2>&1 | tee -a java-run.log
 echo LIBGL_ALWAYS_INDIRECT: $LIBGL_ALWAYS_INDIRECT 2>&1 | tee -a java-run.log
 echo LIBGL_ALWAYS_SOFTWARE: $LIBGL_ALWAYS_SOFTWARE 2>&1 | tee -a java-run.log
 echo SWT_CLASSPATH: $SWT_CLASSPATH 2>&1 | tee -a java-run.log
-echo $javaexe $javaxargs $X_ARGS $D_ARGS $* 2>&1 | tee -a java-run.log
+echo "$javaexe" $javaxargs $X_ARGS $D_ARGS $* 2>&1 | tee -a java-run.log
 echo MacOsX $MOSX
 
 function jrun() {
@@ -67,6 +89,10 @@ function jrun() {
     #D_ARGS="-Djogl.debug.FBObject"
     #D_ARGS="-Djogl.debug.GLSLCode"
     #D_ARGS="-Djogl.debug.GLSLCode -Djogl.debug.DebugGL -Djogl.debug.TraceGL"
+    #D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.JAWT -Dnewt.debug.Window"
+    #D_ARGS="-Dnativewindow.debug.JAWT -Djogamp.debug.TaskBase.TraceSource"
+    #D_ARGS="-Djogl.debug.GLContext.TraceSwitch"
+    #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLContext.TraceSwitch"
     #D_ARGS="-Djogl.debug.FixedFuncPipeline -Djogl.debug.GLSLCode"
     #D_ARGS="-Djogl.debug.FixedFuncPipeline -Djogl.debug.GLSLState"
     #D_ARGS="-Djogl.debug.FixedFuncPipeline"
@@ -75,12 +101,21 @@ function jrun() {
     #D_ARGS="-Djogl.debug.TraceGL -Djogl.debug.DebugGL -Djogl.debug.GLSLCode"
     #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.FBObject -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Djogl.debug.GLCanvas -Dnewt.debug.Window"
     #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.FBObject"
+    #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration"
+    #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration"
+    #D_ARGS="-Djogl.debug.GLContext"
     #D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing"
+    #D_ARGS="-Djogamp.debug=all"
     #D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all"
     #D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all"
+    #D_ARGS="-Dnativewindow.debug.X11Util -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Djogl.debug.EGLDisplayUtil -Djogl.debug.GLDrawable"
+    #D_ARGS="-Djogl.debug.GLDrawable -Dnativewindow.debug.X11Util -Dnativewindow.debug.NativeWindow -Dnewt.debug.Display -Dnewt.debug.Screen -Dnewt.debug.Window"
+    #D_ARGS="-Djogl.debug.Animator"
     #D_ARGS="-Djogl.debug=all -Dnewt.debug=all"
-    #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration"
+    #D_ARGS="-Djogl.debug.EGLDisplayUtil -Djogl.debug.GLDrawable"
+    #D_ARGS="-Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLCanvas"
     #D_ARGS="-Djogl.debug.GLDrawable"
+    #D_ARGS="-Djogl.debug.GLEventListenerState"
     #D_ARGS="-Djogl.fbo.force.none"
     #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock"
     #D_ARGS="-Djogl.debug=all"
@@ -100,11 +135,13 @@ function jrun() {
     #D_ARGS="-Djogl.debug.EGLDisplayUtil -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable"
     #D_ARGS="-Djogl.debug.EGLDisplayUtil -Dnativewindow.debug.X11Util"
     #D_ARGS="-Djogl.debug.GLDrawable"
+    #D_ARGS="-Dnewt.debug.Screen"
+    #D_ARGS="-Dnewt.test.Screen.disableRandR13"
     #D_ARGS="-Dnewt.test.Screen.disableScreenMode -Dnewt.debug.Screen"
     #D_ARGS="-Dnewt.debug.Screen -Djogl.debug.Animator"
-    #D_ARGS="-Djogl.debug.ExtensionAvailabilityCache -Djogl.debug=all -Dnativewindow.debug=all -Djogamp.debug.ProcAddressHelper=true -Djogamp.debug.NativeLibrary=true -Djogamp.debug.NativeLibrary.Lookup=true"
+    #D_ARGS="-Djogamp.debug.ProcAddressHelper -Djogamp.debug.NativeLibrary -Djogamp.debug.NativeLibrary.Lookup -Djogamp.debug.JNILibLoader -Djogamp.debug.TempJarCache -Djogamp.debug.JarUtil"
+    #D_ARGS="-Djogl.debug.GLContext -Djogamp.debug.NativeLibrary -Djogamp.debug.JNILibLoader -Djogl.debug.DebugGL -Djogl.debug.GLDebugMessageHandler"
     #D_ARGS="-Dnewt.debug.MainThread"
-    #D_ARGS="-Dnewt.debug.Window"
     #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Dnativewindow.debug.NativeWindow"
     #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Animator -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLContext.TraceSwitch"
     #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.ExtensionAvailabilityCache"
@@ -112,7 +149,7 @@ function jrun() {
     #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLProfile"
     #D_ARGS="-Djogl.debug.GLProfile"
     #D_ARGS="-Dnativewindow.debug.NativeWindow"
-    #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT"
+    #D_ARGS="-Djogl.debug.GLCanvas -Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.Animator"
     #D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Window -Djogl.debug.GLContext"
     #D_ARGS="-Dnativewindow.debug.X11Util.XErrorStackDump -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Dnativewindow.debug.X11Util"
     #D_ARGS="-Dnativewindow.debug.X11Util -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnewt.debug=all"
@@ -126,7 +163,8 @@ function jrun() {
     #D_ARGS="-Djogamp.common.utils.locks.Lock.timeout=600000 -Djogamp.debug.Lock -Djogamp.debug.Lock.TraceLock -Dnativewindow.debug.ToolkitLock.TraceLock"
     #D_ARGS="-Djogamp.common.utils.locks.Lock.timeout=600000 -Djogamp.debug.Lock -Dnativewindow.debug.X11Util"
     #D_ARGS="-Dnewt.debug.EDT -Djogamp.common.utils.locks.Lock.timeout=600000 -Djogl.debug.Animator -Dnewt.debug.Display -Dnewt.debug.Screen"
-    #D_ARGS="-Dnewt.debug.Window -Djogamp.common.utils.locks.Lock.timeout=600000 -Djogl.debug.Animator"
+    #D_ARGS="-Dnewt.debug.Window -Djogamp.common.utils.locks.Lock.timeout=600000"
+    #D_ARGS="-Dnewt.debug=all -Djogamp.common.utils.locks.Lock.timeout=600000"
     #D_ARGS="-Djogl.debug.Animator -Dnewt.debug=all"
     #D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Display -Dnativewindow.debug.X11Util -Djogl.debug.GLDrawable -Djogl.debug.GLCanvas"
     #D_ARGS="-Djogl.debug.GLContext"
@@ -136,16 +174,19 @@ function jrun() {
     #D_ARGS="-Dnewt.debug.EDT"
     #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.GLContext"
     #D_ARGS="-Dnewt.debug.Window -Djogl.debug.Animator -Dnewt.debug.Screen"
-    #D_ARGS="-Dnewt.debug.Window"
+    #D_ARGS="-Dnativewindow.debug.JAWT -Dnewt.debug.Window"
     #D_ARGS="-Dnewt.debug.Window.KeyEvent"
     #D_ARGS="-Dnewt.debug.Window.MouseEvent"
+    #D_ARGS="-Dnewt.debug.Window.MouseEvent -Dnewt.debug.Window.KeyEvent"
     #D_ARGS="-Dnewt.debug.Window -Dnativewindow.debug=all"
     #D_ARGS="-Dnewt.debug.Window -Dnativewindow.debug.JAWT -Djogl.debug.Animator"
-    #D_ARGS="-Dnewt.debug.Window"
+    #D_ARGS="-Dnewt.debug.Window -Djogl.debug.GLDrawable"
+    #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Window.KeyEvent"
     #D_ARGS="-Xprof"
-    #D_ARGS="-Djogl.debug.Animator"
     #D_ARGS="-Dnativewindow.debug=all"
-    #D_ARGS="-Djogl.debug.GLCanvas"
+    #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel"
+    #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel -Djogl.gljpanel.noglsl"
+    #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Animator"
     #D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.X11Util.XSync"
     #D_ARGS="-Dnativewindow.debug.X11Util.XSync -Dnativewindow.debug.ToolkitLock.TraceLock"
     #D_ARGS="-Dnativewindow.debug.NativeWindow"
@@ -161,11 +202,17 @@ function jrun() {
     #D_ARGS="-Dnewt.debug=all -Djogamp.debug.Lock.TraceLock -Djogamp.common.utils.locks.Lock.timeout=600000"
     #D_ARGS="-Dnewt.debug=all -Djogamp.debug.Lock -Djogamp.debug.Lock.TraceLock"
     #D_ARGS="-Djogl.debug.GLContext -Dnewt.debug=all -Djogamp.debug.Lock -Djogamp.common.utils.locks.Lock.timeout=10000"
+    #D_ARGS="-Djogl.debug.GLContext -Dnewt.debug=all"
     #D_ARGS="-Dnewt.debug=all"
+    #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel"
+    #D_ARGS="-Djogl.debug.PNGImage"
+    #D_ARGS="-Djogl.debug.JPEGImage"
+    #D_ARGS="-Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser"
     #X_ARGS="-Dsun.java2d.noddraw=True -Dsun.java2d.opengl=True -Dsun.java2d.xrender=false"
     #X_ARGS="-Dsun.java2d.noddraw=True -Dsun.java2d.opengl=false -Dsun.java2d.xrender=false"
     #X_ARGS="-verbose:jni"
     #X_ARGS="-Xrs"
+    #X_ARGS="-Dsun.awt.disableMixing=true"
 
     if [ $awton -eq 1 ] ; then
         export CLASSPATH=$JOGAMP_ALL_AWT_CLASSPATH
@@ -189,32 +236,23 @@ function jrun() {
     #X_ARGS="-Dnativewindow.ws.name=jogamp.newt.driver.broadcom.egl $X_ARGS"
     echo CLASSPATH $CLASSPATH
     if [ $MOSX_MT -eq 1 ] ; then
-        X_ARGS="-XstartOnFirstThread $X_ARGS"
-        if [ $swton -eq 0 ] ; then
+        if [ $awton -eq 0 -a $swton -eq 0 ] ; then
+            # No AWT, No SWT -> Preserve Main-Thread
+            X_ARGS="-XstartOnFirstThread $X_ARGS"
             C_ARG="com.jogamp.newt.util.MainThread"
+        elif [ $awton -eq 0 -a $swton -eq 1 ] ; then
+            # SWT Only: Launch on Main-Thread
+            X_ARGS="-XstartOnFirstThread $X_ARGS"
+        # elif [ $awton -eq 1 -a $swton -eq 1 ] ; then
+            # AWT and SWT -> Use AWT Main-Thread
         fi
     fi
-    #export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_64:$LD_LIBRARY_PATH
-    #export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_32:$LD_LIBRARY_PATH
-    #export LD_LIBRARY_PATH=/usr/local/projects/Xorg.modular/build-x86_64/lib:$LD_LIBRARY_PATH
-    #export LD_LIBRARY_PATH=/opt-linux-x86_64/x11lib-1.3:$LD_LIBRARY_PATH
-    #export LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64:$LD_LIBRARY_PATH
-    #export LD_LIBRARY_PATH=/usr/lib/mesa:/usr/lib32/mesa:$LD_LIBRARY_PATH
-    #export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/mesa:/usr/lib/i386-linux-gnu/mesa:$LD_LIBRARY_PATH
-    #export LD_LIBRARY_PATH=`pwd`/lib/external/mesa/x86_64-linux-gnu:$LD_LIBRARY_PATH
-    #export LD_LIBRARY_PATH=`pwd`/lib/external/mesa/x86_64-linux-gnu/gallium:$LD_LIBRARY_PATH
     echo
     echo "Test Start: $*"
     echo
-    echo LD_LIBRARY_PATH $LD_LIBRARY_PATH
-    echo
-    echo $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $*
-    #LIBGL_DRIVERS_PATH=/usr/lib/mesa:/usr/lib32/mesa \
-    #LIBGL_DEBUG=verbose INTEL_STRICT_CONFORMANCE=1 INTEL_DEBUG="buf bat" \
-    #LIBGL_DEBUG=verbose MESA_DEBUG=true INTEL_STRICT_CONFORMANCE=1 \
-    #export LIBGL_DEBUG=verbose MESA_DEBUG=true LIBGL_ALWAYS_SOFTWARE=true
-    #gdb --args $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $*
-    $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $*
+    echo "$javaexe" $javaxargs $X_ARGS $D_ARGS $C_ARG $*
+    #gdb --args "$javaexe" $javaxargs $X_ARGS $D_ARGS $C_ARG $*
+    "$javaexe" $javaxargs $X_ARGS $D_ARGS $C_ARG $*
     echo
     echo "Test End: $*"
     echo
@@ -238,19 +276,56 @@ function testawtswt() {
 }
 
 #
+# demos (any TK, more user driven tests)
+#
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestOlympicES1NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestRedSquareES1NEWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NewtCanvasAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NEWT $*
+#testawtswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT $*
+#testswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $*
+#testswt com.jogamp.opengl.test.junit.jogl.demos.es2.swt.TestGearsES2SWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWTAnalyzeBug455 $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWTBug450 $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestTeapotNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl3.newt.TestGeomShader01TextureGL3NEWT $*
+
+#
+# av demos
+#
+#testnoawt jogamp.opengl.openal.av.ALDummyUsage $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
+
+#
 # core/newt (testnoawt and testawt)
 #
 #testnoawt com.jogamp.nativewindow.NativeWindowVersion $*
 #testnoawt com.jogamp.opengl.JoglVersion $*
 #testnoawt com.jogamp.newt.NewtVersion $*
 #testnoawt com.jogamp.newt.opengl.GLWindow $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen01GLPBufferNEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT $*
-testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFloatUtil01MatrixMatrixMultNOUI $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPMVMatrix01NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPMVMatrix02NEWT $*
+
+#testnoawt com.jogamp.opengl.test.junit.jogl.math.TestPMVMatrix01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.math.TestPMVMatrix02NOUI $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.math.TestPMVMatrix03NOUI $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.math.TestGluUnprojectFloatNOUI $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.math.TestGluUnprojectDoubleNOUI $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.math.TestFloatUtil01MatrixMatrixMultNOUI $*
+
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLVersionParsing00NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestNEWTCloseX11DisplayBug565 $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $*
@@ -261,63 +336,80 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextSurfaceLockNEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMapBufferRead01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext02NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug692GL3VAO $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT2 $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES1NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPointsNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLPointsNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLMesaBug651NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLMesaBug658NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestX11DefaultDisplay $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer01GLCanvasAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer02NewtCanvasAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.TestAddRemove01GLCanvasSwingAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.TestAddRemove02GLWindowNewtCanvasAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.TestAddRemove03GLWindowNEWT $*
 
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryGLnBitmapCapsNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryES2OffscrnCapsNEWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryOffscrnCapsNEWT $*
-
-#testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer01GLCanvasAWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer02NewtCanvasAWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
 
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOffThreadSharedContextMix2DemosES2NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOnThreadSharedContext1DemoES2NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $*
-#testawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT
-#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
 
-#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cSwingAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimNEWT $*
+#testawt   com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimNEWT $*
+#testawt   com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext11VSyncAnimNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext12FPSAnimNEWT $*
+
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch10NEWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch11NewtAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch12AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch21Newt2AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestBug722GLContextDrawableSwitchNewt2AWT $*
 
+#testnoawt com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen01GLPBufferNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT $*
+
+#testawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT
 
-#testnoawt com.jogamp.opengl.test.junit.jogl.glu.TestGluUnprojectFloatNOUI $*
 #testnoawt com.jogamp.opengl.test.junit.newt.TestRemoteWindow01NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.newt.TestRemoteGLWindows01NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestRedSquareES1NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT $*
+
 #testnoawt com.jogamp.opengl.test.junit.newt.TestWindows01NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindows02NEWTAnimated $*
+#testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindowInvisiblePointer01NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT
 #testnoawt com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle02NEWT
-#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode00NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode00bNEWT
 #testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01NEWT
-#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01bNEWT
-#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT
-#testnoawt com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT
-#testnoawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $*
-#testnoawt -Djava.awt.headless=true com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT
+#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01aNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01bNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01cNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT $*
+#testnoawt -Djava.awt.headless=true com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindowWarpPointer01NEWT $*
 
 #
 # awt (testawt)
@@ -325,10 +417,6 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
 #testawt jogamp.newt.awt.opengl.VersionApplet $*
 #testawt javax.media.opengl.awt.GLCanvas $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLCanvasAWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug551AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug572AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug611AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWT01GLn $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.TestAWTCloseX11DisplayBug565 $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListAWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextNewtAWTBug523 $*
@@ -336,19 +424,33 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.TestPBufferDeadlockAWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteAWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.x11.TestGLXCallsOnAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug675BeansInDesignTimeAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug551AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug572AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug611AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWT01GLn $*
 #testawt com.jogamp.opengl.test.junit.jogl.awt.TestSwingAWT01GLn
 #testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWT03GLCanvasRecreate01 $*
 #testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWT02WindowClosing
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestJScrollPaneMixHwLw01AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug642JSplitPaneMixHwLw01AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug664GLCanvasSetVisibleSwingAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestIsRealizedConcurrency01AWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.awt.text.TestAWTTextRendererUseVertexArrayBug464
-#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWTAnalyzeBug455 $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWTBug450 $*
 #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT
 #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461PBufferSupersamplingSwingAWT
 #testawt com.jogamp.opengl.test.junit.jogl.glu.TestBug463ScaleImageMemoryAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.glu.TestBug694ScaleImageUnpackBufferSizeAWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayoutAnimatorStartStopBug532 $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock00AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock01AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.awt.TestGLCanvasAWTActionDeadlock02AWT $*
+
+#testawt com.jogamp.opengl.test.bugs.Bug735Inv0AppletAWT $*
+#testawt com.jogamp.opengl.test.bugs.Bug735Inv1AppletAWT $*
+#testawt com.jogamp.opengl.test.bugs.Bug735Inv2AppletAWT $*
+#testawt com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT $*
+#testawt com.jogamp.opengl.test.bugs.Bug735Inv4AWT $*
 
 #
 # swt (testswt)
@@ -366,61 +468,82 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
 #testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn $*
 #testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
 #testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $*
+#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTBug628ResizeDeadlockAWT $*
+#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTBug643AsyncExec $*
 
 #
 # newt.awt (testawt)
 #
 #testawt com.jogamp.opengl.test.junit.jogl.newt.TestSwingAWTRobotUsageBeforeJOGLInitBug411 $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper $*
 #testawt com.jogamp.opengl.test.junit.newt.TestEventSourceNotAWTBug
 #testawt com.jogamp.opengl.test.junit.newt.TestFocus01SwingAWTRobot $*
 #testawt com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot $*
-#testawt com.jogamp.opengl.test.junit.newt.TestNewtKeyEventOrderAWT $*
-#testawt com.jogamp.opengl.test.junit.newt.TestNewtKeyEventAutoRepeatAWT $*
-#testawt com.jogamp.opengl.test.junit.newt.TestNewtKeyPressReleaseUnmaskRepeatAWT $*
-#testawt com.jogamp.opengl.test.junit.newt.TestNewtKeyCodesAWT $*
-#testawt com.jogamp.opengl.test.junit.newt.TestNewtKeyCodeModifiersAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.event.TestNewtKeyEventOrderAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.event.TestNewtKeyEventAutoRepeatAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.event.TestNewtKeyPressReleaseUnmaskRepeatAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.event.TestNewtKeyCodesAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.event.TestNewtKeyCodeModifiersAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.event.TestNewtEventModifiersNEWTWindowAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.event.TestNewtEventModifiersAWTCanvas $*
+#testawt com.jogamp.opengl.test.junit.newt.event.TestNewtEventModifiersNewtCanvasAWT $*
+testawtswt com.jogamp.opengl.test.junit.newt.event.TestNewtEventModifiersNewtCanvasSWTAWT $*
+
 #testawt com.jogamp.opengl.test.junit.newt.TestListenerCom01AWT
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aAWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01bAWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cAWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cSwingAWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02AWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $*
-#testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT $*
-#testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentParentingAWT $*
-#testawt com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT
 #testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1AWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyAWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentChildWindowBug632NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestBug605FlippedImageNEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestBug605FlippedImageAWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT
 
+#testawt com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT
 #testawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT $*
 #testnoawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $*
 #testawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol03NewtAWT $*
 
 #testawt $*
 
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestInitConcurrent01NEWT $*
+
+#
+# NEWT Parenting (w/ NEWT, AWT or SWT)
+#
+#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT $*
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $*
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cSwingAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01bAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cAWT $*
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02AWT $*
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT $*
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $*
+#testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT $*
+#testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $*
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentParentingAWT $*
+#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentChildWindowBug632NEWT $*
+
 #
 # Misc Utils
 #
 #testnoawt com.jogamp.opengl.test.junit.jogl.util.TestImmModeSinkES1NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.TestImmModeSinkES2NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.util.TestES1FixedFunctionPipelineNEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestRedSquareES1NEWT $*
 
 #
 # Texture / TextureUtils
 #
-#testnoawt com.jogamp.opengl.test.junit.jogl.util.TestPNGImage01NEWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestTexture01AWT
+#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestTexture01AWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestTexture02AWT $*
+
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGImage01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTCompareNewtAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTBenchmarkNewtAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGTextureFromFileNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGImage01NEWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGTextureFromFileAWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGTextureFromFileNEWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestGLReadBufferUtilTextureIOWrite01AWT $*
@@ -430,8 +553,6 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestTextureSequence01NEWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestTextureSequence01AWT $*
 
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $*
 
 #
 # GLSL
@@ -458,32 +579,40 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
 #testnoawt com.jogamp.opengl.test.junit.graph.demos.GPUUISceneNewtDemo02 $*
 
 #
-# Security
-#
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMapBufferRead01NEWT $*
-
-#
-# osx bugs
+# OSX bugs
 #
 #testawt com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot $*
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $*
+
+# test rotation change
+#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT
 
 #
 # regressions
 #
-#Windows
-#testawt com.jogamp.opengl.test.junit.newt.TestFocus01SwingAWTRobot $*
-#testawt com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot $*
-
-# osx:
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDrawable02NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $*
-#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $*
 
 #linux:
-#testawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT $*
 
+# ATI/Linux: XCB Unknown request in queue while dequeuing
+#            Most likely this is a multi-threaded client and XInitThreads has not been called
+#            ../../src/xcb_io.c:178: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimNEWT $*
+# this one works - though !
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimNEWT $* 
+
+# ATI/Linux XCB Unknown request in queue while dequeuing
+#           Most likely this is a multi-threaded client and XInitThreads has not been called
+#           ../../src/xcb_io.c:178: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $*
+
+# NEW
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestBug605FlippedImageNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestBug605FlippedImageAWT $*
+
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch11NEWT $*
+
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $*
 
 
 $spath/count-edt-start.sh java-run.log
diff --git a/make/stub_includes/jni/macosx/jawt_md.h b/make/stub_includes/jni/macosx/jawt_md.h
index 3a371af..519a513 100644
--- a/make/stub_includes/jni/macosx/jawt_md.h
+++ b/make/stub_includes/jni/macosx/jawt_md.h
@@ -1,8 +1,25 @@
-//
-//  jawt_md.h
-//
-//  Copyright (c) 2002 Apple computer Inc. All rights reserved.
-//
+/**
+ * This C header file is derived from Apple's Java SDK provided C header file
+ * with the following copyright notice:
+ *
+ *   Copyright (c) 2002 Apple computer Inc. All rights reserved.
+ * 
+ * This version has complex comments removed and does not contain inlined algorithms etc, if any existed.
+ *
+ * The original C header file was included to JOGL on Mon Jun 15 22:57:38 2009
+ * (commit cbc45e816f4ee81031bffce19a99550681462a24) by Sun Microsystem's staff and were approved. 
+ *
+ * This C header file is included due to ensure compatibility with - and invocation of the JAWT protocol.
+ * They are processed by GlueGen to create a Java binding for JAWT invocation only.
+ * 
+ * http://ftp.resource.org/courts.gov/c/F3/387/387.F3d.522.03-5400.html (36)
+ * "Atari Games Corp. v. Nintendo of Am., Inc., Nos. 88-4805 & 89-0027, 1993 WL 207548, at *1 (N.D.Cal. May 18, 1993) ("Atari III") 
+ * ("Program code that is strictly necessary to achieve current compatibility presents a merger problem, almost by definition, 
+ * and is thus excluded from the scope of any copyright.")."
+ *
+ * http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=OJ:L:2009:111:0016:0022:EN:PDF
+ * L 111/17 (10) and (15)
+ */
 
 #ifndef _JAVASOFT_JAWT_MD_H_
 #define _JAVASOFT_JAWT_MD_H_
@@ -27,16 +44,17 @@ typedef struct JAWT_MacOSXDrawingSurfaceInfo
 }
 JAWT_MacOSXDrawingSurfaceInfo;
 
-/** 
- * JAWT_DrawingSurfaceInfo.getPlatformInfo()
- *
- * >= 10.6.4 if JAWT_MACOSX_USE_CALAYER is set in JAWT version
- */
-typedef struct JAWT_SurfaceLayers
-{
-    CALayer *layer;
-}
-JAWT_SurfaceLayers;
+#ifndef __GLUEGEN__
+
+    #define JAWT_MACOSX_USE_CALAYER 0x80000000
+
+    /** Java7 and Java6 (OSX >= 10.6.4) CALayer surface if provided (Bit JAWT_MACOSX_USE_CALAYER set in the JAWT version) */
+    @protocol JAWT_SurfaceLayers
+    @property (readwrite, retain) CALayer *layer;
+    @property (readonly) CALayer *windowLayer;
+    @end
+
+#endif __GLUEGEN__
 
 #ifdef __cplusplus
 }
diff --git a/make/stub_includes/opengl/GL/glext.h b/make/stub_includes/opengl/GL/glext.h
index e5de746..6048075 100644
--- a/make/stub_includes/opengl/GL/glext.h
+++ b/make/stub_includes/opengl/GL/glext.h
@@ -1859,7 +1859,9 @@ extern "C" {
 #endif
 
 #ifndef GL_ARB_copy_buffer
+#define GL_COPY_READ_BUFFER_BINDING       0x8F36
 #define GL_COPY_READ_BUFFER               0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING      0x8F37
 #define GL_COPY_WRITE_BUFFER              0x8F37
 #endif
 
diff --git a/make/stub_includes/opengl/GL3/gl3.h b/make/stub_includes/opengl/GL3/gl3.h
index daa0c25..d66d49d 100644
--- a/make/stub_includes/opengl/GL3/gl3.h
+++ b/make/stub_includes/opengl/GL3/gl3.h
@@ -1409,7 +1409,9 @@ typedef void GLvoid;
 #endif
 
 #ifndef GL_ARB_copy_buffer
+#define GL_COPY_READ_BUFFER_BINDING       0x8F36
 #define GL_COPY_READ_BUFFER               0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING      0x8F37
 #define GL_COPY_WRITE_BUFFER              0x8F37
 #endif
 
diff --git a/make/stub_includes/opengl/macosx-window-system.h b/make/stub_includes/opengl/macosx-window-system.h
index aaa0cc4..2bfe86a 100644
--- a/make/stub_includes/opengl/macosx-window-system.h
+++ b/make/stub_includes/opengl/macosx-window-system.h
@@ -36,6 +36,8 @@ NSOpenGLContext* createContext(NSOpenGLContext* shareContext,
                     NSOpenGLPixelFormat* pixelFormat,
                     Bool opaque,
                     int* viewNotReady);
+void setContextView(NSOpenGLContext* ctx, NSView* view);
+void clearDrawable(NSOpenGLContext* ctx);
 Bool  makeCurrentContext(NSOpenGLContext* ctx);
 Bool  clearCurrentContext(NSOpenGLContext *ctx);
 Bool  deleteContext(NSOpenGLContext* ctx, Bool releaseOnMainThread);
@@ -55,6 +57,7 @@ void setContextTextureImageToPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer*
 Bool isNSOpenGLPixelBuffer(uint64_t object);
 
 NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, int gl3ShaderProgramName, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight);
+void setNSOpenGLLayerEnabled(NSOpenGLLayer* layer, Bool enable);
 void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval);
 void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros);
 void setNSOpenGLLayerNeedsDisplayFBO(NSOpenGLLayer* layer, uint32_t texID);
diff --git a/make/stub_includes/win32/WindowsDWM.h b/make/stub_includes/win32/WindowsDWM.h
index 357602d..2115a59 100644
--- a/make/stub_includes/win32/WindowsDWM.h
+++ b/make/stub_includes/win32/WindowsDWM.h
@@ -1,8 +1,11 @@
 #ifndef WGL_DWM_VERSION_1_X
 
-#define DWM_BB_ENABLE 1
+#define DWM_BB_ENABLE                 0x00000001
+#define DWM_BB_BLURREGION             0x00000002
+#define DWM_BB_TRANSITIONONMAXIMIZED  0x00000004
 #define DWM_EC_DISABLECOMPOSITION     0
 #define DWM_EC_ENABLECOMPOSITION      1
+
   
 typedef struct tagDWM_BLURBEHIND {  
     DWORD dwFlags;  
diff --git a/make/versions.xml b/make/versions.xml
deleted file mode 100644
index 6256831..0000000
--- a/make/versions.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<!-- This file is the one canonical location containing the version
-     numbers for the various components such as JOGL and Newt. -->
-
-<project name="versions">
-
-  <!-- This is the base version of JOGL. For official release builds,
-       and nightly builds, this should be in the form "x.y{.z}", for
-       example, "2.0" or "2.1.1". Nightly builds will have a "-pre-"
-       and a timestamp automatically added to this version number. For
-       intermediate release builds, this should be in the form, for
-       example, "2.0-beta1" or "2.0-rc1". For large releases, push
-       betas before release candidates to give the Community time to
-       react.-->
-  <property name="jogl_base_version" value="2.0" />
-  <property name="jogl_int_version"  value="0914011" /> <!-- xxyyzzz, xx=API yy screen-from-to zzz app-version-->
-
-  <!-- Uncomment this property in order to produce a JOGL release
-       build without running the "RI" (Reference Implementation)
-       target in build-jogl.xml. This should be uncommented for
-       official release builds and intermediate release builds, but
-       commented out for nightly builds. -->
-  <!-- <property name="jogl.ri" value="true" /> -->
-
-  <!-- Base version of the NativeWindow interface, following the same
-       rules as above -->
-  <property name="nativewindow_base_version" value="2.0" />
-
-  <!-- Uncomment this property in order to produce a NativeWindow
-       build without running the "RI" (Reference Implementation)
-       target in build-nativewindow.xml. This should be uncommented for
-       official release builds and intermediate release builds, but
-       commented out for nightly builds. -->
-  <!-- <property name="nativewindow.ri" value="true" /> -->
-
-  <!-- Base version of the Newt library, following the same
-       rules as above -->
-  <property name="newt_base_version" value="2.0" />
-
-  <!-- Newt isn't covered by a JSR at the moment, so there is little
-       value in having a different reference implementation
-       vs. intermediate build numbering scheme, but for the moment
-       let's keep things symmetric. This should be uncommented for
-       official release builds and intermediate release builds, but
-       commented out for nightly builds.  -->
-  <!-- <property name="newt.ri" value="true" /> -->
-
-</project>
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
old mode 100755
new mode 100644
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
index 809c678..075c8bf 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
@@ -454,34 +454,69 @@ public class GLEmitter extends ProcAddressEmitter {
         return (GLConfiguration) getConfig();
     }
 
+    /**
+     * {@inheritDoc}
+     */   
     @Override
     protected void endProcAddressTable() throws Exception {
         PrintWriter w = tableWriter;
-
-        w.println("  /**");
-        w.println("   * This is a convenience method to get (by name) the native function");
-        w.println("   * pointer for a given function. It lets you avoid having to");
-        w.println("   * manually compute the "" + PROCADDRESS_VAR_PREFIX + " + ");
-        w.println("   * <functionName>" member variable name and look it up via");
-        w.println("   * reflection; it also will throw an exception if you try to get the");
-        w.println("   * address of an unknown function, or one that is statically linked");
-        w.println("   * and therefore does not have a function pointer in this table.");
-        w.println("   *");
-        w.println("   * @throws RuntimeException if the function pointer was not found in");
-        w.println("   *   this table, either because the function was unknown or because");
-        w.println("   *   it was statically linked.");
-        w.println("   */");
-        w.println("  public long getAddressFor(String functionNameUsr) {");
-        w.println("    String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
-        w.println("    String addressFieldNameBase = PROCADDRESS_VAR_PREFIX + functionNameBase;");
-        w.println("    java.lang.reflect.Field addressField = null;");
-        w.println("    int  funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
-        w.println("    for(int i = 0; null==addressField && i < funcNamePermNum; i++) {");
-        w.println("        String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
-        w.println("        try {");
-        w.println("          addressField = getClass().getField(addressFieldName);");
-        w.println("        } catch (Exception e) { }");
+        
+        w.println("  @Override");
+        w.println("  protected boolean isFunctionAvailableImpl(String functionNameUsr) throws IllegalArgumentException  {");
+        w.println("    final String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
+        w.println("    final String addressFieldNameBase = \"" + PROCADDRESS_VAR_PREFIX + "\" + functionNameBase;");
+        w.println("    final int funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");        
+        w.println("    final java.lang.reflect.Field addressField = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<java.lang.reflect.Field>() {");
+        w.println("        public final java.lang.reflect.Field run() {");
+        w.println("            java.lang.reflect.Field addressField = null;");
+        w.println("            for(int i = 0; i < funcNamePermNum; i++) {");
+        w.println("                final String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
+        w.println("                try {");
+        w.println("                    addressField = "+tableClassName+".class.getDeclaredField( addressFieldName );");
+        w.println("                    addressField.setAccessible(true); // we need to read the protected value!");
+        w.println("                    return addressField;");
+        w.println("                } catch (NoSuchFieldException ex) { }");
+        w.println("            }");
+        w.println("            return null;");
+        w.println("        } } );");
+        w.println();
+        w.println("    if(null==addressField) {");
+        w.println("      // The user is calling a bogus function or one which is not");
+        w.println("      // runtime linked");
+        w.println("      throw new RuntimeException(");
+        w.println("          \"WARNING: Address field query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
+        w.println("          \"\\\"; it's either statically linked or address field is not a known \" +");
+        w.println("          \"function\");");
+        w.println("    } ");
+        w.println("    try {");
+        w.println("      return 0 != addressField.getLong(this);");
+        w.println("    } catch (Exception e) {");
+        w.println("      throw new RuntimeException(");
+        w.println("          \"WARNING: Address query failed for \\\"\" + functionNameBase + \"\\\"/\\\"\" + functionNameUsr +");
+        w.println("          \"\\\"; it's either statically linked or is not a known \" +");
+        w.println("          \"function\", e);");
         w.println("    }");
+        w.println("  }");
+        
+        w.println("  @Override");
+        w.println("  public long getAddressFor(String functionNameUsr) throws SecurityException, IllegalArgumentException {");
+        w.println("    SecurityUtil.checkAllLinkPermission();");
+        w.println("    final String functionNameBase = "+GLNameResolver.class.getName()+".normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);");
+        w.println("    final String addressFieldNameBase = \"" + PROCADDRESS_VAR_PREFIX + "\" + functionNameBase;");
+        w.println("    final int  funcNamePermNum = "+GLNameResolver.class.getName()+".getFuncNamePermutationNumber(functionNameBase);");
+        w.println("    final java.lang.reflect.Field addressField = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<java.lang.reflect.Field>() {");
+        w.println("        public final java.lang.reflect.Field run() {");
+        w.println("            java.lang.reflect.Field addressField = null;");
+        w.println("            for(int i = 0; i < funcNamePermNum; i++) {");
+        w.println("                final String addressFieldName = "+GLNameResolver.class.getName()+".getFuncNamePermutation(addressFieldNameBase, i);");
+        w.println("                try {");
+        w.println("                    addressField = "+tableClassName+".class.getDeclaredField( addressFieldName );");
+        w.println("                    addressField.setAccessible(true); // we need to read the protected value!");
+        w.println("                    return addressField;");
+        w.println("                } catch (NoSuchFieldException ex) { }");
+        w.println("            }");
+        w.println("            return null;");
+        w.println("        } } );");
         w.println();
         w.println("    if(null==addressField) {");
         w.println("      // The user is calling a bogus function or one which is not");
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLJavaMethodBindingEmitter.java
old mode 100755
new mode 100644
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureEmitter.java
old mode 100755
new mode 100644
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/nativesig/NativeSignatureJavaMethodBindingEmitter.java
old mode 100755
new mode 100644
diff --git a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
old mode 100755
new mode 100644
index e60fba0..a374978
--- a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
@@ -32,11 +32,11 @@ import java.util.Collections;
 
 import com.jogamp.graph.curve.tess.Triangulation;
 import com.jogamp.graph.curve.tess.Triangulator;
-import com.jogamp.graph.geom.AABBox;
 import com.jogamp.graph.geom.Outline;
 import com.jogamp.graph.geom.Triangle;
 import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.math.VectorUtil;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.math.geom.AABBox;
 
 
 /** A Generic shape objects which is defined by a list of Outlines.
diff --git a/src/jogl/classes/com/jogamp/graph/curve/Region.java b/src/jogl/classes/com/jogamp/graph/curve/Region.java
index af15f9d..8b6d000 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/Region.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/Region.java
@@ -31,9 +31,9 @@ import java.util.ArrayList;
 
 import jogamp.opengl.Debug;
 
-import com.jogamp.graph.geom.AABBox;
 import com.jogamp.graph.geom.Triangle;
 import com.jogamp.graph.geom.Vertex;
+import com.jogamp.opengl.math.geom.AABBox;
 
 /** Abstract Outline shape GL representation
  *  define the method an OutlineShape(s) is
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
old mode 100755
new mode 100644
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
index 3c23733..9981295 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
@@ -33,6 +33,7 @@ import javax.media.opengl.GL2ES2;
 import javax.media.opengl.GLException;
 import javax.media.opengl.fixedfunc.GLMatrixFunc;
 
+import com.jogamp.opengl.util.glsl.ShaderCode;
 import com.jogamp.opengl.util.glsl.ShaderState;
 import com.jogamp.opengl.util.PMVMatrix;
 
@@ -139,8 +140,10 @@ public abstract class Renderer {
             throw new GLException("Error setting PMVMatrix in shader: "+rs.getShaderState());
         }
         
-        if(!rs.getShaderState().uniform(gl, rs.getWeight())) {
-            throw new GLException("Error setting weight in shader: "+rs.getShaderState());
+        if( Region.isNonUniformWeight( getRenderModes() ) ) {
+            if(!rs.getShaderState().uniform(gl, rs.getWeight())) {
+                throw new GLException("Error setting weight in shader: "+rs.getShaderState());
+            }
         }
                 
         if(!rs.getShaderState().uniform(gl, rs.getAlpha())) {
@@ -181,7 +184,7 @@ public abstract class Renderer {
         	 throw new IllegalArgumentException("Weight out of range");
         }
         rs.getWeight().setData(v);
-        if(null != gl && rs.getShaderState().inUse()) {
+        if(null != gl && rs.getShaderState().inUse() && Region.isNonUniformWeight( getRenderModes() ) ) {
             rs.getShaderState().uniform(gl, rs.getWeight());
         }
     }
@@ -261,21 +264,31 @@ public abstract class Renderer {
         return true;        
     }
 
-    protected String getVertexShaderName(GL2ES2 gl) {
-        return "curverenderer01" + getShaderGLVersionSuffix(gl);
+    protected String getVertexShaderName() {
+        return "curverenderer" + getImplVersion();
     }
     
-    protected String getFragmentShaderName(GL2ES2 gl) {
-        final String type = "01" ; // Region.isNonUniformWeight(renderModes) ? "02" : "01" ;
-        final String pass = Region.isVBAA(renderModes) ? "b" : "a" ;
-        return "curverenderer" + type + pass + getShaderGLVersionSuffix(gl);
+    protected String getFragmentShaderName() {
+        final String version = getImplVersion(); 
+        final String pass = Region.isVBAA(renderModes) ? "-2pass" : "-1pass" ;
+        final String weight = Region.isNonUniformWeight(renderModes) ? "-weight" : "" ;
+        return "curverenderer" + version + pass + weight;
     }
-        
-    protected String getShaderGLVersionSuffix(GL2ES2 gl) {
-        if(gl.isGLES2()) {
-            return "-es2";
+
+    // FIXME: Really required to have sampler2D def. precision ? If not, we can drop getFragmentShaderPrecision(..) and use default ShaderCode ..
+    public static final String es2_precision_fp = "\nprecision mediump float;\nprecision mediump int;\nprecision mediump sampler2D;\n";
+    
+    protected String getFragmentShaderPrecision(GL2ES2 gl) {
+        if( gl.isGLES2() ) {
+            return es2_precision_fp;
+        }
+        if( ShaderCode.requiresGL3DefaultPrecision(gl) ) {
+            return ShaderCode.gl3_default_precision_fp;
         }
-        return "-gl2";
-    }    
+        return null;
+    }
     
+    protected String getImplVersion() {
+        return "01";
+    }
 }
\ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/graph/font/Font.java b/src/jogl/classes/com/jogamp/graph/font/Font.java
index e2b3fe5..64a3a3e 100644
--- a/src/jogl/classes/com/jogamp/graph/font/Font.java
+++ b/src/jogl/classes/com/jogamp/graph/font/Font.java
@@ -27,7 +27,7 @@
  */
 package com.jogamp.graph.font;
 
-import com.jogamp.graph.geom.AABBox;
+import com.jogamp.opengl.math.geom.AABBox;
 
 /**
  * Interface wrapper for font implementation.
diff --git a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
index 33d4873..bbdfc0e 100644
--- a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
+++ b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
@@ -33,13 +33,23 @@ import java.net.URLConnection;
 
 import com.jogamp.common.util.PropertyAccess;
 import com.jogamp.common.util.ReflectionUtil;
-import com.jogamp.common.util.SecurityUtil;
 
 import jogamp.graph.font.FontConstructor;
 import jogamp.graph.font.JavaFontLoader;
 import jogamp.graph.font.UbuntuFontLoader;
 
+/**
+ * The optional property <i>jogamp.graph.font.ctor</i>
+ * allows user to specify the {@link FontConstructor} implementation.
+ * <p>
+ * Default {@link FontConstructor} is {@link jogamp.graph.font.typecast.TypecastFontConstructor},
+ * i.e. using our internal <i>typecast</i> branch.
+ * </p>
+ */
 public class FontFactory {
+    private static final String FontConstructorPropKey = "jogamp.graph.font.ctor";
+    private static final String DefaultFontConstructor = "jogamp.graph.font.typecast.TypecastFontConstructor";
+    
     /** Ubuntu is the default font family */
     public static final int UBUNTU = 0;
     
@@ -54,9 +64,9 @@ public class FontFactory {
          *   "jogamp.graph.font.typecast.TypecastFontFactory" (default)
          *   "jogamp.graph.font.ttf.TTFFontImpl"
          */        
-        String fontImplName = PropertyAccess.getProperty("FontImpl", true, SecurityUtil.getCommonAccessControlContext(FontFactory.class));
+        String fontImplName = PropertyAccess.getProperty(FontConstructorPropKey, true);
         if(null == fontImplName) {
-            fontImplName = "jogamp.graph.font.typecast.TypecastFontConstructor";
+            fontImplName = DefaultFontConstructor;
         }
         fontConstr = (FontConstructor) ReflectionUtil.createInstance(fontImplName, FontFactory.class.getClassLoader());
     }
diff --git a/src/jogl/classes/com/jogamp/graph/geom/Outline.java b/src/jogl/classes/com/jogamp/graph/geom/Outline.java
index 5030488..12c4586 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/Outline.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/Outline.java
@@ -30,7 +30,8 @@ package com.jogamp.graph.geom;
 import java.util.ArrayList;
 
 import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.math.VectorUtil;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.math.geom.AABBox;
 
 
 
diff --git a/src/jogl/classes/com/jogamp/graph/geom/Vertex.java b/src/jogl/classes/com/jogamp/graph/geom/Vertex.java
index 3080f32..e3df86d 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/Vertex.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/Vertex.java
@@ -27,10 +27,12 @@
  */
 package com.jogamp.graph.geom;
 
+import com.jogamp.opengl.math.Vert3fImmutable;
+
 /**
  * A Vertex with custom memory layout using custom factory. 
  */
-public interface Vertex extends Cloneable {
+public interface Vertex extends Vert3fImmutable, Cloneable {
 
     public static interface Factory <T extends Vertex> {
         T create();
@@ -47,20 +49,12 @@ public interface Vertex extends Cloneable {
      */
     void setCoord(float[] coordsBuffer, int offset, int length);
     
-    float[] getCoord();
-
     void setX(float x);
 
     void setY(float y);
 
     void setZ(float z);
 
-    float getX();
-
-    float getY();
-
-    float getZ();
-
     boolean isOnCurve();
 
     void setOnCurve(boolean onCurve);
diff --git a/src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java b/src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java
index 9dade17..97e438b 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java
@@ -28,7 +28,7 @@
 package com.jogamp.graph.geom.opengl;
 
 import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.math.VectorUtil;
+import com.jogamp.opengl.math.VectorUtil;
 
 /** A Simple Vertex Implementation. Where the coordinates, and other attributes are
  * float based, and the coordinates and texture coordinates are saved in two float arrays.
@@ -88,6 +88,12 @@ public class SVertex implements Vertex {
         System.arraycopy(coordsBuffer, offset, coord, 0, length);
     }
         
+    @Override
+    public int getCoordCount() {
+        return 3;
+    }
+    
+    @Override
     public final float[] getCoord() {
         return coord;
     }
diff --git a/src/jogl/classes/com/jogamp/graph/math/Quaternion.java b/src/jogl/classes/com/jogamp/graph/math/Quaternion.java
deleted file mode 100755
index adaf073..0000000
--- a/src/jogl/classes/com/jogamp/graph/math/Quaternion.java
+++ /dev/null
@@ -1,382 +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.graph.math;
-
-import jogamp.graph.math.MathFloat;
-
-public class Quaternion {
-    protected float x,y,z,w;
-
-    public Quaternion(){
-
-    }
-    
-    public Quaternion(float x, float y, float z, float w) {
-        this.x = x;
-        this.y = y;
-        this.z = z;
-        this.w = w;
-    }
-    
-    /** Constructor to create a rotation based quaternion from two vectors
-     * @param vector1
-     * @param vector2
-     */
-    public Quaternion(float[] vector1, float[] vector2) 
-    {
-        float theta = (float)MathFloat.acos(dot(vector1, vector2));
-        float[] cross = cross(vector1,vector2);
-        cross = normalizeVec(cross);
-
-        this.x = (float)MathFloat.sin(theta/2)*cross[0];
-        this.y = (float)MathFloat.sin(theta/2)*cross[1];
-        this.z = (float)MathFloat.sin(theta/2)*cross[2];
-        this.w = (float)MathFloat.cos(theta/2);
-        this.normalize();
-    }
-    
-    /** Transform the rotational quaternion to axis based rotation angles
-     * @return new float[4] with ,theta,Rx,Ry,Rz
-     */
-    public float[] toAxis()
-    {
-        float[] vec = new float[4];
-        float scale = (float)MathFloat.sqrt(x * x + y * y + z * z);
-        vec[0] =(float) MathFloat.acos(w) * 2.0f;
-        vec[1] = x / scale;
-        vec[2] = y / scale;
-        vec[3] = z / scale;
-        return vec;
-    }
-    
-    /** Normalize a vector
-     * @param vector input vector
-     * @return normalized vector
-     */
-    private float[] normalizeVec(float[] vector)
-    {
-        float[] newVector = new float[3];
-
-        float d = MathFloat.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]);
-        if(d> 0.0f)
-        {
-            newVector[0] = vector[0]/d;
-            newVector[1] = vector[1]/d;
-            newVector[2] = vector[2]/d;
-        }
-        return newVector;
-    }
-    /** compute the dot product of two points
-     * @param vec1 vector 1
-     * @param vec2 vector 2
-     * @return the dot product as float
-     */
-    private float dot(float[] vec1, float[] vec2)
-    {
-        return (vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]);
-    }
-    /** cross product vec1 x vec2
-     * @param vec1 vector 1
-     * @param vec2 vecttor 2
-     * @return the resulting vector
-     */
-    private float[] cross(float[] vec1, float[] vec2)
-    {
-        float[] out = new float[3];
-
-        out[0] = vec2[2]*vec1[1] - vec2[1]*vec1[2];
-        out[1] = vec2[0]*vec1[2] - vec2[2]*vec1[0];
-        out[2] = vec2[1]*vec1[0] - vec2[0]*vec1[1];
-
-        return out;
-    }
-    public float getW() {
-        return w;
-    }
-    public void setW(float w) {
-        this.w = w;
-    }
-    public float getX() {
-        return x;
-    }
-    public void setX(float x) {
-        this.x = x;
-    }
-    public float getY() {
-        return y;
-    }
-    public void setY(float y) {
-        this.y = y;
-    }
-    public float getZ() {
-        return z;
-    }
-    public void setZ(float z) {
-        this.z = z;
-    }
-
-    /** Add a quaternion
-     * @param q quaternion
-     */
-    public void add(Quaternion q)
-    {
-        x+=q.x;
-        y+=q.y;
-        z+=q.z;
-    }
-    
-    /** Subtract a quaternion
-     * @param q quaternion
-     */
-    public void subtract(Quaternion q)
-    {
-        x-=q.x;
-        y-=q.y;
-        z-=q.z;
-    }
-    
-    /** Divide a quaternion by a constant
-     * @param n a float to divide by
-     */
-    public void divide(float n)
-    {
-        x/=n;
-        y/=n;
-        z/=n;
-    }
-    
-    /** Multiply this quaternion by 
-     * the param quaternion
-     * @param q a quaternion to multiply with
-     */
-    public void mult(Quaternion q)
-    {
-        float w1 = w*q.w - (x*q.x + y*q.y + z*q.z);
-
-        float x1 = w*q.z + q.w*z + y*q.z - z*q.y;
-        float y1 = w*q.x + q.w*x + z*q.x - x*q.z;
-        float z1 = w*q.y + q.w*y + x*q.y - y*q.x;
-
-        w = w1;
-        x = x1;
-        y = y1;
-        z = z1; 
-    }
-    
-    /** Multiply a quaternion by a constant
-     * @param n a float constant
-     */
-    public void mult(float n)
-    {
-        x*=n;
-        y*=n;
-        z*=n;
-    }
-    
-    /** Normalize a quaternion required if  
-     *  to be used as a rotational quaternion
-     */
-    public void normalize()
-    {
-        float norme = (float)MathFloat.sqrt(w*w + x*x + y*y + z*z);
-        if (norme == 0.0f)
-        {
-            w = 1.0f; 
-            x = y = z = 0.0f;
-        }
-        else
-        {
-            float recip = 1.0f/norme;
-
-            w *= recip;
-            x *= recip;
-            y *= recip;
-            z *= recip;
-        }
-    }
-    
-    /** Invert the quaternion If rotational, 
-     * will produce a the inverse rotation
-     */
-    public void inverse()
-    {
-        float norm = w*w + x*x + y*y + z*z;
-
-        float recip = 1.0f/norm;
-
-        w *= recip;
-        x = -1*x*recip;
-        y = -1*y*recip;
-        z = -1*z*recip;
-    }
-    
-    /** Transform this quaternion to a
-     * 4x4 column matrix representing the rotation
-     * @return new float[16] column matrix 4x4 
-     */
-    public float[] toMatrix()
-    {
-        float[] matrix = new float[16];
-        matrix[0] = 1.0f - 2*y*y - 2*z*z;
-        matrix[1] = 2*x*y + 2*w*z;
-        matrix[2] = 2*x*z - 2*w*y;
-        matrix[3] = 0;
-
-        matrix[4] = 2*x*y - 2*w*z;
-        matrix[5] = 1.0f - 2*x*x - 2*z*z;
-        matrix[6] = 2*y*z + 2*w*x;
-        matrix[7] = 0;
-
-        matrix[8]  = 2*x*z + 2*w*y;
-        matrix[9]  = 2*y*z - 2*w*x;
-        matrix[10] = 1.0f - 2*x*x - 2*y*y;
-        matrix[11] = 0;
-
-        matrix[12] = 0;
-        matrix[13] = 0;
-        matrix[14] = 0;
-        matrix[15] = 1;
-        return matrix;
-    }
-    
-    /** Set this quaternion from a Sphereical interpolation
-     *  of two param quaternion, used mostly for rotational animation
-     * @param a initial quaternion
-     * @param b target quaternion
-     * @param t float between 0 and 1 representing interp.
-     */
-    public void slerp(Quaternion a,Quaternion b, float t)
-    {
-        float omega, cosom, sinom, sclp, sclq;
-        cosom = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
-        if ((1.0f+cosom) > MathFloat.E) {
-            if ((1.0f-cosom) > MathFloat.E) {
-                omega = (float)MathFloat.acos(cosom);
-                sinom = (float)MathFloat.sin(omega);
-                sclp = (float)MathFloat.sin((1.0f-t)*omega) / sinom;
-                sclq = (float)MathFloat.sin(t*omega) / sinom;
-            }
-            else {
-                sclp = 1.0f - t;
-                sclq = t;
-            }
-            x = sclp*a.x + sclq*b.x;
-            y = sclp*a.y + sclq*b.y;
-            z = sclp*a.z + sclq*b.z;
-            w = sclp*a.w + sclq*b.w;
-        }
-        else {
-            x =-a.y;
-            y = a.x;
-            z =-a.w;
-            w = a.z;
-            sclp = MathFloat.sin((1.0f-t) * MathFloat.PI * 0.5f);
-            sclq = MathFloat.sin(t * MathFloat.PI * 0.5f);
-            x = sclp*a.x + sclq*b.x;
-            y = sclp*a.y + sclq*b.y;
-            z = sclp*a.z + sclq*b.z;
-        }
-    }
-    
-    /** Check if this quaternion is empty, ie (0,0,0,1)
-     * @return true if empty, false otherwise
-     */
-    public boolean isEmpty()
-    {
-        if (w==1 && x==0 && y==0 && z==0)
-            return true;
-        return false;
-    }
-    
-    /** Check if this quaternion represents an identity
-     * matrix, for rotation.
-     * @return true if it is an identity rep., false otherwise
-     */
-    public boolean isIdentity()
-    {
-        if (w==0 && x==0 && y==0 && z==0)
-            return true;
-        return false;
-    }
-    
-    /** compute the quaternion from a 3x3 column matrix
-     * @param m 3x3 column matrix 
-     */
-    public void setFromMatrix(float[] m) {
-        float T= m[0] + m[4] + m[8] + 1;
-        if (T>0){
-            float S = 0.5f / (float)MathFloat.sqrt(T);
-            w = 0.25f / S;
-            x = ( m[5] - m[7]) * S;
-            y = ( m[6] - m[2]) * S;
-            z = ( m[1] - m[3] ) * S;
-        }
-        else{
-            if ((m[0] > m[4])&(m[0] > m[8])) { 
-                float S = MathFloat.sqrt( 1.0f + m[0] - m[4] - m[8] ) * 2f; // S=4*qx 
-                w = (m[7] - m[5]) / S;
-                x = 0.25f * S;
-                y = (m[3] + m[1]) / S; 
-                z = (m[6] + m[2]) / S; 
-            } 
-            else if (m[4] > m[8]) { 
-                float S = MathFloat.sqrt( 1.0f + m[4] - m[0] - m[8] ) * 2f; // S=4*qy
-                w = (m[6] - m[2]) / S;
-                x = (m[3] + m[1]) / S; 
-                y = 0.25f * S;
-                z = (m[7] + m[5]) / S; 
-            } 
-            else { 
-                float S = MathFloat.sqrt( 1.0f + m[8] - m[0] - m[4] ) * 2f; // S=4*qz
-                w = (m[3] - m[1]) / S;
-                x = (m[6] + m[2]) / S; 
-                y = (m[7] + m[5]) / S; 
-                z = 0.25f * S;
-            } 
-        }
-    }
-    
-    /** Check if the the 3x3 matrix (param) is in fact 
-     * an affine rotational matrix
-     * @param m 3x3 column matrix
-     * @return true if representing a rotational matrix, false otherwise
-     */
-    public boolean isRotationMatrix(float[] m) {
-        double epsilon = 0.01; // margin to allow for rounding errors
-        if (MathFloat.abs(m[0]*m[3] + m[3]*m[4] + m[6]*m[7]) > epsilon) return false;
-        if (MathFloat.abs(m[0]*m[2] + m[3]*m[5] + m[6]*m[8]) > epsilon) return false;
-        if (MathFloat.abs(m[1]*m[2] + m[4]*m[5] + m[7]*m[8]) > epsilon) return false;
-        if (MathFloat.abs(m[0]*m[0] + m[3]*m[3] + m[6]*m[6] - 1) > epsilon) return false;
-        if (MathFloat.abs(m[1]*m[1] + m[4]*m[4] + m[7]*m[7] - 1) > epsilon) return false;
-        if (MathFloat.abs(m[2]*m[2] + m[5]*m[5] + m[8]*m[8] - 1) > epsilon) return false;
-        return (MathFloat.abs(determinant(m)-1) < epsilon);
-    }
-    private float determinant(float[] m) {
-          return m[0]*m[4]*m[8] + m[3]*m[7]*m[2] + m[6]*m[1]*m[5] - m[0]*m[7]*m[5] - m[3]*m[1]*m[8] - m[6]*m[4]*m[2];
-    }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java
index b7188a7..7060bb7 100644
--- a/src/jogl/classes/com/jogamp/opengl/FBObject.java
+++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java
@@ -31,6 +31,7 @@ package com.jogamp.opengl;
 import java.util.Arrays;
 
 import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
 import javax.media.opengl.GL2GL3;
 import javax.media.opengl.GL3;
 import javax.media.opengl.GLBase;
@@ -59,7 +60,6 @@ import com.jogamp.opengl.FBObject.Attachment.Type;
  */
 public class FBObject {
     protected static final boolean DEBUG = Debug.debug("FBObject");
-    private static final boolean forceMinimumFBOSupport = Debug.isPropertyDefined("jogl.fbo.force.min", true);
     private static final boolean FBOResizeQuirk = false;
     
     private static enum DetachAction { NONE, DISPOSE, RECREATE };
@@ -642,9 +642,9 @@ public class FBObject {
     private Colorbuffer[] colorAttachmentPoints; // colorbuffer attachment points 
     private RenderAttachment depth, stencil; // depth and stencil maybe equal in case of packed-depth-stencil
 
-    private final FBObject samplesSink; // MSAA sink
-    private TextureAttachment samplesSinkTexture; 
-    private boolean samplesSinkDirty;
+    private FBObject samplingSink; // MSAA sink
+    private TextureAttachment samplingSinkTexture; 
+    private boolean samplingSinkDirty;
 
     //
     // ColorAttachment helper ..
@@ -746,9 +746,6 @@ public class FBObject {
      * </p>
      */
     public FBObject() {
-        this(false);
-    }
-    /* pp */ FBObject(boolean isSampleSink) {
         this.initialized = false;
         
         // TBD @ init
@@ -779,9 +776,9 @@ public class FBObject {
         this.depth = null;
         this.stencil = null;                
         
-        this.samplesSink = isSampleSink ? null : new FBObject(true);
-        this.samplesSinkTexture = null;
-        this.samplesSinkDirty = true;
+        this.samplingSink = null;
+        this.samplingSinkTexture = null;
+        this.samplingSinkDirty = true;
     }
     
     private void init(GL gl, int width, int height, int samples) throws GLException {
@@ -813,9 +810,10 @@ public class FBObject {
 
         int realMaxColorAttachments = 1;
         maxColorAttachments = 1;
-        if( null != samplesSink && fullFBOSupport || NV_fbo_color_attachments ) {
+        if( fullFBOSupport || NV_fbo_color_attachments ) {
             try {
-                gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, val, 0);
+                val[0] = 0;
+                gl.glGetIntegerv(GL2ES2.GL_MAX_COLOR_ATTACHMENTS, val, 0);
                 realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1
             } catch (GLException gle) { gle.printStackTrace(); }
         }
@@ -825,18 +823,15 @@ public class FBObject {
         colorAttachmentCount = 0;
         
         maxSamples = gl.getMaxRenderbufferSamples();
-        if(!forceMinimumFBOSupport) {
-            gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
-            maxTextureSize = val[0];
-            gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0);
-            maxRenderbufferSize = val[0];
-        } else {
-            maxTextureSize = 2048;
-            maxRenderbufferSize = 2048;
-        }
+        gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
+        maxTextureSize = val[0];
+        gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0);
+        maxRenderbufferSize = val[0];
         
         checkPreGLError(gl);
         
+        if( 0 >= width )  { width = 1; }
+        if( 0 >= height ) { height = 1; }
         this.width = width;
         this.height = height;
         this.samples = samples <= maxSamples ? samples : maxSamples;
@@ -844,7 +839,6 @@ public class FBObject {
         if(DEBUG) {
             System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+this.samples+" samples");
             System.err.println("fullFBOSupport:           "+fullFBOSupport);
-            System.err.println("isSamplesSink:            "+(null == samplesSink));
             System.err.println("maxColorAttachments:      "+maxColorAttachments+"/"+realMaxColorAttachments+" [capped/real]");
             System.err.println("maxSamples:               "+maxSamples);
             System.err.println("maxTextureSize:           "+maxTextureSize);
@@ -886,7 +880,7 @@ public class FBObject {
             checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException
         }
         bound = true;
-        samplesSinkDirty = true;
+        samplingSinkDirty = true;
         initialized = true;
         
         vStatus = GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; // always incomplete w/o attachments!
@@ -944,7 +938,7 @@ public class FBObject {
      * @throws GLException in case of an error, i.e. size too big, etc ..
      */
     public final void reset(GL gl, int newWidth, int newHeight, int newSamples, boolean resetSamplingSink) {
-        if(!initialized) {
+        if( !initialized ) {
             init(gl, newWidth, newHeight, newSamples);
             return;
         }
@@ -952,10 +946,10 @@ public class FBObject {
         newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp
         
         if( newWidth !=  width || newHeight !=  height || newSamples != samples ) {
-            if(0>=newWidth)  { newWidth = 1; }
-            if(0>=newHeight) { newHeight = 1; }
-            if(newWidth > 2 + maxTextureSize  || newHeight> 2 + maxTextureSize ||
-               newWidth > maxRenderbufferSize || newHeight> maxRenderbufferSize  ) {
+            if( 0 >= newWidth )  { newWidth = 1; }
+            if( 0 >= newHeight ) { newHeight = 1; }
+            if( newWidth > 2 + maxTextureSize  || newHeight > 2 + maxTextureSize ||
+                newWidth > maxRenderbufferSize || newHeight > maxRenderbufferSize  ) {
                 throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]");
             }
         
@@ -968,12 +962,18 @@ public class FBObject {
             width = newWidth;
             height = newHeight;
             samples = newSamples;
+            
+            if(0 < samples && null == samplingSink ) {
+                // needs valid samplingSink for detach*() -> bind()
+                samplingSink = new FBObject();
+                samplingSink.init(gl, width, height, 0);
+            }
             detachAllImpl(gl, true , true);            
             if(resetSamplingSink) {
                 resetSamplingSink(gl);
             }
             
-            samplesSinkDirty = true;
+            samplingSinkDirty = true;
 
             if(!wasBound) {
                 unbind(gl);
@@ -1085,8 +1085,10 @@ public class FBObject {
                 
             case 0:                
             default:
-                System.err.println("Framebuffer " + fbName + " is incomplete, status = " + toHexString(vStatus) + 
-                        " : " + getStatusString(vStatus));
+                if(DEBUG) {
+                    System.err.println("Framebuffer " + fbName + " is incomplete, status = " + toHexString(vStatus) + 
+                            " : " + getStatusString(vStatus));
+                }
                 return false;
         }
     }
@@ -1579,11 +1581,11 @@ public class FBObject {
                     colA.setSamples(samples);
                 } else {
                     // switch to non MSAA
-                    if(null != samplesSinkTexture) {
-                        colbuf = createColorTextureAttachment(samplesSinkTexture.format, width, height, 
-                                                              samplesSinkTexture.dataFormat, samplesSinkTexture.dataType, 
-                                                              samplesSinkTexture.magFilter, samplesSinkTexture.minFilter, 
-                                                              samplesSinkTexture.wrapS, samplesSinkTexture.wrapT);
+                    if(null != samplingSinkTexture) {
+                        colbuf = createColorTextureAttachment(samplingSinkTexture.format, width, height, 
+                                                              samplingSinkTexture.dataFormat, samplingSinkTexture.dataType, 
+                                                              samplingSinkTexture.magFilter, samplingSinkTexture.minFilter, 
+                                                              samplingSinkTexture.wrapS, samplingSinkTexture.wrapT);
                     } else {
                         colbuf = createColorTextureAttachment(gl.getGLProfile(), true, width, height);
                     }
@@ -1787,8 +1789,8 @@ public class FBObject {
      * @param gl the current GL context
      */
     public final void detachAll(GL gl) {
-        if(null != samplesSink) {
-            samplesSink.detachAll(gl);
+        if(null != samplingSink) {
+            samplingSink.detachAll(gl);
         }        
         detachAllImpl(gl, true/* detachNonColorbuffer */, false /* recreate */);
     }
@@ -1803,8 +1805,8 @@ public class FBObject {
      * @param gl the current GL context
      */
     public final void detachAllColorbuffer(GL gl) {
-        if(null != samplesSink) {
-            samplesSink.detachAllColorbuffer(gl);
+        if(null != samplingSink) {
+            samplingSink.detachAllColorbuffer(gl);
         }        
         detachAllImpl(gl, false/* detachNonColorbuffer */, false /* recreate */);
     }
@@ -1821,8 +1823,8 @@ public class FBObject {
         if( !isInitialized() ) {
             return;
         }
-        if(null != samplesSink) {
-            samplesSink.detachAllTexturebuffer(gl);
+        if(null != samplingSink) {
+            samplingSink.detachAllTexturebuffer(gl);
         }
         bind(gl);        
         for(int i=0; i<maxColorAttachments; i++) {
@@ -1839,8 +1841,8 @@ public class FBObject {
         if( !isInitialized() ) {
             return;
         }
-        if(null != samplesSink) {
-            samplesSink.detachAllRenderbuffer(gl);
+        if(null != samplingSink) {
+            samplingSink.detachAllRenderbuffer(gl);
         }
         bind(gl);        
         detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, DetachAction.DISPOSE);
@@ -1898,8 +1900,8 @@ public class FBObject {
             System.err.println("FBObject.destroy.0: "+this);
             // Thread.dumpStack();
         }
-        if( null != samplesSink && samplesSink.isInitialized() ) {
-            samplesSink.destroy(gl);
+        if( null != samplingSink && samplingSink.isInitialized() ) {
+            samplingSink.destroy(gl);
         }
         
         detachAllImpl(gl, true /* detachNonColorbuffer */, false /* recreate */);
@@ -1922,19 +1924,19 @@ public class FBObject {
     }
 
     private final boolean sampleSinkSizeMismatch() {
-        return samplesSink.getWidth() != width || samplesSink.getHeight() != height ;
+        return samplingSink.getWidth() != width || samplingSink.getHeight() != height ;
     }
     private final boolean sampleSinkTexMismatch() {
-        return null == samplesSinkTexture || 0 == samplesSinkTexture.getName() ;
+        return null == samplingSinkTexture || 0 == samplingSinkTexture.getName() ;
     }
     private final boolean sampleSinkDepthStencilMismatch() {
-        final boolean depthMismatch   = ( null != depth && null == samplesSink.depth ) ||
-                                        ( null != depth && null != samplesSink.depth &&
-                                          depth.format != samplesSink.depth.format );
+        final boolean depthMismatch   = ( null != depth && null == samplingSink.depth ) ||
+                                        ( null != depth && null != samplingSink.depth &&
+                                          depth.format != samplingSink.depth.format );
         
-        final boolean stencilMismatch = ( null != stencil && null == samplesSink.stencil ) ||
-                                        ( null != stencil && null != samplesSink.stencil &&
-                                          stencil.format != samplesSink.stencil.format );        
+        final boolean stencilMismatch = ( null != stencil && null == samplingSink.stencil ) ||
+                                        ( null != stencil && null != samplingSink.stencil &&
+                                          stencil.format != samplingSink.stencil.format );        
         
         return depthMismatch || stencilMismatch;                
     }
@@ -1942,6 +1944,10 @@ public class FBObject {
     /**
      * Manually reset the MSAA sampling sink, if used.
      * <p>
+     * If MSAA is being used and no sampling sink is attached via {@link #setSamplingSink(FBObject)}
+     * a new sampling sink is being created.
+     * </p>
+     * <p>
      * Automatically called by {@link #reset(GL, int, int, int, boolean)} 
      * and {@link #syncSamplingSink(GL)}.
      * </p>
@@ -1953,20 +1959,21 @@ public class FBObject {
      * @throws GLException in case of an error, i.e. size too big, etc ..
      */
     public final void resetSamplingSink(GL gl) throws GLException {
-        if(null == samplesSink ) {
-            return; // this is the sample sink!
-        }
         if(0 == samples) {
             // MSAA off
-            if(samplesSink.initialized) {
+            if(null != samplingSink && samplingSink.initialized) {
                 // cleanup
-                samplesSink.detachAll(gl);
+                samplingSink.detachAll(gl);
             }
             return;
         }
         
-        if(!samplesSink.initialized) {
-            samplesSink.init(gl, width, height, 0);
+        if(null == samplingSink ) {
+            samplingSink = new FBObject();
+        }
+        
+        if(!samplingSink.initialized) {
+            samplingSink.init(gl, width, height, 0);
         }
         
         boolean sampleSinkSizeMismatch = sampleSinkSizeMismatch();
@@ -1986,29 +1993,29 @@ public class FBObject {
         unbind(gl);
         
         if(DEBUG) {
-            System.err.println("FBObject.resetSamplingSink: BEGIN\n\tTHIS "+this+",\n\tSINK "+samplesSink+
+            System.err.println("FBObject.resetSamplingSink: BEGIN\n\tTHIS "+this+",\n\tSINK "+samplingSink+
                                "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
         }
                 
         if( sampleSinkDepthStencilMismatch ) {
-            samplesSink.detachAllRenderbuffer(gl);
+            samplingSink.detachAllRenderbuffer(gl);
         }
         
         if( sampleSinkSizeMismatch ) {
-            samplesSink.reset(gl, width, height);
+            samplingSink.reset(gl, width, height);
         }
         
-        if(null == samplesSinkTexture) {
-            samplesSinkTexture = samplesSink.attachTexture2D(gl, 0, true);
-        } else if( 0 == samplesSinkTexture.getName() ) {
-            samplesSinkTexture.setSize(width, height);
-            samplesSink.attachColorbuffer(gl, 0, samplesSinkTexture);
+        if(null == samplingSinkTexture) {
+            samplingSinkTexture = samplingSink.attachTexture2D(gl, 0, true);
+        } else if( 0 == samplingSinkTexture.getName() ) {
+            samplingSinkTexture.setSize(width, height);
+            samplingSink.attachColorbuffer(gl, 0, samplingSinkTexture);
         }
         
         if( sampleSinkDepthStencilMismatch ) {
-            samplesSink.attachRenderbuffer(gl, depth.format);
+            samplingSink.attachRenderbuffer(gl, depth.format);
             if( null != stencil && !isDepthStencilPackedFormat() ) {
-                samplesSink.attachRenderbuffer(gl, stencil.format);
+                samplingSink.attachRenderbuffer(gl, stencil.format);
             }
         }        
         
@@ -2016,16 +2023,40 @@ public class FBObject {
         sampleSinkTexMismatch = sampleSinkTexMismatch();
         sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch();
         if(sampleSinkSizeMismatch || sampleSinkTexMismatch || sampleSinkDepthStencilMismatch) {
-            throw new InternalError("Samples sink mismatch after reset: \n\tTHIS "+this+",\n\t SINK "+samplesSink+
+            throw new InternalError("Samples sink mismatch after reset: \n\tTHIS "+this+",\n\t SINK "+samplingSink+
                                     "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
         }
         
         if(DEBUG) {
-            System.err.println("FBObject.resetSamplingSink: END\n\tTHIS "+this+",\n\tSINK "+samplesSink+
+            System.err.println("FBObject.resetSamplingSink: END\n\tTHIS "+this+",\n\tSINK "+samplingSink+
                                "\n\t size "+sampleSinkSizeMismatch +", tex "+sampleSinkTexMismatch +", depthStencil "+sampleSinkDepthStencilMismatch);
         }
     }
     
+    /**
+     * Setting this FBO sampling sink.
+     * @param newSamplingSink the new FBO sampling sink to use, or null to remove current sampling sink
+     * @return the previous sampling sink or null if none was attached 
+     * @throws GLException if this FBO doesn't use MSAA or the given sink uses MSAA itself
+     */
+    public FBObject setSamplingSink(FBObject newSamplingSink) throws GLException {
+        final FBObject prev = samplingSink; 
+        if( null == newSamplingSink) {
+            samplingSink = null;
+            samplingSinkTexture = null;
+        } else if( samples > 0 ) {
+            if( newSamplingSink.getNumSamples() > 0 ) {
+                throw new GLException("SamplingSink FBO cannot use MSAA itself: "+newSamplingSink);
+            }
+            samplingSink = newSamplingSink;
+            samplingSinkTexture = (TextureAttachment) newSamplingSink.getColorbuffer(0);
+        } else {
+            throw new GLException("Setting SamplingSink for non MSAA FBO not allowed: "+this);
+        }
+        samplingSinkDirty = true;
+        return prev;
+    }
+    
     /** 
      * Bind this FBO, i.e. bind write framebuffer to {@link #getWriteFramebuffer()}.
      * 
@@ -2052,7 +2083,7 @@ public class FBObject {
             }
 
             bound = true;
-            samplesSinkDirty = true;
+            samplingSinkDirty = true;
         }
     }
 
@@ -2131,12 +2162,12 @@ public class FBObject {
      */
     public final void syncSamplingSink(GL gl) {
         markUnbound();
-        if(samples>0 && samplesSinkDirty) {
-            samplesSinkDirty = false;
+        if(samples>0 && samplingSinkDirty) {
+            samplingSinkDirty = false;
             resetSamplingSink(gl);
             checkPreGLError(gl);
             gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbName);
-            gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplesSink.getWriteFramebuffer());
+            gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplingSink.getWriteFramebuffer());
             ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, casting to GL2GL3 is OK
                                            GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST);
             checkNoError(null, gl.glGetError(), "FBObject syncSampleSink"); // throws GLException if error            
@@ -2252,7 +2283,8 @@ public class FBObject {
     /** Returns the framebuffer name to render to. */
     public final int getWriteFramebuffer() { return fbName; }
     /** Returns the framebuffer name to read from. Depending on multisampling, this may be a different framebuffer. */
-    public final int getReadFramebuffer() { return ( samples > 0 ) ? samplesSink.getReadFramebuffer() : fbName; }
+    public final int getReadFramebuffer() { return ( samples > 0 ) ? samplingSink.getReadFramebuffer() : fbName; }    
+    public final int getDefaultReadBuffer() { return GL.GL_COLOR_ATTACHMENT0; }    
     /** Return the number of color/texture attachments */
     public final int getColorAttachmentCount() { return colorAttachmentCount; }
     /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */ 
@@ -2261,16 +2293,16 @@ public class FBObject {
     public final RenderAttachment getDepthAttachment() { return depth; }
     
     /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */ 
-    public final FBObject getSamplingSinkFBO() { return samplesSink; }
+    public final FBObject getSamplingSinkFBO() { return samplingSink; }
     
     /** Return the multisampling {@link TextureAttachment} sink, if using multisampling. */ 
-    public final TextureAttachment getSamplingSink() { return samplesSinkTexture; }
+    public final TextureAttachment getSamplingSink() { return samplingSinkTexture; }
     /** 
      * Returns <code>true</code> if the multisampling colorbuffer (msaa-buffer) 
      * has been flagged dirty by a previous call of {@link #bind(GL)},
      * otherwise <code>false</code>.
      */
-    public final boolean isSamplingBufferDirty() { return samplesSinkDirty; }
+    public final boolean isSamplingBufferDirty() { return samplingSinkDirty; }
     
     int objectHashCode() { return super.hashCode(); }
     
@@ -2279,7 +2311,7 @@ public class FBObject {
         return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+
                ", samples "+samples+"/"+maxSamples+", depth "+depth+", stencil "+stencil+
                ", color attachments: "+colorAttachmentCount+"/"+maxColorAttachments+
-               ": "+caps+", msaa-sink "+samplesSinkTexture+", isSamplesSink "+(null == samplesSink)+
+               ": "+caps+", msaa-sink "+samplingSinkTexture+", hasSamplesSink "+(null != samplingSink)+
                ", state "+getStatusString()+", obj "+toHexString(objectHashCode())+"]";
     }
     
diff --git a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
index 38a8dee..bec05a0 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
@@ -48,15 +48,15 @@ import jogamp.opengl.GLDrawableImpl;
 
 /**
  * Fully functional {@link GLAutoDrawable} implementation
- * utilizing already created created {@link GLDrawable} and {@link GLContext} instances.
+ * utilizing already created {@link GLDrawable} and {@link GLContext} instances.
  * <p>
  * Since no native windowing system events are being processed, it is recommended
- * to handle at least:
+ * to handle at least the {@link com.jogamp.newt.event.WindowEvent window events}:
  * <ul>
  *   <li>{@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint} using {@link #windowRepaintOp()}</li>
  *   <li>{@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize} using {@link #windowResizedOp()}</li>
- *   <li>{@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify}  using {@link #windowDestroyNotifyOp()}</li> 
- * </ul> 
+ * </ul>
+ * and setup a {@link com.jogamp.newt.Window#setWindowDestroyNotifyAction(Runnable) custom toolkit destruction} issuing {@link #windowDestroyNotifyOp()}.
  * </p>
  * <p> 
  * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}.
@@ -64,8 +64,11 @@ import jogamp.opengl.GLDrawableImpl;
  */
 public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAutoDrawable {
     /**
-     * @param drawable a valid and already realized {@link GLDrawable}
-     * @param context a valid {@link GLContext}, may not be made current (created) yet.
+     * @param drawable a valid {@link GLDrawable}, may not be {@link GLDrawable#isRealized() realized} yet.
+     * @param context a valid {@link GLContext}, 
+     *                may not have been made current (created) yet,
+     *                may not be associated w/ <code>drawable<code> yet,
+     *                may be <code>null</code> for lazy initialization
      * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
      * @param ownDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
      *                  otherwise pass <code>false</code>. Closing the device is required in case
@@ -78,12 +81,6 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAuto
         if(null == drawable) {
             throw new IllegalArgumentException("null drawable");
         }
-        if(null == context) {
-            throw new IllegalArgumentException("null context");
-        }        
-        if(!drawable.isRealized()) {
-            throw new IllegalArgumentException("drawable not realized");
-        }
         this.upstreamWidget = upstreamWidget;
         this.lock = ( null != lock ) ? lock : LockFactory.createRecursiveLock() ;
     }
@@ -173,10 +170,6 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAuto
     }
     
     @Override
-    public final void setRealized(boolean realized) {
-    }
-
-    @Override
     public final void swapBuffers() throws GLException {
          defaultSwapBuffers();
     }
diff --git a/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java b/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java
new file mode 100644
index 0000000..21dafec
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java
@@ -0,0 +1,435 @@
+/**
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.DefaultGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLRunnable;
+
+import jogamp.opengl.Debug;
+
+import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+
+/**
+ * GLEventListenerState is holding {@link GLAutoDrawable} components crucial 
+ * to relocating all its {@link GLEventListener} w/ their operating {@link GLContext}, etc.
+ * The components are:
+ * <ul>
+ *   <li>{@link GLContext}</li>
+ *   <li>All {@link GLEventListener}, incl. their init state</li>
+ *   <li>{@link GLAnimatorControl}</li>
+ *   <!--li>{@link GLCapabilitiesImmutable} for compatibility check</li-->
+ *   <li>{@link AbstractGraphicsDevice} for compatibility check and preserving the native device handle incl. ownership</li>
+ * </ul>
+ * <p>
+ * A GLEventListenerState instance can be created while components are {@link #moveFrom(GLAutoDrawable) moved from} a {@link GLAutoDrawable}
+ * to the new instance, which gains {@link #isOwner() ownership} of the moved components.
+ * </p>
+ * <p>
+ * A GLEventListenerState instance's components can be {@link #moveTo(GLAutoDrawable) moved to} a {@link GLAutoDrawable},
+ * while loosing {@link #isOwner() ownership} of the moved components.
+ * </p>
+ */
+public class GLEventListenerState {
+    private static final boolean DEBUG = Debug.debug("GLDrawable") || Debug.debug("GLEventListenerState");
+    
+    private GLEventListenerState(AbstractGraphicsDevice upstreamDevice, boolean proxyOwnsUpstreamDevice, AbstractGraphicsDevice device, 
+                                 GLCapabilitiesImmutable caps,
+                                 GLContext context, int count, GLAnimatorControl anim, boolean animStarted) {
+        this.upstreamDevice = upstreamDevice;
+        this.proxyOwnsUpstreamDevice = proxyOwnsUpstreamDevice;
+        this.device = device;
+        this.caps = caps;
+        this.context = context;
+        this.listeners = new GLEventListener[count];
+        this.listenersInit = new boolean[count];
+        this.anim = anim;
+        this.animStarted = animStarted;
+        
+        this.owner = true;
+    }
+    /**
+     * Returns <code>true</code>, if this instance is the current owner of the components, 
+     * otherwise <code>false</code>.
+     * <p>
+     * Ownership is lost if {@link #moveTo(GLAutoDrawable)} is being called successfully
+     * and all components are transferred to the new {@link GLAutoDrawable}. 
+     * </p>
+     */
+    public final boolean isOwner() { return owner; }
+    
+    public final int listenerCount() { return listeners.length; }
+
+    public final AbstractGraphicsDevice upstreamDevice;
+    public final boolean proxyOwnsUpstreamDevice;
+    public final AbstractGraphicsDevice device;
+    public final GLCapabilitiesImmutable caps;
+    public final GLContext context;
+    public final GLEventListener[] listeners;
+    public final boolean[] listenersInit;    
+    public final GLAnimatorControl anim;
+    public final boolean animStarted;
+    
+    private boolean owner;
+
+    /**
+     * Last resort to destroy and loose ownership
+     */
+    public void destroy() {
+        if( owner ) {
+            final int aSz = listenerCount();
+            for(int i=0; i<aSz; i++) {
+                listeners[i] = null;
+            }
+            // context.destroy(); - NPE (null drawable)
+            device.close();
+            owner = false;
+        }
+    }
+
+    private static AbstractGraphicsDevice cloneDevice(AbstractGraphicsDevice aDevice) {
+        return (AbstractGraphicsDevice) aDevice.clone();
+    }
+    
+    /**
+     * Moves all GLEventListenerState components from the given {@link GLAutoDrawable} 
+     * to a newly created instance.
+     * <p>
+     * Note that all components are removed from the {@link GLAutoDrawable},
+     * i.e. the {@link GLContext}, all {@link GLEventListener}.
+     * </p>
+     * <p> 
+     * If the {@link GLAutoDrawable} was added to a {@link GLAnimatorControl}, it is removed
+     * and the {@link GLAnimatorControl} added to the GLEventListenerState.
+     * </p>
+     * <p>
+     * The returned GLEventListenerState instance is the {@link #isOwner() owner of the components}. 
+     * </p>
+     * 
+     * @param a {@link GLAutoDrawable} source to move components from
+     * @return new GLEventListenerState instance {@link #isOwner() owning} moved components.
+     * 
+     * @see #moveTo(GLAutoDrawable)
+     */
+    public static GLEventListenerState moveFrom(GLAutoDrawable a) {
+        final GLAnimatorControl aAnim = a.getAnimator();
+        final boolean aAnimStarted;
+        if( null != aAnim ) {
+            aAnimStarted = aAnim.isStarted();
+            aAnim.remove(a); // also handles ECT
+        } else {        
+            aAnimStarted = false;
+        }
+        
+        final GLEventListenerState glls;
+        final NativeSurface aSurface = a.getNativeSurface();
+        final boolean surfaceLocked = false; // NativeSurface.LOCK_SURFACE_NOT_READY < aSurface.lockSurface();
+        try {
+            final int aSz = a.getGLEventListenerCount();
+    
+            // Create new AbstractGraphicsScreen w/ cloned AbstractGraphicsDevice for future GLAutoDrawable
+            // allowing this AbstractGraphicsDevice to loose ownership -> not closing display/device!
+            final AbstractGraphicsConfiguration aCfg = aSurface.getGraphicsConfiguration();
+            final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities();
+            final AbstractGraphicsDevice aDevice1 = aCfg.getScreen().getDevice();
+            final AbstractGraphicsDevice aDevice2 = cloneDevice(aDevice1);
+            aDevice1.clearHandleOwner();  // don't close device handle
+            if( DEBUG ) {            
+                System.err.println("GLEventListenerState.moveFrom.0a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1);
+                System.err.println("GLEventListenerState.moveFrom.0b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2);
+                System.err.println("GLEventListenerState.moveFrom.1: "+aSurface.getClass().getName()/*+", "+aSurface*/);
+            }
+            final AbstractGraphicsDevice aUpDevice2;
+            final boolean proxyOwnsUpstreamDevice;
+            {
+                AbstractGraphicsDevice _aUpDevice2 = null;
+                if(aSurface instanceof ProxySurface) {
+                    final ProxySurface aProxy = (ProxySurface)aSurface;
+                    proxyOwnsUpstreamDevice = aProxy.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+                    final NativeSurface aUpSurface = aProxy.getUpstreamSurface();
+                    if(DEBUG && null != aUpSurface) {
+                        System.err.println("GLEventListenerState.moveFrom.2: "+aUpSurface.getClass().getName()+", "+aUpSurface);
+                    }
+                    if(null != aUpSurface) {
+                        final AbstractGraphicsDevice aUpDevice1 = aUpSurface.getGraphicsConfiguration().getScreen().getDevice();
+                        _aUpDevice2 = cloneDevice(aUpDevice1);
+                        aUpDevice1.clearHandleOwner(); // don't close device handle
+                        if(DEBUG) {
+                            System.err.println("GLEventListenerState.moveFrom.3a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1);
+                            System.err.println("GLEventListenerState.moveFrom.3b: up-pres 0x"+Integer.toHexString(_aUpDevice2.hashCode())+", "+_aUpDevice2);
+                            System.err.println("GLEventListenerState.moveFrom.3c: "+aSurface.getClass().getName()+", "+aSurface);
+                            System.err.println("GLEventListenerState.moveFrom.3d: "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString());
+                        }
+                    }
+                } else {
+                    proxyOwnsUpstreamDevice = false;
+                }
+                aUpDevice2 = _aUpDevice2;
+            }
+            
+            glls = new GLEventListenerState(aUpDevice2, proxyOwnsUpstreamDevice, aDevice2, caps, a.getContext(), aSz, aAnim, aAnimStarted); 
+    
+            //
+            // remove and cache all GLEventListener and their init-state
+            //
+            for(int i=0; i<aSz; i++) {
+                final GLEventListener l = a.getGLEventListener(0);
+                glls.listenersInit[i] = a.getGLEventListenerInitState(l);
+                glls.listeners[i] = a.removeGLEventListener( l );
+            }    
+    
+            //
+            // trigger glFinish to sync GL ctx
+            //
+            a.invoke(true, glFinish);
+    
+            a.setContext( null, false );
+            
+        } finally {
+            if( surfaceLocked ) {
+                aSurface.unlockSurface();
+            }
+        }        
+        
+        return glls;
+    }
+
+    /**
+     * Moves all GLEventListenerState components to the given {@link GLAutoDrawable} 
+     * from this instance, while loosing {@link #isOwner() ownership}.
+     * <p> 
+     * If the previous {@link GLAutoDrawable} was removed from a {@link GLAnimatorControl} by previous {@link #moveFrom(GLAutoDrawable)},
+     * the given {@link GLAutoDrawable} is added to the cached {@link GLAnimatorControl}.
+     * This operation is skipped, if the given {@link GLAutoDrawable} is already added to a {@link GLAnimatorControl} instance.  
+     * </p>
+     * <p>
+     * Note: After this operation, the GLEventListenerState reference should be released. 
+     * </p>
+     * 
+     * @param a {@link GLAutoDrawable} destination to move GLEventListenerState components to
+     * 
+     * <!-- @throws GLException if the {@link GLAutoDrawable}'s configuration is incompatible, i.e. different {@link GLCapabilitiesImmutable}. -->
+     * @throws GLException if this preserved {@link AbstractGraphicsDevice} is incompatible w/ the given destination one.
+     * 
+     * @see #moveFrom(GLAutoDrawable)
+     * @see #isOwner()
+     */
+    public final void moveTo(GLAutoDrawable a) {
+        final GLAnimatorControl aAnim = a.getAnimator();
+        final boolean hasAnimator = null != aAnim;
+        final boolean aPaused;
+        if( hasAnimator ) {
+            aPaused = aAnim.pause();
+            aAnim.remove(a); // also handles ECT
+            if( aPaused ) {
+                aAnim.resume();
+            }
+        } else {        
+            aPaused = false;
+        }
+        
+        final List<GLRunnable> aGLCmds = new ArrayList<GLRunnable>();
+        final int aSz = listenerCount();
+        
+        final NativeSurface aSurface = a.getNativeSurface();
+        final boolean surfaceLocked = false; // NativeSurface.LOCK_SURFACE_NOT_READY < aSurface.lockSurface();
+        final boolean aRealized;
+        try {
+            
+            final MutableGraphicsConfiguration aCfg = (MutableGraphicsConfiguration) aSurface.getGraphicsConfiguration();
+            /**
+            final GLCapabilitiesImmutable aCaps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities();
+            if( caps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) != aCaps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) || 
+                caps.getVisualID(VisualIDHolder.VIDType.NATIVE) != aCaps.getVisualID(VisualIDHolder.VIDType.NATIVE) ) {
+                throw new GLException("Incompatible Capabilities - Prev-Holder: "+caps+", New-Holder "+caps);
+            } */
+            final DefaultGraphicsDevice aDevice1 = (DefaultGraphicsDevice) aCfg.getScreen().getDevice();
+            final DefaultGraphicsDevice aDevice2 = (DefaultGraphicsDevice) device;
+            if( !aDevice1.getUniqueID().equals( aDevice2.getUniqueID() ) ) {
+                throw new GLException("Incompatible devices: Preserved <"+aDevice2.getUniqueID()+">, target <"+aDevice1.getUniqueID()+">");
+            }
+            
+            // collect optional upstream surface info 
+            final ProxySurface aProxy;
+            final NativeSurface aUpSurface;
+            if(aSurface instanceof ProxySurface) {
+                aProxy = (ProxySurface)aSurface;
+                aUpSurface = aProxy.getUpstreamSurface();
+            } else {
+                aProxy = null;
+                aUpSurface = null;
+            }
+            if( DEBUG ) {
+                System.err.println("GLEventListenerState.moveTo.0 : has aProxy "+(null!=aProxy));
+                System.err.println("GLEventListenerState.moveTo.0 : has aUpSurface "+(null!=aUpSurface));
+            }
+            if( null==aUpSurface && null != upstreamDevice ) {
+                throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = true, New-Holder = false");
+            }            
+            
+            // Destroy and remove currently associated GLContext, if any (will be replaced)
+            a.setContext( null, true );
+            aRealized = a.isRealized();
+            if( aRealized && null != aUpSurface ) {
+                // Unrealize due to device dependencies of an upstream surface, e.g. EGLUpstreamSurfaceHook
+                a.getDelegatedDrawable().setRealized(false);
+            }
+            
+            // Set new Screen and close previous one
+            {
+                if( DEBUG ) {
+                    System.err.println("GLEventListenerState.moveTo.0a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1);
+                    System.err.println("GLEventListenerState.moveTo.0b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2);
+                }
+                DefaultGraphicsDevice.swapDeviceHandleAndOwnership(aDevice1, aDevice2);
+                aDevice2.close();                
+                if( DEBUG ) {
+                    System.err.println("GLEventListenerState.moveTo.1a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1);
+                    System.err.println("GLEventListenerState.moveTo.1b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2);
+                }
+            }
+            
+            // If using a ProxySurface w/ an upstream surface, set new Screen and close previous one on it
+            if( null != aUpSurface ) {
+                final MutableGraphicsConfiguration aUpCfg = (MutableGraphicsConfiguration) aUpSurface.getGraphicsConfiguration();
+                if( null != upstreamDevice ) {
+                    final DefaultGraphicsDevice aUpDevice1 = (DefaultGraphicsDevice) aUpCfg.getScreen().getDevice();
+                    final DefaultGraphicsDevice aUpDevice2 = (DefaultGraphicsDevice)upstreamDevice;
+                    if( !aUpDevice1.getUniqueID().equals( aUpDevice2.getUniqueID() ) ) {
+                        throw new GLException("Incompatible updtream devices: Preserved <"+aUpDevice2.getUniqueID()+">, target <"+aUpDevice1.getUniqueID()+">");
+                    }
+                    if( DEBUG ) {
+                        System.err.println("GLEventListenerState.moveTo.2a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1);
+                        System.err.println("GLEventListenerState.moveTo.2b: up-pres 0x"+Integer.toHexString(aUpDevice2.hashCode())+", "+aUpDevice2);
+                        System.err.println("GLEventListenerState.moveTo.2c:  "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString());
+                    }                            
+                    DefaultGraphicsDevice.swapDeviceHandleAndOwnership(aUpDevice1, aUpDevice2);
+                    aUpDevice2.close();                            
+                    if( proxyOwnsUpstreamDevice ) {
+                        aProxy.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+                    }
+                    if( DEBUG ) {
+                        System.err.println("GLEventListenerState.moveTo.3a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1);
+                        System.err.println("GLEventListenerState.moveTo.3b: up-pres 0x"+Integer.toHexString(aUpDevice2.hashCode())+", "+aUpDevice2);
+                        System.err.println("GLEventListenerState.moveTo.3c:  "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString());
+                    }
+                } else {
+                    throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = false, New-Holder = true");
+                }
+            }
+            
+            if( aRealized && null != aUpSurface ) {
+                a.getDelegatedDrawable().setRealized(true);
+            }
+            if( DEBUG ) {
+                System.err.println("GLEventListenerState.moveTo.X : has aProxy "+(null!=aProxy));
+                System.err.println("GLEventListenerState.moveTo.X : has aUpSurface "+(null!=aUpSurface));
+            }
+            a.setContext( context, false );
+        } finally {
+            if( surfaceLocked ) {
+                aSurface.unlockSurface();
+            }
+        }
+        owner = false;
+        
+        //
+        // Trigger GL-Viewport reset and reshape of all initialized GLEventListeners
+        //
+        aGLCmds.add(setViewport);
+        for(int i=0; i<aSz; i++) {
+            if( listenersInit[i] ) {
+                aGLCmds.add(new ReshapeGLEventListener( listeners[i] ) );
+            }
+        }
+        aGLCmds.add(glFinish);
+        a.invoke(aRealized, aGLCmds); // only wait if already realized
+
+        // add all cached GLEventListener to their destination and fix their init-state
+        for(int i=0; i<aSz; i++) {
+            final GLEventListener l = listeners[i];
+            a.addGLEventListener( l );
+            a.setGLEventListenerInitState(l, listenersInit[i]);
+            listeners[i] = null;
+        }
+        
+        if( hasAnimator ) {
+            // prefer already bound animator
+            aAnim.add(a);
+            if( aPaused ) {
+                aAnim.resume();
+            }
+        } else if ( null != anim ) {
+            // use previously bound animator
+            anim.add(a); // also handles ECT
+            if(animStarted) {
+                anim.start();
+            }
+        }
+    }
+
+    public static GLRunnable setViewport = new GLRunnable() {
+        @Override
+        public boolean run(GLAutoDrawable drawable) {
+            drawable.getGL().glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
+            return true;
+        }            
+    };
+
+    public static GLRunnable glFinish = new GLRunnable() {
+        @Override
+        public boolean run(GLAutoDrawable drawable) {
+            drawable.getGL().glFinish();
+            return true;
+        }            
+    };
+
+    public static class ReshapeGLEventListener implements GLRunnable {
+        private GLEventListener listener;
+        public ReshapeGLEventListener(GLEventListener listener) {
+            this.listener = listener;
+        }
+        @Override
+        public boolean run(GLAutoDrawable drawable) {
+            listener.reshape(drawable, 0, 0, drawable.getWidth(), drawable.getHeight());
+            return true;
+        }      
+    }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
index cf81b85..c0666d1 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
@@ -73,8 +73,9 @@ public class GLExtensions {
   public static final String OES_EGL_image_external          = "GL_OES_EGL_image_external";
   
   public static final String ARB_gpu_shader_fp64             = "GL_ARB_gpu_shader_fp64";
-  public static final String ARB_shader_objects              = "GL_ARB_shader_objects";
-   
+  public static final String ARB_shader_objects              = "GL_ARB_shader_objects"; 
+  public static final String ARB_geometry_shader4            = "GL_ARB_geometry_shader4";
+  
   //
   // Aliased GLX/WGL/.. extensions
   //
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
index 2f453a4..9fe74ee 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -27,6 +27,8 @@
  */
 package com.jogamp.opengl;
 
+import java.util.List;
+
 /** 
  * GLRendererQuirks contains information of known bugs of various GL renderer. 
  * This information allows us to workaround them.
@@ -34,10 +36,14 @@ package com.jogamp.opengl;
  * Using centralized quirk identifier enables us to
  * locate code dealing w/ it and hence eases it's maintenance.   
  * </p>
+ * <p>
+ * <i>Some</i> <code>GL_VENDOR</code> and <code>GL_RENDERER</code> strings are
+ * listed here <http://feedback.wildfiregames.com/report/opengl/feature/GL_VENDOR>. 
+ * </p>
  */
 public class GLRendererQuirks {
     /** 
-     * Crashes XServer when using double buffered PBuffer with:
+     * Crashes XServer when using double buffered PBuffer with GL_RENDERER:
      * <ul>
      *  <li>Mesa DRI Intel(R) Sandybridge Desktop</li>
      *  <li>Mesa DRI Intel(R) Ivybridge Mobile - 3.0 Mesa 8.0.4</li>
@@ -59,14 +65,130 @@ public class GLRendererQuirks {
     /** SIGSEGV on setSwapInterval() after changing the context's drawable w/ 'Mesa 8.0.4' dri2SetSwapInterval/DRI2 (soft & intel) */
     public static final int NoSetSwapIntervalPostRetarget = 4;
 
-    /** GLSL <code>discard</code> command leads to undefined behavior or won't get compiled if being used. Appears to happen on Nvidia Tegra2. FIXME: Constrain version. */
+    /** GLSL <code>discard</code> command leads to undefined behavior or won't get compiled if being used. Appears to <i>have</i> happened on Nvidia Tegra2, but seems to be fine now. FIXME: Constrain version. */
     public static final int GLSLBuggyDiscard = 5;
     
+    /** 
+     * Non compliant GL context due to a buggy implementation not suitable for use.
+     * <p>
+     * Mesa >= 9.0 (?), Intel driver, OpenGL 3.1 compatibility context is not compliant: 
+     * <pre>
+     * GL_RENDERER: 'Mesa .* Intel(R) Sandybridge Desktop' 
+     * </pre>
+     * </p>
+     * <p>
+     * Mesa >= 9.0 (?), AMD driver, OpenGL 3.1 core and compatibility context is not compliant: 
+     * <pre>
+     * GL_RENDERER: 'Gallium 0.4 on AMD RS880'
+     * </pre>
+     * </p>
+     */
+    public static final int GLNonCompliant = 6;
+    
+    /**
+     * The OpenGL Context needs a <code>glFlush()</code> before releasing it, otherwise driver may freeze:
+     * <ul>
+     *   <li>OSX < 10.7.3 - NVidia Driver. Bug 533 and Bug 548 @ https://jogamp.org/bugzilla/.</li>
+     * </ul>  
+     */
+    public static final int GLFlushBeforeRelease = 7;
+    
+    /** 
+     * Closing X11 displays may cause JVM crashes or X11 errors with some buggy drivers
+     * while being used in concert w/ OpenGL.
+     * <p>
+     * Some drivers may require X11 displays to be closed in the same order as they were created,
+     * some may not allow them to be closed at all while resources are being used somehow.
+     * </p>
+     * <p>
+     * Drivers known exposing such bug:
+     * <ul>
+     *   <li>Mesa < 8.0 _with_ X11 software renderer <code>Mesa X11</code>, not with GLX/DRI renderer.</li>
+     *   <li>ATI proprietary Catalyst X11 driver versions:
+     *     <ul>
+     *       <li>8.78.6</li>
+     *       <li>8.881</li>
+     *       <li>8.911</li>
+     *       <li>9.01.8</li>
+     *     </ul></li>
+     * </ul>
+     * </p>
+     * <p>
+     * See Bug 515 - https://jogamp.org/bugzilla/show_bug.cgi?id=515
+     * and {@link jogamp.nativewindow.x11.X11Util#ATI_HAS_XCLOSEDISPLAY_BUG}.
+     * </p>
+     * <p>
+     * See Bug 705 - https://jogamp.org/bugzilla/show_bug.cgi?id=705
+     * </p>
+     */
+    public static final int DontCloseX11Display = 8;
+    
+    /**
+     * Need current GL Context when calling new ARB <i>pixel format query</i> functions, 
+     * otherwise driver crashes the VM.
+     * <p>
+     * Drivers known exposing such bug:
+     * <ul>
+     *   <li>ATI proprietary Catalyst driver on Windows version ≤ XP. 
+     *       TODO: Validate if bug actually relates to 'old' ATI Windows drivers for old GPU's like X300
+     *             regardless of the Windows version.</li>
+     * </ul>
+     * <p>
+     * See Bug 480 - https://jogamp.org/bugzilla/show_bug.cgi?id=480
+     * </p>
+     */
+    public static final int NeedCurrCtx4ARBPixFmtQueries = 9;
+    
+    /**
+     * Need current GL Context when calling new ARB <i>CreateContext</i> function,
+     * otherwise driver crashes the VM.
+     * <p>
+     * Drivers known exposing such bug:
+     * <ul>
+     *   <li>ATI proprietary Catalyst Windows driver on laptops with a driver version as reported in <i>GL_VERSION</i>:
+     *     <ul>
+     *       <li> <i>null</i> </li>
+     *       <li> < <code>12.102.3.0</code> ( <i>amd_catalyst_13.5_mobility_beta2</i> ) </li>
+     *     </ul></li>
+     * </ul>
+     * </p>
+     * <p>
+     * See Bug 706 - https://jogamp.org/bugzilla/show_bug.cgi?id=706<br/>
+     * See Bug 520 - https://jogamp.org/bugzilla/show_bug.cgi?id=520
+     * </p>
+     */
+    public static final int NeedCurrCtx4ARBCreateContext = 10;
+    
+    /**
+     * No full FBO support, i.e. not compliant w/
+     * <ul> 
+     *   <li>GL_ARB_framebuffer_object</li>
+     *   <li>EXT_framebuffer_object</li> 
+     *   <li>EXT_framebuffer_multisample</li> 
+     *   <li>EXT_framebuffer_blit</li> 
+     *   <li>EXT_packed_depth_stencil</li>
+     * </ul>.
+     * Drivers known exposing such bug:
+     * <ul>
+     *   <li>Mesa <i>7.12-devel</i> on Windows with VMware <i>SVGA3D</i> renderer:
+     *     <ul>
+     *       <li>GL_VERSION:  <i>2.1 Mesa 7.12-devel (git-d6c318e)</i> </li>
+     *       <li>GL_RENDERER: <i>Gallium 0.4 on SVGA3D; build: RELEASE;</i> </li>
+     *     </ul></li>
+     * </ul>
+     * Quirk can also be enabled via property: <code>jogl.fbo.force.min</code>.
+     */
+    public static final int NoFullFBOSupport = 11;
+    
+    
     /** Number of quirks known. */
-    public static final int COUNT = 6;
+    public static final int COUNT = 12;
     
     private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
-                                                          "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard"
+                                                          "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard",
+                                                          "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11Display",
+                                                          "NeedCurrCtx4ARBPixFmtQueries", "NeedCurrCtx4ARBCreateContext",
+                                                          "NoFullFBOSupport"
                                                         };
 
     private final int _bitmask;
@@ -91,6 +213,20 @@ public class GLRendererQuirks {
     }      
 
     /**
+     * @param quirks a list of valid quirks
+     * @throws IllegalArgumentException if one of the quirks is out of range
+     */
+    public GLRendererQuirks(List<Integer> quirks) throws IllegalArgumentException {
+        int bitmask = 0;
+        for(int i=0; i<quirks.size(); i++) {
+            final int quirk = quirks.get(i);
+            validateQuirk(quirk);
+            bitmask |= 1 << quirk;
+        }
+        _bitmask = bitmask;
+    }
+    
+    /**
      * @param quirk the quirk to be tested
      * @return true if quirk exist, otherwise false
      * @throws IllegalArgumentException if quirk is out of range
diff --git a/src/jogl/classes/com/jogamp/opengl/GLStateKeeper.java b/src/jogl/classes/com/jogamp/opengl/GLStateKeeper.java
new file mode 100644
index 0000000..321d4ee
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLStateKeeper.java
@@ -0,0 +1,100 @@
+/**
+ * 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;
+
+/**
+ * Interface adding a {@link GLEventListenerState} protocol to {@link GLAutoDrawable}s
+ * or other self-contained compound types combining {@link GLDrawable}, {@link GLContext} and {@link GLEventListener}.
+ * <p>
+ * Implementing classes {@link #isGLStatePreservationSupported() may support} preservation 
+ * of the {@link GLContext} state and it's associated {@link GLEventListener}. 
+ * </p> 
+ */
+public interface GLStateKeeper {
+    
+    /** Listener for preserve and restore notifications. */
+    public static interface Listener {
+        /** Invoked before preservation. */
+        void glStatePreserveNotify(GLStateKeeper glsk);
+        /** Invoked after restoration. */
+        void glStateRestored(GLStateKeeper glsk);
+    }
+    
+    /** 
+     * Sets a {@link Listener}, overriding the old one.
+     * @param l the new {@link Listener}.
+     * @return the previous {@link Listener}.
+     */
+    public Listener setGLStateKeeperListener(Listener l);
+    
+    /**
+     * @return <code>true</code> if GL state preservation is supported in implementation and on current platform, <code>false</code> otherwise.
+     * @see #preserveGLStateAtDestroy(boolean)
+     * @see #getPreservedGLState()
+     * @see #clearPreservedGLState()
+     */
+    public boolean isGLStatePreservationSupported();
+    
+    /**
+     * If set to <code>true</code>, the next {@link GLAutoDrawable#destroy()} operation will
+     * {@link #pullGLEventListenerState() pull} to preserve the {@link GLEventListenerState}.
+     * <p>
+     * This is a one-shot flag, i.e. after preserving the {@link GLEventListenerState},
+     * the flag is cleared.
+     * </p>
+     * <p>
+     * A preserved {@link GLEventListenerState} will be {@link #pushGLEventListenerState() pushed} 
+     * if realized again. 
+     * </p>
+     * @return <code>true</code> if supported and successful, <code>false</code> otherwise.
+     * @see #isGLStatePreservationSupported()
+     * @see #getPreservedGLState()
+     * @see #clearPreservedGLState()
+     */
+    public boolean preserveGLStateAtDestroy(boolean value);
+    
+    /**
+     * Returns the preserved {@link GLEventListenerState} if preservation was performed,
+     * otherwise <code>null</code>. 
+     * @see #isGLStatePreservationSupported()
+     * @see #preserveGLStateAtDestroy(boolean)
+     * @see #clearPreservedGLState()
+     */
+    public GLEventListenerState getPreservedGLState();
+    
+    /**
+     * Clears the preserved {@link GLEventListenerState} from this {@link GLStateKeeper}, without destroying it.
+     *  
+     * @return the preserved and cleared {@link GLEventListenerState} if preservation was performed,
+     *         otherwise <code>null</code>. 
+     * @see #isGLStatePreservationSupported()
+     * @see #preserveGLStateAtDestroy(boolean)
+     * @see #getPreservedGLState()
+     */
+    public GLEventListenerState clearPreservedGLState();
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index 52721e3..6cd02b7 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -93,6 +93,21 @@ public class JoglVersion extends JogampVersion {
         return sb;        
     }
     
+    public static StringBuilder getAllAvailableCapabilitiesInfo(AbstractGraphicsDevice device, StringBuilder sb) {
+        if(null==sb) {
+            sb = new StringBuilder();
+        }
+        if(null == device) {
+            device = GLProfile.getDefaultDevice();
+        }        
+        sb.append(Platform.getNewline()).append(Platform.getNewline());
+        sb.append("Desktop Capabilities: ").append(Platform.getNewline());
+        getAvailableCapabilitiesInfo(GLDrawableFactory.getDesktopFactory(), device, sb);
+        sb.append("EGL Capabilities: ").append(Platform.getNewline());
+        getAvailableCapabilitiesInfo(GLDrawableFactory.getEGLFactory(), device, sb);
+        return sb;
+    }
+    
     public static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, boolean withCapabilitiesInfo) {
         if(null==sb) {
             sb = new StringBuilder();
@@ -107,16 +122,15 @@ public class JoglVersion extends JogampVersion {
             sb.append("none");
         }
         if(withCapabilitiesInfo) {
-            sb.append(Platform.getNewline()).append(Platform.getNewline());
-            sb.append("Desktop Capabilities: ").append(Platform.getNewline());
-            getAvailableCapabilitiesInfo(GLDrawableFactory.getDesktopFactory(), device, sb);
-            sb.append("EGL Capabilities: ").append(Platform.getNewline());
-            getAvailableCapabilitiesInfo(GLDrawableFactory.getEGLFactory(), device, sb);
+            sb = getAllAvailableCapabilitiesInfo(device, sb);
         }
         return sb;
     }
     
     public static StringBuilder getGLInfo(GL gl, StringBuilder sb) {
+        return getGLInfo(gl, sb, false);
+    }
+    public static StringBuilder getGLInfo(GL gl, StringBuilder sb, boolean withCapabilitiesInfo) {
         AbstractGraphicsDevice device = gl.getContext().getGLDrawable().getNativeSurface()
                                             .getGraphicsConfiguration().getScreen().getDevice();
         if(null==sb) {
@@ -129,7 +143,12 @@ public class JoglVersion extends JogampVersion {
         GLProfile.glAvailabilityToString(device, sb, "\t", 1);        
         sb.append(Platform.getNewline());
 
-        return getGLStrings(gl, sb);
+        sb = getGLStrings(gl, sb);
+        
+        if( withCapabilitiesInfo ) {
+            sb = getAllAvailableCapabilitiesInfo(device, sb);            
+        }
+        return sb;
     }
     
     public static StringBuilder getGLStrings(GL gl, StringBuilder sb) {        
@@ -141,9 +160,11 @@ public class JoglVersion extends JogampVersion {
         sb.append(Platform.getNewline());
         sb.append("GL Profile     ").append(gl.getGLProfile());
         sb.append(Platform.getNewline());
-        sb.append("CTX VERSION    ").append(gl.getContext().getGLVersion());
+        sb.append("GL Version     ").append(ctx.getGLVersion()).append(" [GL ").append(ctx.getGLVersionNumber()).append(", vendor ").append(ctx.getGLVendorVersionNumber()).append("]");
+        sb.append(Platform.getNewline());
+        sb.append("Quirks         ").append(ctx.getRendererQuirks());
         sb.append(Platform.getNewline());
-        sb.append("GL             ").append(gl);
+        sb.append("Impl. class    ").append(gl.getClass().getCanonicalName());
         sb.append(Platform.getNewline());
         sb.append("GL_VENDOR      ").append(gl.glGetString(GL.GL_VENDOR));
         sb.append(Platform.getNewline());
@@ -151,9 +172,9 @@ public class JoglVersion extends JogampVersion {
         sb.append(Platform.getNewline());
         sb.append("GL_VERSION     ").append(gl.glGetString(GL.GL_VERSION));
         sb.append(Platform.getNewline());        
-        sb.append("GLSL           ").append(gl.hasGLSL()).append(", has-compiler: ").append(gl.isFunctionAvailable("glCompileShader"));
+        sb.append("GLSL           ").append(gl.hasGLSL()).append(", has-compiler-func: ").append(gl.isFunctionAvailable("glCompileShader"));
         if(gl.hasGLSL()) {
-            sb.append(", version: ").append(gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION));
+            sb.append(", version: ").append(gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION)).append(" / ").append(ctx.getGLSLVersionNumber());
         }
         sb.append(Platform.getNewline());
         sb.append("GL_EXTENSIONS  ").append(ctx.getGLExtensionCount());
diff --git a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java
index d160ecc..ca48469 100644
--- a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java
@@ -39,8 +39,8 @@ import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.*;
 
-public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
-    private static List<String> glueLibNames;
+public final class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
+    private static final List<String> glueLibNames;
     static {
         AccessController.doPrivileged(new PrivilegedAction<Object>() {
             public Object run() {
@@ -69,11 +69,16 @@ public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
 
     /** Make Cg symbols available to CgGL */
     @Override
-    public boolean shallLinkGlobal() { return true; }
+    public final boolean shallLinkGlobal() { return true; }
 
-    /** default **/
+    /**
+     * {@inheritDoc}
+     * <p>
+     * Returns <code>false</code>.
+     * </p>
+     */ 
     @Override
-    public boolean shallLookupGlobal() { return false; }
+    public final boolean shallLookupGlobal() { return false; }
 
     /** Tool has none **/
     @Override
@@ -88,12 +93,12 @@ public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
     }
     
     @Override
-    public boolean useToolGetProcAdressFirst(String funcName) {
+    public final boolean useToolGetProcAdressFirst(String funcName) {
         return false;
     }
 
     @Override
-    public List<List<String>> getToolLibNames() {
+    public final List<List<String>> getToolLibNames() {
         final List<List<String>> libsList = new ArrayList<List<String>>();
         final List<String> libsCg = new ArrayList<String>();
         libsCg.add("Cg");
@@ -112,7 +117,7 @@ public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
     }
 
     @Override
-    public RunnableExecutor getLibLoaderExecutor() {
+    public final RunnableExecutor getLibLoaderExecutor() {
         return DynamicLibraryBundle.getDefaultRunnableExecutor();
     }    
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FixedPoint.java b/src/jogl/classes/com/jogamp/opengl/math/FixedPoint.java
similarity index 98%
rename from src/jogl/classes/com/jogamp/opengl/util/FixedPoint.java
rename to src/jogl/classes/com/jogamp/opengl/math/FixedPoint.java
index 6412db5..e0acfec 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/FixedPoint.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/FixedPoint.java
@@ -31,7 +31,7 @@
  * 
  */
 
-package com.jogamp.opengl.util;
+package com.jogamp.opengl.math;
 
 public class FixedPoint {
   public static final int toFixed(int value) {
diff --git a/src/jogl/classes/com/jogamp/opengl/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
similarity index 66%
rename from src/jogl/classes/com/jogamp/opengl/FloatUtil.java
rename to src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
index ffd2344..f3f44f1 100644
--- a/src/jogl/classes/com/jogamp/opengl/FloatUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
@@ -25,7 +25,7 @@
  * authors and should not be interpreted as representing official policies, either expressed
  * or implied, of JogAmp Community.
  */
-package com.jogamp.opengl;
+package com.jogamp.opengl.math;
 
 import java.nio.FloatBuffer;
 
@@ -113,6 +113,22 @@ public class FloatUtil {
   }
   
   /**
+   * @param a 4x4 matrix in column-major order (also result)
+   * @param b 4x4 matrix in column-major order
+   */
+  public static final void multMatrixf(final float[] a, int a_off, final float[] b, int b_off) {
+     for (int i = 0; i < 4; i++) {
+        // one row in column-major order
+        final int a_off_i = a_off+i;
+        final float ai0=a[a_off_i+0*4],  ai1=a[a_off_i+1*4],  ai2=a[a_off_i+2*4],  ai3=a[a_off_i+3*4]; // row-i of a
+        a[a_off_i+0*4] = ai0 * b[b_off+0+0*4] + ai1 * b[b_off+1+0*4] + ai2 * b[b_off+2+0*4] + ai3 * b[b_off+3+0*4] ;
+        a[a_off_i+1*4] = ai0 * b[b_off+0+1*4] + ai1 * b[b_off+1+1*4] + ai2 * b[b_off+2+1*4] + ai3 * b[b_off+3+1*4] ;
+        a[a_off_i+2*4] = ai0 * b[b_off+0+2*4] + ai1 * b[b_off+1+2*4] + ai2 * b[b_off+2+2*4] + ai3 * b[b_off+3+2*4] ;
+        a[a_off_i+3*4] = ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] ;
+     }
+  }
+  
+  /**
    * @param a 4x4 matrix in column-major order
    * @param b 4x4 matrix in column-major order
    * @param d result a*b in column-major order
@@ -146,6 +162,23 @@ public class FloatUtil {
         d.put(dP+i+3*4 , ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] );
      }
   }
+  
+  /**
+   * @param a 4x4 matrix in column-major order (also result)
+   * @param b 4x4 matrix in column-major order
+   */
+  public static final void multMatrixf(final FloatBuffer a, final float[] b, int b_off) {
+     final int aP = a.position(); 
+     for (int i = 0; i < 4; i++) {
+        // one row in column-major order
+        final int aP_i = aP+i;
+        final float ai0=a.get(aP_i+0*4),  ai1=a.get(aP_i+1*4),  ai2=a.get(aP_i+2*4),  ai3=a.get(aP_i+3*4); // row-i of a
+        a.put(aP_i+0*4 , ai0 * b[b_off+0+0*4] + ai1 * b[b_off+1+0*4] + ai2 * b[b_off+2+0*4] + ai3 * b[b_off+3+0*4] );
+        a.put(aP_i+1*4 , ai0 * b[b_off+0+1*4] + ai1 * b[b_off+1+1*4] + ai2 * b[b_off+2+1*4] + ai3 * b[b_off+3+1*4] );
+        a.put(aP_i+2*4 , ai0 * b[b_off+0+2*4] + ai1 * b[b_off+1+2*4] + ai2 * b[b_off+2+2*4] + ai3 * b[b_off+3+2*4] );
+        a.put(aP_i+3*4 , ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] );
+     }
+  }
 
   /**
    * @param a 4x4 matrix in column-major order
@@ -166,6 +199,41 @@ public class FloatUtil {
      }
   }
   
+  /**
+   * @param a 4x4 matrix in column-major order (also result)
+   * @param b 4x4 matrix in column-major order
+   */
+  public static final void multMatrixf(final FloatBuffer a, final FloatBuffer b) {
+     final int aP = a.position(); 
+     final int bP = b.position();
+     for (int i = 0; i < 4; i++) {
+        // one row in column-major order
+        final int aP_i = aP+i;
+        final float ai0=a.get(aP_i+0*4),  ai1=a.get(aP_i+1*4),  ai2=a.get(aP_i+2*4),  ai3=a.get(aP_i+3*4); // row-i of a
+        a.put(aP_i+0*4 , ai0 * b.get(bP+0+0*4) + ai1 * b.get(bP+1+0*4) + ai2 * b.get(bP+2+0*4) + ai3 * b.get(bP+3+0*4) );
+        a.put(aP_i+1*4 , ai0 * b.get(bP+0+1*4) + ai1 * b.get(bP+1+1*4) + ai2 * b.get(bP+2+1*4) + ai3 * b.get(bP+3+1*4) );
+        a.put(aP_i+2*4 , ai0 * b.get(bP+0+2*4) + ai1 * b.get(bP+1+2*4) + ai2 * b.get(bP+2+2*4) + ai3 * b.get(bP+3+2*4) );
+        a.put(aP_i+3*4 , ai0 * b.get(bP+0+3*4) + ai1 * b.get(bP+1+3*4) + ai2 * b.get(bP+2+3*4) + ai3 * b.get(bP+3+3*4) );
+     }
+  }
+  
+  /**
+   * @param a 4x4 matrix in column-major order
+   * @param b 4x4 matrix in column-major order
+   * @param d result a*b in column-major order
+   */
+  public static final void multMatrixf(final FloatBuffer a, final FloatBuffer b, float[] d, int d_off) {
+     final int aP = a.position(); 
+     final int bP = b.position();
+     for (int i = 0; i < 4; i++) {
+        // one row in column-major order
+        final float ai0=a.get(aP+i+0*4),  ai1=a.get(aP+i+1*4),  ai2=a.get(aP+i+2*4),  ai3=a.get(aP+i+3*4); // row-i of a
+        d[d_off+i+0*4] = ai0 * b.get(bP+0+0*4) + ai1 * b.get(bP+1+0*4) + ai2 * b.get(bP+2+0*4) + ai3 * b.get(bP+3+0*4) ;
+        d[d_off+i+1*4] = ai0 * b.get(bP+0+1*4) + ai1 * b.get(bP+1+1*4) + ai2 * b.get(bP+2+1*4) + ai3 * b.get(bP+3+1*4) ;
+        d[d_off+i+2*4] = ai0 * b.get(bP+0+2*4) + ai1 * b.get(bP+1+2*4) + ai2 * b.get(bP+2+2*4) + ai3 * b.get(bP+3+2*4) ;
+        d[d_off+i+3*4] = ai0 * b.get(bP+0+3*4) + ai1 * b.get(bP+1+3*4) + ai2 * b.get(bP+2+3*4) + ai3 * b.get(bP+3+3*4) ;
+     }
+  }
   
   /**
    * Normalize vector
@@ -357,6 +425,33 @@ public class FloatUtil {
 
   /** 
    * @param sb optional passed StringBuilder instance to be used
+   * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+   * @param a mxn matrix (rows x columns)
+   * @param aOffset offset to <code>a</code>'s current position
+   * @param rows
+   * @param columns
+   * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
+   * @param row row number to print 
+   * @return matrix row string representation
+   */
+  public static StringBuilder matrixRowToString(StringBuilder sb, String f, float[] a, int aOffset, int rows, int columns, boolean rowMajorOrder, int row) {
+      if(null == sb) {
+          sb = new StringBuilder();
+      }
+      if(rowMajorOrder) {
+          for(int c=0; c<columns; c++) {
+              sb.append( String.format( f+" ", a[ aOffset + row*columns + c ] ) ); 
+          }
+      } else {
+          for(int r=0; r<columns; r++) {
+              sb.append( String.format( f+" ", a[ aOffset + row + r*rows ] ) ); 
+          }
+      }
+      return sb;
+  }
+  
+  /** 
+   * @param sb optional passed StringBuilder instance to be used
    * @param rowPrefix optional prefix for each row 
    * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
    * @param a mxn matrix (rows x columns)
@@ -383,6 +478,30 @@ public class FloatUtil {
    * @param sb optional passed StringBuilder instance to be used
    * @param rowPrefix optional prefix for each row 
    * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+   * @param a mxn matrix (rows x columns)
+   * @param aOffset offset to <code>a</code>'s current position
+   * @param rows
+   * @param columns
+   * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
+   * @return matrix string representation
+   */
+  public static StringBuilder matrixToString(StringBuilder sb, String rowPrefix, String f, float[] a, int aOffset, int rows, int columns, boolean rowMajorOrder) {
+      if(null == sb) {
+          sb = new StringBuilder();
+      }
+      final String prefix = ( null == rowPrefix ) ? "" : rowPrefix;
+      for(int i=0; i<rows; i++) {
+          sb.append(prefix).append("[ ");
+          matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i);
+          sb.append("]").append(Platform.getNewline());      
+      }
+      return sb;
+  }
+  
+  /** 
+   * @param sb optional passed StringBuilder instance to be used
+   * @param rowPrefix optional prefix for each row 
+   * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
    * @param a 4x4 matrix in column major order (OpenGL)
    * @param aOffset offset to <code>a</code>'s current position
    * @param b 4x4 matrix in column major order (OpenGL)
@@ -406,5 +525,49 @@ public class FloatUtil {
       }
       return sb;
   }
+
+  /** 
+   * @param sb optional passed StringBuilder instance to be used
+   * @param rowPrefix optional prefix for each row 
+   * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
+   * @param a 4x4 matrix in column major order (OpenGL)
+   * @param aOffset offset to <code>a</code>'s current position
+   * @param b 4x4 matrix in column major order (OpenGL)
+   * @param bOffset offset to <code>a</code>'s current position
+   * @param rows
+   * @param columns
+   * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
+   * @return side by side representation
+   */
+  public static StringBuilder matrixToString(StringBuilder sb, String rowPrefix, String f, float[] a, int aOffset, float[] b, int bOffset, int rows, int columns, boolean rowMajorOrder) {
+      if(null == sb) {
+          sb = new StringBuilder();
+      }
+      final String prefix = ( null == rowPrefix ) ? "" : rowPrefix;
+      for(int i=0; i<rows; i++) {
+          sb.append(prefix).append("[ ");
+          matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i);
+          sb.append("=?= ");
+          matrixRowToString(sb, f, b, bOffset, rows, columns, rowMajorOrder, i);
+          sb.append("]").append(Platform.getNewline());      
+      }
+      return sb;
+  }
+  
+  public static final float E = 2.7182818284590452354f;
+
+  public static final float PI = 3.14159265358979323846f;
+
+  public static float abs(float a) { return (float) java.lang.Math.abs(a);  }
+
+  public static float pow(float a, float b) { return (float) java.lang.Math.pow(a, b);  }
+
+  public static float sin(float a) { return (float) java.lang.Math.sin(a);  }
+
+  public static float cos(float a) { return (float) java.lang.Math.cos(a);  }
+
+  public static float acos(float a) { return (float) java.lang.Math.acos(a);  }
+
+  public static float sqrt(float a) { return (float) java.lang.Math.sqrt(a);  }
   
 }
\ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
new file mode 100644
index 0000000..d5ffe2d
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
@@ -0,0 +1,426 @@
+/**
+ * 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.math;
+
+public class Quaternion {
+    protected float x, y, z, w;
+
+    public Quaternion() {
+        setIdentity();
+    }
+    
+    public Quaternion(Quaternion q) {
+        x = q.x;
+        y = q.y;
+        z = q.z;
+        w = q.w;
+    }
+
+    public Quaternion(float x, float y, float z, float w) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+        this.w = w;
+    }
+
+    /**
+     * Constructor to create a rotation based quaternion from two vectors
+     * 
+     * @param vector1
+     * @param vector2
+     */
+    public Quaternion(float[] vector1, float[] vector2) {
+        final float theta = FloatUtil.acos(VectorUtil.dot(vector1, vector2));
+        final float[] cross = VectorUtil.cross(vector1, vector2);
+        fromAxis(cross, theta);
+    }
+    
+    /***
+     * Constructor to create a rotation based quaternion from axis vector and angle
+     * @param vector axis vector
+     * @param angle rotation angle (rads)
+     * @see #fromAxis(float[], float)
+     */
+    public Quaternion(float[] vector, float angle) {
+        fromAxis(vector, angle);
+    }
+    
+    /***
+     * Initialize this quaternion with given axis vector and rotation angle
+     * 
+     * @param vector axis vector
+     * @param angle rotation angle (rads)
+     */
+    public void fromAxis(float[] vector, float angle) {
+        final float halfangle = angle * 0.5f;
+        final float sin = FloatUtil.sin(halfangle);
+        final float[] nv = VectorUtil.normalize(vector);
+        x = (nv[0] * sin);
+        y = (nv[1] * sin);
+        z = (nv[2] * sin);
+        w = FloatUtil.cos(halfangle);
+    }
+
+    /**
+     * Transform the rotational quaternion to axis based rotation angles
+     * 
+     * @return new float[4] with ,theta,Rx,Ry,Rz
+     */
+    public float[] toAxis() {
+        final float[] vec = new float[4];
+        final float scale = FloatUtil.sqrt(x * x + y * y + z * z);
+        vec[0] = FloatUtil.acos(w) * 2.0f;
+        vec[1] = x / scale;
+        vec[2] = y / scale;
+        vec[3] = z / scale;
+        return vec;
+    }
+
+    public float getW() {
+        return w;
+    }
+
+    public void setW(float w) {
+        this.w = w;
+    }
+
+    public float getX() {
+        return x;
+    }
+
+    public void setX(float x) {
+        this.x = x;
+    }
+
+    public float getY() {
+        return y;
+    }
+
+    public void setY(float y) {
+        this.y = y;
+    }
+
+    public float getZ() {
+        return z;
+    }
+
+    public void setZ(float z) {
+        this.z = z;
+    }
+
+    /**
+     * Add a quaternion
+     * 
+     * @param q quaternion
+     */
+    public void add(Quaternion q) {
+        x += q.x;
+        y += q.y;
+        z += q.z;
+    }
+
+    /**
+     * Subtract a quaternion
+     * 
+     * @param q quaternion
+     */
+    public void subtract(Quaternion q) {
+        x -= q.x;
+        y -= q.y;
+        z -= q.z;
+    }
+
+    /**
+     * Divide a quaternion by a constant
+     * 
+     * @param n a float to divide by
+     */
+    public void divide(float n) {
+        x /= n;
+        y /= n;
+        z /= n;
+    }
+
+    /**
+     * Multiply this quaternion by the param quaternion
+     * 
+     * @param q a quaternion to multiply with
+     */
+    public void mult(Quaternion q) {
+        final float w1 = w * q.w - x * q.x - y * q.y - z * q.z;
+
+        final float x1 = w * q.x + x * q.w + y * q.z - z * q.y;
+        final float y1 = w * q.y - x * q.z + y * q.w + z * q.x;
+        final float z1 = w * q.z + x * q.y - y * q.x + z * q.w;
+
+        w = w1;
+        x = x1;
+        y = y1;
+        z = z1;
+    }
+
+    /**
+     * Multiply a quaternion by a constant
+     * 
+     * @param n a float constant
+     */
+    public void mult(float n) {
+        x *= n;
+        y *= n;
+        z *= n;
+    }
+    
+    /***
+     * Rotate given vector by this quaternion
+     * 
+     * @param vector input vector
+     * @return rotated vector
+     */
+    public float[] mult(float[] vector) {
+        // TODO : optimize
+        final float[] res = new float[3];
+        final Quaternion a = new Quaternion(vector[0], vector[1], vector[2], 0.0f);
+        final Quaternion b = new Quaternion(this);
+        final Quaternion c = new Quaternion(this);
+        b.inverse();
+        a.mult(b);
+        c.mult(a);
+        res[0] = c.x;
+        res[1] = c.y;
+        res[2] = c.z;
+        return res;
+    }
+
+    /**
+     * Normalize a quaternion required if to be used as a rotational quaternion
+     */
+    public void normalize() {
+        final float norme = (float) FloatUtil.sqrt(w * w + x * x + y * y + z * z);
+        if (norme == 0.0f) {
+            setIdentity();
+        } else {
+            final float recip = 1.0f / norme;
+
+            w *= recip;
+            x *= recip;
+            y *= recip;
+            z *= recip;
+        }
+    }
+
+    /**
+     * Invert the quaternion If rotational, will produce a the inverse rotation
+     */
+    public void inverse() {
+        final float norm = w * w + x * x + y * y + z * z;
+
+        final float recip = 1.0f / norm;
+
+        w *= recip;
+        x = -1 * x * recip;
+        y = -1 * y * recip;
+        z = -1 * z * recip;
+    }
+
+    /**
+     * Transform this quaternion to a 4x4 column matrix representing the
+     * rotation
+     * 
+     * @return new float[16] column matrix 4x4
+     */
+    public float[] toMatrix() {
+        final float[] matrix = new float[16];
+        matrix[0] = 1.0f - 2 * y * y - 2 * z * z;
+        matrix[1] = 2 * x * y + 2 * w * z;
+        matrix[2] = 2 * x * z - 2 * w * y;
+        matrix[3] = 0;
+
+        matrix[4] = 2 * x * y - 2 * w * z;
+        matrix[5] = 1.0f - 2 * x * x - 2 * z * z;
+        matrix[6] = 2 * y * z + 2 * w * x;
+        matrix[7] = 0;
+
+        matrix[8] = 2 * x * z + 2 * w * y;
+        matrix[9] = 2 * y * z - 2 * w * x;
+        matrix[10] = 1.0f - 2 * x * x - 2 * y * y;
+        matrix[11] = 0;
+
+        matrix[12] = 0;
+        matrix[13] = 0;
+        matrix[14] = 0;
+        matrix[15] = 1;
+        return matrix;
+    }
+
+    /**
+     * Set this quaternion from a Sphereical interpolation of two param
+     * quaternion, used mostly for rotational animation.
+     * <p>
+     * Note: Method does not normalize this quaternion!
+     * </p>
+     * <p>
+     * See http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/
+     * quaternions/slerp/
+     * </p>
+     * 
+     * @param a initial quaternion
+     * @param b target quaternion
+     * @param t float between 0 and 1 representing interp.
+     */
+    public void slerp(Quaternion a, Quaternion b, float t) {
+        final float cosom = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
+        final float t1 = 1.0f - t;
+
+        // if the two quaternions are close, just use linear interpolation
+        if (cosom >= 0.95f) {
+            x = a.x * t1 + b.x * t;
+            y = a.y * t1 + b.y * t;
+            z = a.z * t1 + b.z * t;
+            w = a.w * t1 + b.w * t;
+            return;
+        }
+
+        // the quaternions are nearly opposite, we can pick any axis normal to
+        // a,b
+        // to do the rotation
+        if (cosom <= -0.99f) {
+            x = 0.5f * (a.x + b.x);
+            y = 0.5f * (a.y + b.y);
+            z = 0.5f * (a.z + b.z);
+            w = 0.5f * (a.w + b.w);
+            return;
+        }
+
+        // cosom is now withion range of acos, do a SLERP
+        final float sinom = FloatUtil.sqrt(1.0f - cosom * cosom);
+        final float omega = FloatUtil.acos(cosom);
+
+        final float scla = FloatUtil.sin(t1 * omega) / sinom;
+        final float sclb = FloatUtil.sin(t * omega) / sinom;
+
+        x = a.x * scla + b.x * sclb;
+        y = a.y * scla + b.y * sclb;
+        z = a.z * scla + b.z * sclb;
+        w = a.w * scla + b.w * sclb;
+    }
+
+    /**
+     * Check if this quaternion is empty, ie (0,0,0,1)
+     * 
+     * @return true if empty, false otherwise
+     * @deprecated use {@link #isIdentity()} instead
+     */
+    @Deprecated
+    public boolean isEmpty() {
+        if (w == 1 && x == 0 && y == 0 && z == 0)
+            return true;
+        return false;
+    }
+
+    /**
+     * Check if this quaternion represents an identity matrix, for rotation.
+     * 
+     * @return true if it is an identity rep., false otherwise
+     */
+    public boolean isIdentity() {
+        return w == 1 && x == 0 && y == 0 && z == 0;
+    }
+    
+    /***
+     * Set this quaternion to identity (x=0,y=0,z=0,w=1)
+     */
+    public void setIdentity() {
+        x = y = z = 0;
+        w = 1;
+    }
+
+    /**
+     * compute the quaternion from a 3x3 column matrix
+     * 
+     * @param m 3x3 column matrix
+     */
+    public void setFromMatrix(float[] m) {
+        final float T = m[0] + m[4] + m[8] + 1;
+        if (T > 0) {
+            final float S = 0.5f / (float) FloatUtil.sqrt(T);
+            w = 0.25f / S;
+            x = (m[5] - m[7]) * S;
+            y = (m[6] - m[2]) * S;
+            z = (m[1] - m[3]) * S;
+        } else {
+            if ((m[0] > m[4]) & (m[0] > m[8])) {
+                final float S = FloatUtil.sqrt(1.0f + m[0] - m[4] - m[8]) * 2f; // S=4*qx
+                w = (m[7] - m[5]) / S;
+                x = 0.25f * S;
+                y = (m[3] + m[1]) / S;
+                z = (m[6] + m[2]) / S;
+            } else if (m[4] > m[8]) {
+                final float S = FloatUtil.sqrt(1.0f + m[4] - m[0] - m[8]) * 2f; // S=4*qy
+                w = (m[6] - m[2]) / S;
+                x = (m[3] + m[1]) / S;
+                y = 0.25f * S;
+                z = (m[7] + m[5]) / S;
+            } else {
+                final float S = FloatUtil.sqrt(1.0f + m[8] - m[0] - m[4]) * 2f; // S=4*qz
+                w = (m[3] - m[1]) / S;
+                x = (m[6] + m[2]) / S;
+                y = (m[7] + m[5]) / S;
+                z = 0.25f * S;
+            }
+        }
+    }
+
+    /**
+     * Check if the the 3x3 matrix (param) is in fact an affine rotational
+     * matrix
+     * 
+     * @param m 3x3 column matrix
+     * @return true if representing a rotational matrix, false otherwise
+     */
+    public boolean isRotationMatrix(float[] m) {
+        final double epsilon = 0.01; // margin to allow for rounding errors
+        if (FloatUtil.abs(m[0] * m[3] + m[3] * m[4] + m[6] * m[7]) > epsilon)
+            return false;
+        if (FloatUtil.abs(m[0] * m[2] + m[3] * m[5] + m[6] * m[8]) > epsilon)
+            return false;
+        if (FloatUtil.abs(m[1] * m[2] + m[4] * m[5] + m[7] * m[8]) > epsilon)
+            return false;
+        if (FloatUtil.abs(m[0] * m[0] + m[3] * m[3] + m[6] * m[6] - 1) > epsilon)
+            return false;
+        if (FloatUtil.abs(m[1] * m[1] + m[4] * m[4] + m[7] * m[7] - 1) > epsilon)
+            return false;
+        if (FloatUtil.abs(m[2] * m[2] + m[5] * m[5] + m[8] * m[8] - 1) > epsilon)
+            return false;
+        return (FloatUtil.abs(determinant(m) - 1) < epsilon);
+    }
+
+    private float determinant(float[] m) {
+        return m[0] * m[4] * m[8] + m[3] * m[7] * m[2] + m[6] * m[1] * m[5]
+                - m[0] * m[7] * m[5] - m[3] * m[1] * m[8] - m[6] * m[4] * m[2];
+    }
+}
diff --git a/src/jogl/classes/com/jogamp/graph/math/VectorUtil.java b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
old mode 100755
new mode 100644
similarity index 73%
rename from src/jogl/classes/com/jogamp/graph/math/VectorUtil.java
rename to src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
index d51afcb..0033afe
--- a/src/jogl/classes/com/jogamp/graph/math/VectorUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
@@ -25,14 +25,10 @@
  * authors and should not be interpreted as representing official policies, either expressed
  * or implied, of JogAmp Community.
  */
-package com.jogamp.graph.math;
+package com.jogamp.opengl.math;
 
 import java.util.ArrayList;
 
-import jogamp.graph.math.MathFloat;
-
-import com.jogamp.graph.geom.Vertex;
-
 public class VectorUtil {
 
     public enum Winding {
@@ -62,9 +58,9 @@ public class VectorUtil {
      */
     public static float[] normalize(float[] vector)
     {
-        float[] newVector = new float[3];
+        final float[] newVector = new float[3];
 
-        float d = MathFloat.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]);
+        final float d = FloatUtil.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]);
         if(d> 0.0f)
         {
             newVector[0] = vector[0]/d;
@@ -81,7 +77,7 @@ public class VectorUtil {
      */
     public static float[] scale(float[] vector, float scale)
     {
-        float[] newVector = new float[3];
+        final float[] newVector = new float[3];
 
         newVector[0] = vector[0]*scale;
         newVector[1] = vector[1]*scale;
@@ -96,7 +92,7 @@ public class VectorUtil {
      */
     public static float[] vectorAdd(float[] v1, float[] v2)
     {
-        float[] newVector = new float[3];
+        final float[] newVector = new float[3];
 
         newVector[0] = v1[0] + v2[0];
         newVector[1] = v1[1] + v2[1];
@@ -111,7 +107,7 @@ public class VectorUtil {
      */
     public static float[] cross(float[] vec1, float[] vec2)
     {
-        float[] out = new float[3];
+        final float[] out = new float[3];
 
         out[0] = vec2[2]*vec1[1] - vec2[1]*vec1[2];
         out[1] = vec2[0]*vec1[2] - vec2[2]*vec1[0];
@@ -127,7 +123,7 @@ public class VectorUtil {
      */
     public static float[] colMatrixVectorMult(float[] colMatrix, float[] vec)
     {
-        float[] out = new float[3];
+        final float[] out = new float[3];
 
         out[0] = vec[0]*colMatrix[0] + vec[1]*colMatrix[4] + vec[2]*colMatrix[8] + colMatrix[12]; 
         out[1] = vec[0]*colMatrix[1] + vec[1]*colMatrix[5] + vec[2]*colMatrix[9] + colMatrix[13]; 
@@ -143,7 +139,7 @@ public class VectorUtil {
      */
     public static float[] rowMatrixVectorMult(float[] rawMatrix, float[] vec)
     {
-        float[] out = new float[3];
+        final float[] out = new float[3];
 
         out[0] = vec[0]*rawMatrix[0] + vec[1]*rawMatrix[1] + vec[2]*rawMatrix[2] + rawMatrix[3]; 
         out[1] = vec[0]*rawMatrix[4] + vec[1]*rawMatrix[5] + vec[2]*rawMatrix[6] + rawMatrix[7]; 
@@ -161,6 +157,7 @@ public class VectorUtil {
     {
         return (p1+p2)/2.0f;
     }
+    
     /** Calculate the midpoint of two points
      * @param p1 first point
      * @param p2 second point
@@ -168,21 +165,23 @@ public class VectorUtil {
      */
     public static float[] mid(float[] p1, float[] p2)
     {
-        float[] midPoint = new float[3];
+        final float[] midPoint = new float[3];
         midPoint[0] = (p1[0] + p2[0])*0.5f;
         midPoint[1] = (p1[1] + p2[1])*0.5f;
         midPoint[2] = (p1[2] + p2[2])*0.5f;
 
         return midPoint;
     }
+    
     /** Compute the norm of a vector
      * @param vec vector
      * @return vorm
      */
     public static float norm(float[] vec)
     {
-        return MathFloat.sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
+        return FloatUtil.sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
     }
+    
     /** Compute distance between 2 points
      * @param p0 a ref point on the line
      * @param vec vector representing the direction of the line
@@ -191,11 +190,11 @@ public class VectorUtil {
      */
     public static float computeLength(float[] p0, float[] point)
     {
-        float[] w = new float[]{point[0]-p0[0],point[1]-p0[1],point[2]-p0[2]};
+        final float w0 = point[0]-p0[0];
+        final float w1 = point[1]-p0[1];
+        final float w2 = point[2]-p0[2];
 
-        float distance = MathFloat.sqrt(w[0]*w[0] + w[1]*w[1] + w[2]*w[2]);
-
-        return distance;
+        return FloatUtil.sqrt(w0*w0 + w1*w1 + w2*w2);
     }
 
     /**Check equality of 2 vec3 vectors
@@ -205,11 +204,9 @@ public class VectorUtil {
      */
     public static boolean checkEquality(float[] v1, float[] v2)
     {
-        if(Float.compare(v1[0], v2[0]) == 0 &&
-                Float.compare(v1[1], v2[1]) == 0 &&
-                Float.compare(v1[2], v2[2]) == 0 )
-            return true;
-        return false;
+        return Float.compare(v1[0], v2[0]) == 0 &&
+               Float.compare(v1[1], v2[1]) == 0 &&
+               Float.compare(v1[2], v2[2]) == 0 ;
     }
 
     /**Check equality of 2 vec2 vectors
@@ -219,10 +216,8 @@ public class VectorUtil {
      */
     public static boolean checkEqualityVec2(float[] v1, float[] v2)
     {
-        if(Float.compare(v1[0], v2[0]) == 0 && 
-                Float.compare(v1[1], v2[1]) == 0)
-            return true;
-        return false;
+        return Float.compare(v1[0], v2[0]) == 0 && 
+               Float.compare(v1[1], v2[1]) == 0 ;
     }
 
     /** Compute the determinant of 3 vectors
@@ -233,8 +228,7 @@ public class VectorUtil {
      */
     public static float computeDeterminant(float[] a, float[] b, float[] c)
     {
-        float area = a[0]*b[1]*c[2] + a[1]*b[2]*c[0] + a[2]*b[0]*c[1] - a[0]*b[2]*c[1] - a[1]*b[0]*c[2] - a[2]*b[1]*c[0];
-        return area;
+        return a[0]*b[1]*c[2] + a[1]*b[2]*c[0] + a[2]*b[0]*c[1] - a[0]*b[2]*c[1] - a[1]*b[0]*c[2] - a[2]*b[1]*c[0];
     }
 
     /** Check if three vertices are colliniear
@@ -255,7 +249,7 @@ public class VectorUtil {
      */
     public static float[] computeVector(float[] v1, float[] v2)
     {
-        float[] vector = new float[3];
+        final float[] vector = new float[3];
         vector[0] = v2[0] - v1[0];
         vector[1] = v2[1] - v1[1];
         vector[2] = v2[2] - v1[2];
@@ -270,11 +264,11 @@ public class VectorUtil {
      * @return true if the vertex d is inside the circle defined by the 
      * vertices a, b, c. from paper by Guibas and Stolfi (1985).
      */
-    public static boolean inCircle(Vertex a, Vertex b, Vertex c, Vertex d){
+    public static boolean inCircle(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d){
         return (a.getX() * a.getX() + a.getY() * a.getY()) * triArea(b, c, d) -
-        (b.getX() * b.getX() + b.getY() * b.getY()) * triArea(a, c, d) +
-        (c.getX() * c.getX() + c.getY() * c.getY()) * triArea(a, b, d) -
-        (d.getX() * d.getX() + d.getY() * d.getY()) * triArea(a, b, c) > 0;
+               (b.getX() * b.getX() + b.getY() * b.getY()) * triArea(a, c, d) +
+               (c.getX() * c.getX() + c.getY() * c.getY()) * triArea(a, b, d) -
+               (d.getX() * d.getX() + d.getY() * d.getY()) * triArea(a, b, c) > 0;
     }
 
     /** Computes oriented area of a triangle
@@ -284,7 +278,7 @@ public class VectorUtil {
      * @return compute twice the area of the oriented triangle (a,b,c), the area
      * is positive if the triangle is oriented counterclockwise.
      */
-    public static float triArea(Vertex a, Vertex b, Vertex c){
+    public static float triArea(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c) {
         return (b.getX() - a.getX()) * (c.getY() - a.getY()) - (b.getY() - a.getY())*(c.getX() - a.getX());
     }
 
@@ -298,21 +292,21 @@ public class VectorUtil {
      */
     public static boolean vertexInTriangle(float[] a, float[]  b, float[]  c, float[]  p){
         // Compute vectors        
-        float[] ac = computeVector(a, c); //v0
-        float[] ab = computeVector(a, b); //v1
-        float[] ap = computeVector(a, p); //v2
+        final float[] ac = computeVector(a, c); //v0
+        final float[] ab = computeVector(a, b); //v1
+        final float[] ap = computeVector(a, p); //v2
 
         // Compute dot products
-        float dot00 = dot(ac, ac);
-        float dot01 = dot(ac, ab);
-        float dot02 = dot(ac, ap);
-        float dot11 = dot(ab, ab);
-        float dot12 = dot(ab, ap);
+        final float dot00 = dot(ac, ac);
+        final float dot01 = dot(ac, ab);
+        final float dot02 = dot(ac, ap);
+        final float dot11 = dot(ab, ab);
+        final float dot12 = dot(ab, ap);
 
         // Compute barycentric coordinates
-        float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
-        float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
-        float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
+        final float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
+        final float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
+        final float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
 
         // Check if point is in triangle
         return (u >= 0) && (v >= 0) && (u + v < 1);
@@ -324,7 +318,7 @@ public class VectorUtil {
      * @param c third vertex
      * @return true if the points a,b,c are in a ccw order
      */
-    public static boolean ccw(Vertex a, Vertex b, Vertex c){
+    public static boolean ccw(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c){
         return triArea(a,b,c) > 0;
     }
 
@@ -334,7 +328,7 @@ public class VectorUtil {
      * @param c third vertex
      * @return Winding
      */
-    public static Winding getWinding(Vertex a, Vertex b, Vertex c) {
+    public static Winding getWinding(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c) {
         return triArea(a,b,c) > 0 ? Winding.CCW : Winding.CW ;
     }
 
@@ -342,13 +336,13 @@ public class VectorUtil {
      * @param vertices
      * @return positive area if ccw else negative area value
      */
-    public static float area(ArrayList<Vertex> vertices) {
-        int n = vertices.size();
+    public static float area(ArrayList<? extends Vert2fImmutable> vertices) {
+        final int n = vertices.size();
         float area = 0.0f;
         for (int p = n - 1, q = 0; q < n; p = q++)
         {
-            float[] pCoord = vertices.get(p).getCoord();
-            float[] qCoord = vertices.get(q).getCoord();
+            final float[] pCoord = vertices.get(p).getCoord();
+            final float[] qCoord = vertices.get(q).getCoord();
             area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1];
         }
         return area;
@@ -358,7 +352,7 @@ public class VectorUtil {
      * @param vertices array of Vertices
      * @return CCW or CW {@link Winding}
      */
-    public static Winding getWinding(ArrayList<Vertex> vertices) {
+    public static Winding getWinding(ArrayList<? extends Vert2fImmutable> vertices) {
         return area(vertices) >= 0 ? Winding.CCW : Winding.CW ;
     }
 
@@ -371,19 +365,19 @@ public class VectorUtil {
      * @return the intersection coordinates if the segments intersect, otherwise 
      * returns null 
      */
-    public static float[] seg2SegIntersection(Vertex a, Vertex b, Vertex c, Vertex d) {
-        float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
+    public static float[] seg2SegIntersection(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d) {
+        final float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
 
         if (determinant == 0) 
             return null;
 
-        float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
-        float beta = (c.getX()*d.getY()-c.getY()*d.getY());
-        float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
-        float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
+        final float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
+        final float beta = (c.getX()*d.getY()-c.getY()*d.getY());
+        final float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
+        final float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
 
-        float gamma = (xi - a.getX())/(b.getX() - a.getX());
-        float gamma1 = (xi - c.getX())/(d.getX() - c.getX());
+        final float gamma = (xi - a.getX())/(b.getX() - a.getX());
+        final float gamma1 = (xi - c.getX())/(d.getX() - c.getX());
         if(gamma <= 0 || gamma >= 1) return null;
         if(gamma1 <= 0 || gamma1 >= 1) return null;
 
@@ -398,16 +392,16 @@ public class VectorUtil {
      * @return the intersection coordinates if the lines intersect, otherwise 
      * returns null 
      */
-    public static float[] line2lineIntersection(Vertex a, Vertex b, Vertex c, Vertex d) {
-        float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
+    public static float[] line2lineIntersection(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d) {
+        final float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
 
         if (determinant == 0) 
             return null;
 
-        float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
-        float beta = (c.getX()*d.getY()-c.getY()*d.getY());
-        float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
-        float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
+        final float alpha = (a.getX()*b.getY()-a.getY()*b.getX());
+        final float beta = (c.getX()*d.getY()-c.getY()*d.getY());
+        final float xi = ((c.getX()-d.getX())*alpha-(a.getX()-b.getX())*beta)/determinant;
+        final float yi = ((c.getY()-d.getY())*alpha-(a.getY()-b.getY())*beta)/determinant;
 
         return new float[]{xi,yi,0};
     }
@@ -420,7 +414,7 @@ public class VectorUtil {
      * @param e vertex 2 of first segment
      * @return true if the segment intersects at least one segment of the triangle, false otherwise
      */
-    public static boolean tri2SegIntersection(Vertex a, Vertex b, Vertex c, Vertex d, Vertex e){
+    public static boolean tri2SegIntersection(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d, Vert2fImmutable e){
         if(seg2SegIntersection(a, b, d, e) != null)
             return true;
         if(seg2SegIntersection(b, c, d, e) != null)
diff --git a/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java b/src/jogl/classes/com/jogamp/opengl/math/Vert2fImmutable.java
similarity index 83%
copy from src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java
copy to src/jogl/classes/com/jogamp/opengl/math/Vert2fImmutable.java
index 832f5ae..1334988 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/Vert2fImmutable.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,19 +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.util;
+package com.jogamp.opengl.math;
 
-public interface KeyEventCountAdapter extends  InputEventCountAdapter {
-    public int getKeyPressedCount(boolean autoRepeatOnly);
+public interface Vert2fImmutable {
+    float getX();
+
+    float getY();
+
+    int getCoordCount();
     
-    public int getKeyReleasedCount(boolean autoRepeatOnly);
+    float[] getCoord();
     
-    public int getKeyTypedCount(boolean autoRepeatOnly);    
 }
-
diff --git a/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java b/src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.java
similarity index 82%
copy from src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java
copy to src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.java
index 832f5ae..76bd02f 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.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,19 +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.util;
+package com.jogamp.opengl.math;
 
-public interface KeyEventCountAdapter extends  InputEventCountAdapter {
-    public int getKeyPressedCount(boolean autoRepeatOnly);
-    
-    public int getKeyReleasedCount(boolean autoRepeatOnly);
-    
-    public int getKeyTypedCount(boolean autoRepeatOnly);    
+public interface Vert3fImmutable extends Vert2fImmutable {
+    float getZ();
 }
-
diff --git a/src/jogl/classes/com/jogamp/graph/geom/AABBox.java b/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java
similarity index 89%
rename from src/jogl/classes/com/jogamp/graph/geom/AABBox.java
rename to src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java
index 87f0849..b6e8ede 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/AABBox.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java
@@ -25,9 +25,10 @@
  * authors and should not be interpreted as representing official policies, either expressed
  * or implied, of JogAmp Community.
  */
-package com.jogamp.graph.geom;
+package com.jogamp.opengl.math.geom;
+
+import com.jogamp.opengl.math.VectorUtil;
 
-import com.jogamp.graph.math.VectorUtil;
 
 /**
  * Axis Aligned Bounding Box. Defined by two 3D coordinates (low and high)
@@ -57,13 +58,8 @@ public class AABBox implements Cloneable {
      * @param hz max z-coordinate
      */
     public AABBox(float lx, float ly, float lz,
-            float hx, float hy, float hz)
-    {
-        reset();
-        resize(lx, ly, lz);
-        resize(hx, hy, hz);
-
-        computeCenter();
+                  float hx, float hy, float hz) {
+        setSize(lx, ly, lz, hx, hy, hz);
     }
     
     /** Create a AABBox defining the low and high
@@ -71,11 +67,7 @@ public class AABBox implements Cloneable {
      * @param high max xyz-coordinates
      */
     public AABBox(float[] low, float[] high) {
-        reset();
-        resize(low[0],low[1],low[2]);
-        resize(high[0],high[1],high[2]);
-
-        computeCenter();
+        setSize(low[0],low[1],low[2], high[0],high[1],high[2]);
     }
 
     /** resets this box to the inverse low/high, allowing the next {@link #resize(float, float, float)} command to hit. */
@@ -113,6 +105,34 @@ public class AABBox implements Cloneable {
         this.low[2] = lz;
     }
 
+    private final void computeCenter() {
+        center[0] = (high[0] + low[0])/2;
+        center[1] = (high[1] + low[1])/2;
+        center[2] = (high[2] + low[2])/2;
+    }
+
+    /** 
+     * Set size of the AABBox specifying the coordinates 
+     * of the low and high.
+     * 
+     * @param lx min x-coordinate
+     * @param ly min y-coordnate
+     * @param lz min z-coordinate
+     * @param hx max x-coordinate
+     * @param hy max y-coordinate
+     * @param hz max z-coordinate
+     */
+    public final void setSize(float lx, float ly, float lz,
+                              float hx, float hy, float hz) {        
+        this.low[0] = lx;
+        this.low[1] = ly;
+        this.low[2] = lz;
+        this.high[0] = hx;
+        this.high[1] = hy;
+        this.high[2] = hz;
+        computeCenter();
+    }
+    
     /** Resize the AABBox to encapsulate another AABox
      * @param newBox AABBox to be encapsulated in
      */
@@ -139,12 +159,6 @@ public class AABBox implements Cloneable {
         computeCenter();
     }
 
-    private final void computeCenter() {
-        center[0] = (high[0] + low[0])/2;
-        center[1] = (high[1] + low[1])/2;
-        center[2] = (high[2] + low[2])/2;
-    }
-
     /** Resize the AABBox to encapsulate the passed
      * xyz-coordinates. 
      * @param x x-axis coordinate value
@@ -291,6 +305,22 @@ public class AABBox implements Cloneable {
         return low[1];
     }
     
+    public final float getMinZ() {
+        return low[2];
+    }
+    
+    public final float getMaxX() {
+        return high[0];
+    }
+    
+    public final float getMaxY() {
+        return high[1];
+    }
+    
+    public final float getMaxZ() {
+        return high[2];
+    }
+    
     public final float getWidth(){
         return high[0] - low[0];
     }
diff --git a/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java b/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java
new file mode 100644
index 0000000..93e68a1
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.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.math.geom;
+
+import com.jogamp.common.os.Platform;
+
+/**
+ * Providing frustum {@link #getPlanes() planes} derived by different inputs 
+ * ({@link #updateByPMV(float[], int) P*MV}, ..)
+ * used to {@link #classifySphere(float[], float) classify objects} and to test 
+ * whether they are {@link #isOutside(AABBox) outside}.
+ * 
+ * <p>
+ * Extracting the world-frustum planes from the P*Mv:
+ * <pre>
+ * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix
+ *   Gil Gribb <ggribb at ravensoft.com>
+ *   Klaus Hartmann <k_hartmann at osnabrueck.netsurf.de>
+ *   http://graphics.cs.ucf.edu/cap4720/fall2008/plane_extraction.pdf
+ * </pre>
+ * Classifying Point, Sphere and AABBox:
+ * <pre>
+ * Efficient View Frustum Culling
+ *   Daniel Sýkora <sykorad at fel.cvut.cz>
+ *   Josef Jelínek <jelinej1 at fel.cvut.cz>
+ *   http://www.cg.tuwien.ac.at/hostings/cescg/CESCG-2002/DSykoraJJelinek/index.html
+ * </pre>
+ * <pre>
+ * Lighthouse3d.com
+ * http://www.lighthouse3d.com/tutorials/view-frustum-culling/
+ * </pre>
+ * 
+ * Fundamentals about Planes, Half-Spaces and Frustum-Culling:<br/>
+ * <pre>
+ * Planes and Half-Spaces,  Max Wagner <mwagner at digipen.edu>
+ * http://www.emeyex.com/site/tuts/PlanesHalfSpaces.pdf
+ * </pre>
+ * <pre>
+ * Frustum Culling,  Max Wagner <mwagner at digipen.edu>
+ * http://www.emeyex.com/site/tuts/FrustumCulling.pdf
+ * </pre>
+ * </p>
+ */
+public class Frustum {
+    /** Normalized planes[l, r, b, t, n, f] */
+	protected Plane[] planes = new Plane[6];
+	
+	/**
+	 * Creates an undefined instance w/o calculating the frustum.
+	 * <p>
+	 * Use one of the <code>update(..)</code> methods to set the {@link #getPlanes() planes}.
+	 * </p>
+	 * @see #updateByPlanes(Plane[])
+	 * @see #updateByPMV(float[], int)
+	 */
+    public Frustum() {
+        for (int i = 0; i < 6; ++i) {
+            planes[i] = new Plane();
+        }
+    }
+    
+	/** 
+	 * Plane equation := dot(n, x - p) = 0 ->  ax + bc + cx + d == 0
+	 * <p>
+	 * In order to work w/ {@link Frustum#isOutside(AABBox) isOutside(..)} methods,
+	 * the normals have to point to the inside of the frustum.
+	 * </p> 
+	 */
+    public static class Plane {
+        /** Normal of the plane */
+        public final float[] n = new float[3];
+        
+        /** Distance to origin */
+        public float d;
+
+        /** 
+         * Return signed distance of plane to given point.
+         * <ul>
+         *   <li>If dist < 0 , then the point p lies in the negative halfspace.</li>
+         *   <li>If dist = 0 , then the point p lies in the plane.</li>
+         *   <li>If dist > 0 , then the point p lies in the positive halfspace.</li>
+         * </ul> 
+         * A plane cuts 3D space into 2 half spaces.
+         * <p>
+         * Positive halfspace is where the plane’s normals vector points into.
+         * </p> 
+         * <p>
+         * Negative halfspace is the <i>other side</i> of the plane, i.e. *-1
+         * </p> 
+         **/
+        public final float distanceTo(float x, float y, float z) {
+            return n[0] * x + n[1] * y + n[2] * z + d;
+        }
+
+        /** Return distance of plane to given point, see {@link #distanceTo(float, float, float)}. */
+        public final float distanceTo(float[] p) {
+            return n[0] * p[0] + n[1] * p[1] + n[2] * p[2] + d;
+        }
+        
+        @Override
+        public String toString() {
+            return "Plane[ [ " + n[0] + ", " + n[1] + ", " + n[2] + " ], " + d + "]";
+        }
+    }
+    
+    /** Index for left plane: {@value} */
+    public static final int LEFT   = 0;
+    /** Index for right plane: {@value} */
+    public static final int RIGHT  = 1;
+    /** Index for bottom plane: {@value} */
+    public static final int BOTTOM = 2;
+    /** Index for top plane: {@value} */
+    public static final int TOP    = 3;
+    /** Index for near plane: {@value} */
+    public static final int NEAR   = 4;
+    /** Index for far plane: {@value} */
+    public static final int FAR    = 5;
+    
+    /**
+     * {@link Plane}s are ordered in the returned array as follows:
+     * <ul>
+     *   <li>{@link #LEFT}</li>
+     *   <li>{@link #RIGHT}</li>
+     *   <li>{@link #BOTTOM}</li>
+     *   <li>{@link #TOP}</li>
+     *   <li>{@link #NEAR}</li>
+     *   <li>{@link #FAR}</li>
+     * </ul>
+     * <p>
+     * {@link Plane}'s normals are pointing to the inside of the frustum
+     * in order to work w/ {@link #isOutside(AABBox) isOutside(..)} methods.
+     * </p> 
+     * 
+     * @return array of normalized {@link Plane}s, order see above. 
+     */
+    public final Plane[] getPlanes() { return planes; }
+    
+    /**
+     * Copy the given <code>src</code> planes into this this instance's planes.
+     * @param src the 6 source planes
+     */
+    public final void updateByPlanes(Plane[] src) { 
+        for (int i = 0; i < 6; ++i) {
+            final Plane p0 = planes[i];
+            final float[] p0_n = p0.n;
+            final Plane p1 = src[i];
+            final float[] p1_n = p1.n;
+            p0_n[0] = p1_n[0];
+            p0_n[1] = p1_n[1];
+            p0_n[2] = p1_n[2];
+            p0.d = p1.d;
+        }
+    }
+    
+    /**
+     * Calculate the frustum planes in world coordinates
+     * using the passed float[16] as premultiplied P*MV (column major order).
+     * <p>
+     * Frustum plane's normals will point to the inside of the viewing frustum,
+     * as required by this class.
+     * </p>
+     */
+    public void updateByPMV(float[] pmv, int pmv_off) {        
+        // Left:   a = m41 + m11, b = m42 + m12, c = m43 + m13, d = m44 + m14  - [1..4] row-major
+        // Left:   a = m30 + m00, b = m31 + m01, c = m32 + m02, d = m33 + m03  - [0..3] row-major
+        {
+            final Plane p = planes[LEFT];
+            final float[] p_n = p.n;
+            p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 0 + 0 * 4 ];
+            p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 0 + 1 * 4 ];
+            p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 0 + 2 * 4 ];
+            p.d    = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 0 + 3 * 4 ];
+        }
+
+        // Right:  a = m41 - m11, b = m42 - m12, c = m43 - m13, d = m44 - m14  - [1..4] row-major
+        // Right:  a = m30 - m00, b = m31 - m01, c = m32 - m02, d = m33 - m03  - [0..3] row-major
+        {
+            final Plane p = planes[RIGHT];
+            final float[] p_n = p.n;
+            p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 0 + 0 * 4 ];
+            p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 0 + 1 * 4 ];
+            p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 0 + 2 * 4 ];
+            p.d    = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 0 + 3 * 4 ];
+        }
+
+        // Bottom: a = m41 + m21, b = m42 + m22, c = m43 + m23, d = m44 + m24  - [1..4] row-major
+        // Bottom: a = m30 + m10, b = m31 + m11, c = m32 + m12, d = m33 + m13  - [0..3] row-major
+        {
+            final Plane p = planes[BOTTOM];
+            final float[] p_n = p.n;
+            p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 1 + 0 * 4 ];
+            p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 1 + 1 * 4 ];
+            p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 1 + 2 * 4 ];
+            p.d    = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 1 + 3 * 4 ];
+        }
+
+        // Top:   a = m41 - m21, b = m42 - m22, c = m43 - m23, d = m44 - m24  - [1..4] row-major
+        // Top:   a = m30 - m10, b = m31 - m11, c = m32 - m12, d = m33 - m13  - [0..3] row-major
+        {
+            final Plane p = planes[TOP];
+            final float[] p_n = p.n;
+            p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 1 + 0 * 4 ];
+            p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 1 + 1 * 4 ];
+            p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 1 + 2 * 4 ];
+            p.d    = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 1 + 3 * 4 ];
+        }
+
+        // Near:  a = m41 + m31, b = m42 + m32, c = m43 + m33, d = m44 + m34  - [1..4] row-major
+        // Near:  a = m30 + m20, b = m31 + m21, c = m32 + m22, d = m33 + m23  - [0..3] row-major
+        {
+            final Plane p = planes[NEAR];
+            final float[] p_n = p.n;
+            p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 2 + 0 * 4 ];
+            p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 2 + 1 * 4 ];
+            p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 2 + 2 * 4 ];
+            p.d    = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 2 + 3 * 4 ];
+        }
+
+        // Far:   a = m41 - m31, b = m42 - m32, c = m43 - m33, d = m44 - m34  - [1..4] row-major
+        // Far:   a = m30 - m20, b = m31 - m21, c = m32 + m22, d = m33 + m23  - [0..3] row-major
+        {
+            final Plane p = planes[FAR];
+            final float[] p_n = p.n;
+            p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 2 + 0 * 4 ];
+            p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 2 + 1 * 4 ];
+            p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 2 + 2 * 4 ];
+            p.d    = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 2 + 3 * 4 ];
+        }
+
+        // Normalize all planes
+        for (int i = 0; i < 6; ++i) {
+            final Plane p = planes[i];
+            final float[] p_n = p.n;
+            final double invl = Math.sqrt(p_n[0] * p_n[0] + p_n[1] * p_n[1] + p_n[2] * p_n[2]);
+
+            p_n[0] /= invl;
+            p_n[1] /= invl;
+            p_n[2] /= invl;
+            p.d /= invl;
+        }
+    }
+    
+	private static final boolean isOutsideImpl(Plane p, AABBox box) {
+	    final float[] low = box.getLow();
+	    final float[] high = box.getHigh();
+	    
+		if ( p.distanceTo(low[0],  low[1],  low[2])  > 0.0f ||
+		     p.distanceTo(high[0], low[1],  low[2])  > 0.0f ||
+		     p.distanceTo(low[0],  high[1], low[2])  > 0.0f ||
+		     p.distanceTo(high[0], high[1], low[2])  > 0.0f ||
+		     p.distanceTo(low[0],  low[1],  high[2]) > 0.0f ||
+		     p.distanceTo(high[0], low[1],  high[2]) > 0.0f ||
+		     p.distanceTo(low[0],  high[1], high[2]) > 0.0f ||
+		     p.distanceTo(high[0], high[1], high[2]) > 0.0f ) {
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Check to see if an axis aligned bounding box is completely outside of the frustum.
+	 * <p>
+	 * Note: If method returns false, the box may only be partially inside.
+	 * </p>
+	 */
+    public final boolean isAABBoxOutside(AABBox box) {
+        for (int i = 0; i < 6; ++i) {
+            if ( isOutsideImpl(planes[i], box) ) {
+                // fully outside
+                return true;
+            }
+        }
+        // We make no attempt to determine whether it's fully inside or not.
+        return false;
+    }
+    
+    
+    public static enum Location { OUTSIDE, INSIDE, INTERSECT };
+    
+    /**
+     * Check to see if a point is outside, inside or on a plane of the frustum.
+     * 
+     * @param p the point
+     * @return {@link Location} of point related to frustum planes
+     */
+    public final Location classifyPoint(float[] p) {
+        Location res = Location.INSIDE;
+        
+        for (int i = 0; i < 6; ++i) {
+            final float d = planes[i].distanceTo(p);
+            if ( d < 0.0f ) {
+                return Location.OUTSIDE;
+            } else if ( d == 0.0f ) {
+                res = Location.INTERSECT;
+            }
+        }
+        return res;
+    }
+    
+    /**
+     * Check to see if a point is outside of the frustum.
+     * 
+     * @param p the point
+     * @return true if outside of the frustum, otherwise inside or on a plane
+     */
+    public final boolean isPointOutside(float[] p) {
+        return Location.OUTSIDE == classifyPoint(p);
+    }
+    
+    /**
+     * Check to see if a sphere is outside, intersecting or inside of the frustum.
+     * 
+     * @param p center of the sphere
+     * @param radius radius of the sphere
+     * @return {@link Location} of point related to frustum planes
+     */
+    public final Location classifySphere(float[] p, float radius) {
+        Location res = Location.INSIDE; // fully inside
+        
+        for (int i = 0; i < 6; ++i) {
+            final float d = planes[i].distanceTo(p);
+            if ( d < -radius ) { 
+                // fully outside
+                return Location.OUTSIDE;
+            } else if (d < radius ) {
+                // intersecting
+                res = Location.INTERSECT;
+            }
+        }        
+        return res;
+    }
+    
+    /**
+     * Check to see if a sphere is outside of the frustum.
+     * 
+     * @param p center of the sphere
+     * @param radius radius of the sphere
+     * @return true if outside of the frustum, otherwise inside or intersecting
+     */
+    public final boolean isSphereOutside(float[] p, float radius) {
+        return Location.OUTSIDE == classifySphere(p, radius);
+    }
+    
+    public StringBuilder toString(StringBuilder sb) {
+        if( null == sb ) {
+            sb = new StringBuilder();
+        }
+        sb.append("Frustum[ Planes[ ").append(Platform.NEWLINE)
+        .append(" L: ").append(planes[0]).append(", ").append(Platform.NEWLINE)
+        .append(" R: ").append(planes[1]).append(", ").append(Platform.NEWLINE)
+        .append(" B: ").append(planes[2]).append(", ").append(Platform.NEWLINE)
+        .append(" T: ").append(planes[3]).append(", ").append(Platform.NEWLINE)
+        .append(" N: ").append(planes[4]).append(", ").append(Platform.NEWLINE)
+        .append(" F: ").append(planes[5]).append("], ").append(Platform.NEWLINE)
+        .append("]");
+        return sb;
+    }
+    
+	@Override
+	public String toString() {
+	    return toString(null).toString();
+	}
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 3332262..ff764d8 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -27,10 +27,18 @@
  */
 package com.jogamp.opengl.swt;
 
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
 import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
 import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.ProxySurface;
 import javax.media.nativewindow.UpstreamSurfaceHook;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
 import javax.media.opengl.GL;
 import javax.media.opengl.GLAnimatorControl;
 import javax.media.opengl.GLAutoDrawable;
@@ -46,21 +54,20 @@ import javax.media.opengl.GLProfile;
 import javax.media.opengl.GLRunnable;
 import javax.media.opengl.Threading;
 
+import jogamp.nativewindow.x11.X11Util;
 import jogamp.opengl.Debug;
 import jogamp.opengl.GLContextImpl;
 import jogamp.opengl.GLDrawableHelper;
 import jogamp.opengl.GLDrawableImpl;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ControlAdapter;
-import org.eclipse.swt.events.ControlEvent;
-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.Canvas;
 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 com.jogamp.common.GlueGenVersion;
@@ -69,13 +76,14 @@ import com.jogamp.common.util.VersionUtil;
 import com.jogamp.common.util.locks.LockFactory;
 import com.jogamp.common.util.locks.RecursiveLock;
 import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
 import com.jogamp.opengl.JoglVersion;
 
 /**
  * Native SWT Canvas implementing GLAutoDrawable
- * 
- * <p>Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used instead.</p>
- * 
+ * <p>
+ * Implementation allows use of custom {@link GLCapabilities}.
+ * </p>
  */
 public class GLCanvas extends Canvas implements GLAutoDrawable {
   private static final boolean DEBUG = Debug.debug("GLCanvas");
@@ -99,11 +107,15 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
    private final GLCapabilitiesImmutable capsRequested;
    private final GLCapabilitiesChooser capsChooser; 
    
+   private volatile Rectangle clientArea;
    private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
-   private GLContextImpl context;
+   private volatile GLContextImpl context;
 
    /* Native window surface */
-   private AbstractGraphicsDevice device;
+   private final boolean useX11GTK;
+   private volatile long gdkWindow; // either GDK child window ..
+   private volatile long x11Window; // .. or X11 child window (for GL rendering)
+   private final AbstractGraphicsScreen screen;
 
    /* Construction parameters stored for GLAutoDrawable accessor methods */
    private int additionalCtxCreationFlags = 0;
@@ -131,7 +143,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
       @Override
       public void run() {
          if (sendReshape) {
-            helper.reshape(GLCanvas.this, 0, 0, getWidth(), getHeight());
+            helper.reshape(GLCanvas.this, 0, 0, clientArea.width, clientArea.height);
             sendReshape = false;
          }
          helper.display(GLCanvas.this);
@@ -139,13 +151,15 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
    };
 
    /* Action to make specified context current prior to running displayAction */
-   private final Runnable makeCurrentAndDisplayOnEDTAction = new Runnable() {
+   private final Runnable makeCurrentAndDisplayOnGLAction = new Runnable() {
       @Override
       public void run() {
         final RecursiveLock _lock = lock;
         _lock.lock();
-        try {            
-            helper.invokeGL(drawable, context, displayAction, initAction);
+        try {        
+            if( !GLCanvas.this.isDisposed() ) {
+                helper.invokeGL(drawable, context, displayAction, initAction);
+            }
         } finally {
             _lock.unlock();
         }
@@ -153,13 +167,14 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
    };
 
    /* Swaps buffers, assuming the GLContext is current */
-   private final Runnable swapBuffersOnEDTAction = new Runnable() {
+   private final Runnable swapBuffersOnGLAction = new Runnable() {
       @Override
       public void run() {
         final RecursiveLock _lock = lock;
         _lock.lock();
         try {
-            if(null != drawable) {
+            final boolean drawableOK = null != drawable && drawable.isRealized();
+            if( drawableOK && !GLCanvas.this.isDisposed() ) {
                 drawable.swapBuffers();
             }
         } finally {
@@ -171,56 +186,82 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
    /*
     * Disposes of OpenGL resources
     */
-   private final Runnable postDisposeGLAction = new Runnable() {
-      @Override
-      public void run() {
-         context = null;
-         if (null != drawable) {
-            drawable.setRealized(false);
-            drawable = null;
-         }
-      }
-   };
-
    private final Runnable disposeOnEDTGLAction = new Runnable() {
       @Override
       public void run() {
          final RecursiveLock _lock = lock;
          _lock.lock();
          try {
-             if (null != drawable && null != context) {
-                boolean animatorPaused = false;
-                final GLAnimatorControl animator = getAnimator();
-                if (null != animator) {
-                   animatorPaused = animator.pause();
-                }
-        
-                if(context.isCreated()) {
-                    helper.disposeGL(GLCanvas.this, drawable, context, postDisposeGLAction);
-                }
-        
-                if (animatorPaused) {
-                   animator.resume();
-                }
+             final GLAnimatorControl animator = getAnimator();
+             final boolean animatorPaused;
+             if(null!=animator) {
+                 // can't remove us from animator for recreational addNotify()
+                 animatorPaused = animator.pause();
+             } else {
+                 animatorPaused = false;
              }
-             // SWT is owner of the device handle, not us.
-             // Hence close() operation is a NOP. 
-             if (null != device) {
-                device.close();
-                device = null;
+
+             if ( null != context ) {
+                 if( context.isCreated() ) {
+                     // Catch dispose GLExceptions by GLEventListener, just 'print' them
+                     // so we can continue with the destruction.
+                     try {
+                         if( !GLCanvas.this.isDisposed() ) {
+                             helper.disposeGL(GLCanvas.this, context, true);
+                         } else {
+                             context.destroy();
+                         }
+                     } catch (GLException gle) {
+                         gle.printStackTrace();
+                     }
+                 }
+                 context = null;        
+             }
+             if ( null != drawable ) {
+                 drawable.setRealized(false);
+                 drawable = null;
+             }
+             if( 0 != x11Window) {
+                 SWTAccessor.destroyX11Window(screen.getDevice(), x11Window);
+                 x11Window = 0;
+             } else if( 0 != gdkWindow) {
+                 SWTAccessor.destroyGDKWindow(gdkWindow);
+                 gdkWindow = 0;
+             }
+             screen.getDevice().close();
+
+             if (animatorPaused) {
+                 animator.resume();
              }
-             SWTAccessor.setRealized(GLCanvas.this, false); // unrealize ..
+
          } finally {
              _lock.unlock();
          }
       }
    };
 
-   /**
-    * Storage for the client area rectangle so that it may be accessed from outside of the SWT thread.
-    */
-   private volatile Rectangle clientArea;
+   private class DisposeGLEventListenerAction implements Runnable {
+       private GLEventListener listener;
+       private boolean remove;
+       private DisposeGLEventListenerAction(GLEventListener listener, boolean remove) {
+           this.listener = listener;
+           this.remove = remove;
+       }
 
+       @Override
+       public void run() {
+           final RecursiveLock _lock = lock;
+           _lock.lock();
+           try {
+               if( !GLCanvas.this.isDisposed() ) {
+                   listener = helper.disposeGLEventListener(GLCanvas.this, drawable, context, listener, remove);
+               }
+           } finally {
+               _lock.unlock();
+           }
+       }
+   };
+   
    /** 
     * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser, GLContext)} 
     * on the SWT thread.
@@ -260,61 +301,80 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
     * @param style
     *           Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the
     *           Canvas constructor, so OpenGL handles the background.
-    * @param caps
+    * @param capsReqUser
     *           Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the
     *           graphics device determined by the parent Composite are used. Note that the GLCapabilities that are
     *           actually used may differ based on the capabilities of the graphics device.
-    * @param chooser
+    * @param capsChooser
     *           Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the
     *           requested GLCapabilities, and the available capabilities of the graphics device.
     * @param shareWith
     *           Optional GLContext to share state (textures, vbos, shaders, etc.) with.
     */
-   public GLCanvas(final Composite parent, final int style, GLCapabilitiesImmutable caps,
-                   final GLCapabilitiesChooser chooser, final GLContext shareWith) {
+   public GLCanvas(final Composite parent, final int style, GLCapabilitiesImmutable capsReqUser,
+                   final GLCapabilitiesChooser capsChooser, final GLContext shareWith) {
       /* NO_BACKGROUND required to avoid clearing bg in native SWT widget (we do this in the GL display) */
       super(parent, style | SWT.NO_BACKGROUND);
 
       GLProfile.initSingleton(); // ensure JOGL is completly initialized
 
       SWTAccessor.setRealized(this, true);
-
+      
       clientArea = GLCanvas.this.getClientArea();
 
       /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). 
        * Note: SWT is owner of the native handle, hence closing operation will be a NOP. */
-      device = SWTAccessor.getDevice(this);
+      final AbstractGraphicsDevice swtDevice = SWTAccessor.getDevice(this);
+      
+      useX11GTK = SWTAccessor.useX11GTK();
+      if(useX11GTK) {
+          // Decoupled X11 Device/Screen allowing X11 display lock-free off-thread rendering 
+          final long x11DeviceHandle = X11Util.openDisplay(swtDevice.getConnection());
+          if( 0 == x11DeviceHandle ) {
+              throw new RuntimeException("Error creating display(EDT): "+swtDevice.getConnection());
+          }
+          final AbstractGraphicsDevice x11Device = new X11GraphicsDevice(x11DeviceHandle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
+          screen = SWTAccessor.getScreen(x11Device, -1 /* default */);          
+      } else {
+          screen = SWTAccessor.getScreen(swtDevice, -1 /* default */);
+      }
 
       /* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */
-      if(null == caps) {
-          caps = new GLCapabilities(GLProfile.getDefault(device));
+      if(null == capsReqUser) {
+          capsReqUser = new GLCapabilities(GLProfile.getDefault(screen.getDevice()));
       }
-      this.capsRequested = caps;
-      this.capsChooser = chooser;
+            
+      this.capsRequested = capsReqUser;
+      this.capsChooser = capsChooser;
       this.shareWith = shareWith;
 
       // post create .. when ready
+      gdkWindow = 0;
+      x11Window = 0;
       drawable = null;
       context = null;
       
-      /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
-      /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
-      addPaintListener(new PaintListener() {
-         @Override
-        public void paintControl(final PaintEvent arg0) {
-            if ( !helper.isExternalAnimatorAnimating() ) {                
-               display(); // checks: null != drawable
-            }
-         }
-      });
-
-      addControlListener(new ControlAdapter() {
-         @Override
-         public void controlResized(final ControlEvent arg0) {
-            updateSizeCheck();
-         }
-      });
+      final Listener listener = new Listener () {
+          @Override
+          public void handleEvent (Event event) {
+              switch (event.type) {
+              case SWT.Paint:
+                  displayIfNoAnimatorNoCheck();
+                  break;
+              case SWT.Resize:
+                  updateSizeCheck();
+                  break;
+              case SWT.Dispose:
+                  GLCanvas.this.dispose();
+                  break;
+              }
+          }
+      };
+      addListener (SWT.Resize, listener);
+      addListener (SWT.Paint, listener);
+      addListener (SWT.Dispose, listener);
    }
+   
    private final UpstreamSurfaceHook swtCanvasUpStreamHook = new UpstreamSurfaceHook() {
        @Override
        public final void create(ProxySurface s) { /* nop */ }
@@ -346,11 +406,13 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
          ) {
           clientArea = nClientArea; // write back new value
           
-          GLDrawableImpl _drawable = drawable;
-          if( null != _drawable ) {
-              if(DEBUG) {
-                  System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
-              }
+          final GLDrawableImpl _drawable = drawable;
+          final boolean drawableOK = null != _drawable && _drawable.isRealized();
+          if(DEBUG) {
+              final long dh = drawableOK ? _drawable.getHandle() : 0;
+              System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - drawableHandle 0x"+Long.toHexString(dh));
+          }
+          if( drawableOK ) {
               if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
                   final RecursiveLock _lock = lock;
                   _lock.lock();
@@ -363,66 +425,154 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
                   } finally {
                       _lock.unlock();
                   }
-                  sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
-              }
-          }          
+              }              
+          }    
+          if(0 != x11Window) {
+              SWTAccessor.resizeX11Window(screen.getDevice(), clientArea, x11Window);
+          } else if(0 != gdkWindow) {
+              SWTAccessor.resizeGDKWindow(clientArea, gdkWindow);
+          }
+          sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
       }
    }
    
-   @Override
-   public void display() {
-      if( null != drawable || validateDrawableAndContext() ) {
-          runInGLThread(makeCurrentAndDisplayOnEDTAction);
-      }
+   private boolean isValidAndVisibleOnEDTActionResult;
+   private final Runnable isValidAndVisibleOnEDTAction = new Runnable() {
+       @Override
+       public void run() {           
+           isValidAndVisibleOnEDTActionResult = !GLCanvas.this.isDisposed() && GLCanvas.this.isVisible();
+       } };
+       
+   private final boolean isValidAndVisibleOnEDT() {
+       synchronized(isValidAndVisibleOnEDTAction) {
+           runOnEDTIfAvail(true, isValidAndVisibleOnEDTAction);
+           return isValidAndVisibleOnEDTActionResult;
+       }
    }
-
    
-   /** assumes drawable == null ! */
-   protected final boolean validateDrawableAndContext() {
-      if( GLCanvas.this.isDisposed() ) {
+   /** assumes drawable == null || !drawable.isRealized() !  Checks of !isDispose() and isVisible() */
+   protected final boolean validateDrawableAndContextWithCheck() {
+      if( !isValidAndVisibleOnEDT() ) {
           return false;
       }
+      return validateDrawableAndContextPostCheck();       
+   }
+   
+   /** assumes drawable == null || !drawable.isRealized() ! No check of !isDispose() and isVisible() */
+   protected final boolean validateDrawableAndContextPostCheck() {
       final Rectangle nClientArea = clientArea;
       if(0 >= nClientArea.width || 0 >= nClientArea.height) {
           return false;
       }
                
+      final boolean res;
       final RecursiveLock _lock = lock;
       _lock.lock();
       try {
-          final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile());
-    
-          /* Native handle for the control, used to associate with GLContext */
-          final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
-          
-          /* Create a NativeWindow proxy for the SWT canvas */
-          ProxySurface proxySurface = null;
-          try {
-              proxySurface = glFactory.createProxySurface(device, 0 /* screenIdx */, nativeWindowHandle, 
-                                                          capsRequested, capsChooser, swtCanvasUpStreamHook);
-          } catch (GLException gle) {
-              // not ready yet ..
-              if(DEBUG) { System.err.println(gle.getMessage()); }
+          if(null == drawable) {
+              createDrawableAndContext();
           }
-          
-          if(null != proxySurface) {
-              /* Associate a GL surface with the proxy */
-              drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface);
+          if(null != drawable) {
               drawable.setRealized(true);
-        
-              context = (GLContextImpl) drawable.createContext(shareWith);
+              res = drawable.isRealized();
+          } else {
+              res = false;
           }
       } finally {
           _lock.unlock();
+      }  
+            
+      if(res) {
+          sendReshape = true;
+          if(DEBUG) {
+              System.err.println("SWT GLCanvas realized! "+this+", "+drawable);
+              // Thread.dumpStack();
+          }          
       }
-      final boolean res = null != drawable;
-      if(DEBUG && res) {
-          System.err.println("SWT GLCanvas realized! "+this+", "+drawable);
-          Thread.dumpStack();
-      }
-      return res;
+      return res;      
+   }
+   
+   private final void createDrawableAndContext() {
+       final AbstractGraphicsDevice device = screen.getDevice();
+       device.open();
+
+       final long nativeWindowHandle;
+       if( useX11GTK ) {
+           final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(device, capsRequested);
+           final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration(
+                   capsRequested, capsRequested, capsChooser, screen, VisualIDHolder.VID_UNDEFINED);
+           if(DEBUG) {
+               System.err.println("SWT.GLCanvas.X11 factory: "+factory+", chosen config: "+cfg);
+           }        
+           if (null == cfg) {
+               throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+           }
+           final int visualID = cfg.getVisualID(VIDType.NATIVE);
+           if( VisualIDHolder.VID_UNDEFINED != visualID ) {
+               // gdkWindow = SWTAccessor.createCompatibleGDKChildWindow(this, visualID, clientArea.width, clientArea.height);
+               // nativeWindowHandle = SWTAccessor.gdk_window_get_xwindow(gdkWindow); 
+               x11Window = SWTAccessor.createCompatibleX11ChildWindow(screen, this, visualID, clientArea.width, clientArea.height);
+               nativeWindowHandle = x11Window;
+           } else {
+              throw new GLException("Could not choose valid visualID: 0x"+Integer.toHexString(visualID)+", "+this);
+           }
+       } else {
+           nativeWindowHandle = SWTAccessor.getWindowHandle(this);
+       }
+       final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile());
+       
+       // Create a NativeWindow proxy for the SWT canvas
+       ProxySurface proxySurface = glFactory.createProxySurface(device, screen.getIndex(), nativeWindowHandle, 
+                                                                capsRequested, capsChooser, swtCanvasUpStreamHook);
+       // Associate a GL surface with the proxy
+       drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface);
+       context = (GLContextImpl) drawable.createContext(shareWith);
+       context.setContextCreationFlags(additionalCtxCreationFlags);       
+   }
+   
+   @Override
+   public void update() {
+       // don't paint background etc .. nop avoids flickering
+       // super.update();
+   }
+
+   /**
+   @Override
+   public boolean forceFocus() {
+       final boolean r = super.forceFocus();
+       if(r && 0 != gdkWindow) {
+           SWTGTKUtil.focusGDKWindow(gdkWindow);
+       }
+       return r;       
+   } */
+   
+   @Override
+   public void dispose() {
+     runInGLThread(disposeOnEDTGLAction);
+     super.dispose();          
+   }
+
+   private final void displayIfNoAnimatorNoCheck() {
+       if ( !helper.isAnimatorAnimatingOnOtherThread() ) {
+           final boolean drawableOK = null != drawable && drawable.isRealized();
+           if( drawableOK || validateDrawableAndContextPostCheck() ) {
+               runInGLThread(makeCurrentAndDisplayOnGLAction);
+           }                
+       }
    }
    
+   //
+   // GL[Auto]Drawable
+   //
+   
+   @Override
+   public void display() {
+      final boolean drawableOK = null != drawable && drawable.isRealized();
+      if( drawableOK || validateDrawableAndContextWithCheck() ) {
+          runInGLThread(makeCurrentAndDisplayOnGLAction);
+      }
+   }
+
    @Override
    public final Object getUpstreamWidget() {
        return this;
@@ -439,13 +589,51 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
    }
 
    @Override
-   public void addGLEventListener(final GLEventListener arg0) {
-      helper.addGLEventListener(arg0);
+   public boolean isGLOriented() {
+      final GLDrawable _drawable = drawable;
+      return null != _drawable ? _drawable.isGLOriented() : true;
+   }
+    
+   @Override
+   public void addGLEventListener(final GLEventListener listener) {
+      helper.addGLEventListener(listener);
    }
 
    @Override
-   public void addGLEventListener(final int arg0, final GLEventListener arg1) throws IndexOutOfBoundsException {
-      helper.addGLEventListener(arg0, arg1);
+   public void addGLEventListener(final int idx, final GLEventListener listener) throws IndexOutOfBoundsException {
+      helper.addGLEventListener(idx, listener);
+   }
+
+   @Override
+   public int getGLEventListenerCount() {
+      return helper.getGLEventListenerCount();
+   }
+   
+   @Override
+   public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException {
+      return helper.getGLEventListener(index);
+   }
+   
+   @Override
+   public boolean getGLEventListenerInitState(GLEventListener listener) {
+       return helper.getGLEventListenerInitState(listener);
+   }
+   
+   @Override
+   public void setGLEventListenerInitState(GLEventListener listener, boolean initialized) {
+       helper.setGLEventListenerInitState(listener, initialized);
+   }
+   
+   @Override
+   public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove) {
+       final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
+       runInGLThread(r);
+       return r.listener;
+   }
+   
+   @Override
+   public GLEventListener removeGLEventListener(final GLEventListener listener) {
+      return helper.removeGLEventListener(listener);
    }
 
    /**
@@ -467,6 +655,16 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
    }
 
    @Override
+   public final Thread setExclusiveContextThread(Thread t) throws GLException {
+       return helper.setExclusiveContextThread(t, context);
+   }
+
+   @Override
+   public final Thread getExclusiveContextThread() {
+       return helper.getExclusiveContextThread();
+   }
+
+   @Override
    public boolean getAutoSwapBufferMode() {
       return helper.getAutoSwapBufferMode();
    }
@@ -493,20 +691,15 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
    }
 
    @Override
-   public boolean invoke(final boolean wait, final GLRunnable run) {
-      return helper.invoke(this, wait, run);
+   public boolean invoke(final boolean wait, final GLRunnable runnable) {
+      return helper.invoke(this, wait, runnable);
    }
-
-   @Override
-   public void removeGLEventListener(final GLEventListener arg0) {
-      helper.removeGLEventListener(arg0);
-   }
-
+   
    @Override
-   public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
-      return helper.removeGLEventListener(index);
+   public boolean invoke(final boolean wait, final List<GLRunnable> runnables) {
+      return helper.invoke(this, wait, runnables);
    }
-       
+   
    @Override
    public void setAnimator(final GLAnimatorControl arg0) throws GLException {
       helper.setAnimator(arg0);
@@ -518,16 +711,13 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
    }
 
    @Override
-   public GLContext setContext(GLContext newCtx) {
+   public GLContext setContext(GLContext newCtx, boolean destroyPrevCtx) {
       final RecursiveLock _lock = lock;
       _lock.lock();
       try {            
           final GLContext oldCtx = context;
-          final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+          GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
           context=(GLContextImpl)newCtx;
-          if(newCtxCurrent) {
-              context.makeCurrent();
-          }
           return oldCtx;
       } finally {
           _lock.unlock();
@@ -621,18 +811,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
 
    @Override
    public void swapBuffers() throws GLException {
-      runInGLThread(swapBuffersOnEDTAction);
-   }
-
-   @Override
-   public void update() {
-      // don't paint background etc .. nop avoids flickering
-   }
-
-   @Override
-   public void dispose() {
-      runInGLThread(disposeOnEDTGLAction);
-      super.dispose();
+      runInGLThread(swapBuffersOnGLAction);
    }
 
    /**
@@ -641,24 +820,66 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
     *   <li>Mac OSX
     *   <ul>
     *     <!--li>AWT EDT: In case AWT is available, the AWT EDT is the OSX UI main thread</li-->
-    *     <li><i>Main Thread</i>: Run on OSX UI main thread.</li>
+    *     <!--li><i>Main Thread</i>: Run on OSX UI main thread.</li-->
+    *     <li>Current thread</li>
     *   </ul></li>
     *   <li>Linux, Windows, ..
     *   <ul>
-    *     <li>Use {@link Threading#invokeOnOpenGLThread(boolean, Runnable)}</li>
+    *     <!--li>Use {@link Threading#invokeOnOpenGLThread(boolean, Runnable)}</li-->
+    *     <li>Current thread</li>
     *   </ul></li>  
     * </ul>
+    * The current thread seems to be valid for all platforms, 
+    * since no SWT lifecycle tasks are being performed w/ this call.
+    * Only GL task, which are independent from the SWT threading model.
+    *   
     * @see Platform#AWT_AVAILABLE
     * @see Platform#getOSType()
     */
-   private static void runInGLThread(final Runnable action) {
+   private void runInGLThread(final Runnable action) {
+      /**
       if(Platform.OSType.MACOS == Platform.OS_TYPE) {
           SWTAccessor.invoke(true, action);
       } else {
           Threading.invokeOnOpenGLThread(true, action);
-      }
+      } */
+      /**
+      if( !isDisposed() ) {
+          final Display d = getDisplay();
+          if( d.getThread() == Thread.currentThread() ) {
+              action.run();
+          } else {
+              d.syncExec(action);
+          }
+      } */
+      action.run();
+   }
+   
+   private void runOnEDTIfAvail(boolean wait, final Runnable action) {       
+       final Display d = isDisposed() ? null : getDisplay();
+       if( null == d || d.isDisposed() || d.getThread() == Thread.currentThread() ) {
+           action.run();
+       } else if(wait) {
+           d.syncExec(action);
+       } else {
+           d.asyncExec(action);
+       }
    }
 
+   @Override
+   public String toString() {
+       final GLDrawable _drawable = drawable;
+       final int dw = (null!=_drawable) ? _drawable.getWidth() : -1;
+       final int dh = (null!=_drawable) ? _drawable.getHeight() : -1;
+
+       return "SWT-GLCanvas[Realized "+isRealized()+
+               ",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+
+               ",\n\tFactory   "+getFactory()+
+               ",\n\thandle    0x"+Long.toHexString(getHandle())+
+               ",\n\tDrawable size "+dw+"x"+dh+
+               ",\n\tSWT size "+getWidth()+"x"+getHeight()+"]";
+   }
+   
    public static void main(final String[] args) {
        System.err.println(VersionUtil.getPlatformInfo());
        System.err.println(GlueGenVersion.getInstance());
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
index 26d2996..8de178e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java
@@ -165,6 +165,6 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl {
         };
 
     public boolean blockUntilDone(Thread thread) {
-        return ((Thread.currentThread() != thread) && !EventQueue.isDispatchThread());
+        return Thread.currentThread() != thread && !EventQueue.isDispatchThread();
     }
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
index 20ba27c..ac2b241 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java
@@ -41,7 +41,7 @@
 package com.jogamp.opengl.util;
 
 import javax.media.opengl.GLAutoDrawable;
-
+import javax.media.opengl.GLException;
 
 /** <P> An Animator can be attached to one or more {@link
     GLAutoDrawable}s to drive their display() methods in a loop. </P>
@@ -56,12 +56,8 @@ import javax.media.opengl.GLAutoDrawable;
  * so it is able to keep an application from terminating.<br>
  * Call {@link #stop() } to terminate the animation and it's execution thread.
  * </p>
-*/
-
-public class Animator extends AnimatorBase {
-    /** timeout in milliseconds, 15 frames @ 60Hz = 240ms, limiting {@link #finishLifecycleAction(Condition)} */
-    private static final long TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION = 15*16;
-    
+ */
+public class Animator extends AnimatorBase {    
     protected ThreadGroup threadGroup;
     private Runnable runnable;
     private boolean runAsFastAsPossible;
@@ -69,6 +65,9 @@ public class Animator extends AnimatorBase {
     protected boolean pauseIssued;
     protected volatile boolean stopIssued;
 
+    /**
+     * Creates a new, empty Animator.
+     */
     public Animator() {
         super();
         if(DEBUG) {
@@ -76,25 +75,38 @@ public class Animator extends AnimatorBase {
         }
     }
 
+    /** 
+     * Creates a new Animator w/ an associated ThreadGroup.
+     */
     public Animator(ThreadGroup tg) {
         super();
-        threadGroup = tg;
-
+        setThreadGroup(tg);
         if(DEBUG) {
             System.err.println("Animator created, ThreadGroup: "+threadGroup);
         }
     }
 
-    /** Creates a new Animator for a particular drawable. */
+    /** 
+     * Creates a new Animator for a particular drawable.
+     */
     public Animator(GLAutoDrawable drawable) {
         super();
         add(drawable);
+        if(DEBUG) {
+            System.err.println("Animator created, w/ "+drawable);
+        }
     }
 
-    /** Creates a new Animator for a particular drawable. */
+    /** 
+     * Creates a new Animator w/ an associated ThreadGroup for a particular drawable.
+     */
     public Animator(ThreadGroup tg, GLAutoDrawable drawable) {
-        this(tg);
+        super();
+        setThreadGroup(tg);
         add(drawable);
+        if(DEBUG) {
+            System.err.println("Animator created, ThreadGroup: "+threadGroup+" and "+drawable);
+        }
     }
 
     protected String getBaseName(String prefix) {
@@ -115,7 +127,7 @@ public class Animator extends AnimatorBase {
             stateSync.unlock();
         }
     }
-
+    
     private final void setIsAnimatingSynced(boolean v) {
         stateSync.lock();
         try {
@@ -127,28 +139,35 @@ public class Animator extends AnimatorBase {
 
     class MainLoop implements Runnable {
         public String toString() {
-            return "[started "+isStartedImpl()+", animating "+isAnimatingImpl()+", paused "+isPausedImpl()+", drawable "+drawables.size()+"]";
+            return "[started "+isStartedImpl()+", animating "+isAnimatingImpl()+", paused "+isPausedImpl()+", drawable "+drawables.size()+", drawablesEmpty "+drawablesEmpty+"]";
         }
 
         public void run() {
             try {
-                synchronized (Animator.this) {
-                    if(DEBUG) {
-                        System.err.println("Animator start:" + Thread.currentThread() + ": " + toString());
-                    }
-                    fpsCounter.resetFPSCounter();
-                    animThread = Thread.currentThread();
-                    setIsAnimatingSynced(false); // barrier
-                    Animator.this.notifyAll();
+                if(DEBUG) {
+                    System.err.println("Animator start on " + getThreadName() + ": " + toString());
                 }
+                fpsCounter.resetFPSCounter();
+                animThread = Thread.currentThread();
+                setIsAnimatingSynced(false); // barrier
+                // 'waitForStartedCondition' wake-up is handled below!
 
                 while (!stopIssued) {
                     synchronized (Animator.this) {
-                        // Don't consume CPU unless there is work to be done and not paused
+                        // Pause; Also don't consume CPU unless there is work to be done and not paused
+                        boolean ectCleared = false;
                         while (!stopIssued && (pauseIssued || drawablesEmpty)) {
+                            if( drawablesEmpty ) {
+                                pauseIssued = true;
+                            }
                             boolean wasPaused = pauseIssued;
                             if (DEBUG) {
-                                System.err.println("Animator pause:" + Thread.currentThread() + ": " + toString());
+                                System.err.println("Animator pause on " + animThread.getName() + ": " + toString());
+                            }
+                            if ( exclusiveContext && !drawablesEmpty && !ectCleared ) {
+                                ectCleared = true;
+                                setDrawablesExclCtxState(false);
+                                display(); // propagate exclusive change!
                             }
                             setIsAnimatingSynced(false); // barrier
                             Animator.this.notifyAll();
@@ -156,19 +175,21 @@ public class Animator extends AnimatorBase {
                                 Animator.this.wait();
                             } catch (InterruptedException e) {
                             }
-
                             if (wasPaused) {
                                 // resume from pause -> reset counter
                                 fpsCounter.resetFPSCounter();
                                 if (DEBUG) {
-                                    System.err.println("Animator resume:" + Thread.currentThread() + ": " + toString());
+                                    System.err.println("Animator resume on " + animThread.getName() + ": " + toString());
                                 }
                             }
                         }
                         if (!stopIssued && !isAnimating) {
-                            // resume from pause or drawablesEmpty,
+                            // Wakes up 'waitForStartedCondition' sync
+                            // - and - 
+                            // Resume from pause or drawablesEmpty,
                             // implies !pauseIssued and !drawablesEmpty
-                            setIsAnimatingSynced(true);
+                            setIsAnimatingSynced(true); // barrier
+                            setDrawablesExclCtxState(exclusiveContext);
                             Animator.this.notifyAll();
                         }
                     } // sync Animator.this
@@ -181,9 +202,13 @@ public class Animator extends AnimatorBase {
                     }
                 }
             } finally {
+                if( exclusiveContext && !drawablesEmpty ) {
+                    setDrawablesExclCtxState(false);
+                    display(); // propagate exclusive change!
+                }
                 synchronized (Animator.this) {
                     if(DEBUG) {
-                        System.err.println("Animator stop " + Thread.currentThread() + ": " + toString());
+                        System.err.println("Animator stop on " + animThread.getName() + ": " + toString());
                     }
                     stopIssued = false;
                     pauseIssued = false;
@@ -195,18 +220,6 @@ public class Animator extends AnimatorBase {
         }
     }
 
-    private final boolean isStartedImpl() {
-        return animThread != null ;
-    }
-    public final boolean isStarted() {
-        stateSync.lock();
-        try {
-            return animThread != null ;
-        } finally {
-            stateSync.unlock();
-        }
-    }
-
     private final boolean isAnimatingImpl() {
         return animThread != null && isAnimating ;
     }
@@ -231,39 +244,19 @@ public class Animator extends AnimatorBase {
         }
     }
 
-    interface Condition {
-        /**
-         * @return true if branching (cont waiting, action), otherwise false
-         */
-        boolean result();
-    }
-
-    private synchronized void finishLifecycleAction(Condition condition) {
-        // It's hard to tell whether the thread which changes the lifecycle has
-        // dependencies on the Animator's internal thread. Currently we
-        // use a couple of heuristics to determine whether we should do
-        // the blocking wait().
-        final boolean blocking = impl.blockUntilDone(animThread);
-        long remaining = blocking ? TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION : 0;
-        while (remaining>0 && condition.result()) {
-            long td = System.currentTimeMillis();
-            try {
-                wait(remaining);
-            } catch (InterruptedException ie) {  }
-            remaining -= (System.currentTimeMillis() - td) ;
-        }
-        if(DEBUG) {
-            if(remaining<0) {
-                System.err.println("finishLifecycleAction(" + condition.getClass().getName() + "): ++++++ timeout reached ++++++ " + Thread.currentThread().getName());
-            }
-            System.err.println("finishLifecycleAction(" + condition.getClass().getName() + "): finished "+
-                    "- blocking "+blocking+
-                    ", waited " + (blocking ? ( TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION - remaining ) : 0 ) + "/" + TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION + 
-                    ", started: " + isStartedImpl() +", animating: " + isAnimatingImpl() +
-                    ", paused: " + isPausedImpl() + ", drawables " + drawables.size() + " - " + Thread.currentThread().getName());
+    /**
+     * Set a {@link ThreadGroup} for the {@link #getThread() animation thread}.
+     * 
+     * @param tg the {@link ThreadGroup}
+     * @throws GLException if the animator has already been started
+     */
+    public synchronized void setThreadGroup(ThreadGroup tg) throws GLException {
+        if ( isStartedImpl() ) {
+            throw new GLException("Animator already started.");
         }
+        threadGroup = tg;
     }
-
+    
     public synchronized boolean start() {
         if ( isStartedImpl() ) {
             return false;
@@ -272,7 +265,7 @@ public class Animator extends AnimatorBase {
             runnable = new MainLoop();
         }
         fpsCounter.resetFPSCounter();
-        String threadName = Thread.currentThread().getName()+"-"+baseName;
+        String threadName = getThreadName()+"-"+baseName;
         Thread thread;
         if(null==threadGroup) {
             thread = new Thread(runnable, threadName);
@@ -285,74 +278,48 @@ public class Animator extends AnimatorBase {
             System.err.println("Animator "+ct.getName()+"[daemon "+ct.isDaemon()+"]: starting "+thread.getName()+"[daemon "+thread.isDaemon()+"]");
         }
         thread.start();
-        finishLifecycleAction(waitForStartedCondition);
-        return true;
+        return finishLifecycleAction(waitForStartedCondition, 0);
     }
-
-    private class WaitForStartedCondition implements Condition {
-        public boolean result() {
+    private final Condition waitForStartedCondition = new Condition() {
+        public boolean eval() {
             return !isStartedImpl() || (!drawablesEmpty && !isAnimating) ;
-        }
-    }
-    Condition waitForStartedCondition = new WaitForStartedCondition();
+        } };    
 
     public synchronized boolean stop() {
         if ( !isStartedImpl() ) {
             return false;
         }
         stopIssued = true;
-        notifyAll();
-        finishLifecycleAction(waitForStoppedCondition);
-        return true;
+        return finishLifecycleAction(waitForStoppedCondition, 0);
     }
-    private class WaitForStoppedCondition implements Condition {
-        public boolean result() {
+    private final Condition waitForStoppedCondition = new Condition() {
+        public boolean eval() {
             return isStartedImpl();
-        }
-    }
-    Condition waitForStoppedCondition = new WaitForStoppedCondition();
+        } };
 
     public synchronized boolean pause() {
         if ( !isStartedImpl() || pauseIssued ) {
             return false;
         }
-        stateSync.lock();
-        try {
-            pauseIssued = true;
-        } finally {
-            stateSync.unlock();
-        }
-        notifyAll();
-        finishLifecycleAction(waitForPausedCondition);
-        return true;
+        pauseIssued = true;
+        return finishLifecycleAction(waitForPausedCondition, 0);
     }
-    private class WaitForPausedCondition implements Condition {
-        public boolean result() {
+    private final Condition waitForPausedCondition = new Condition() {
+        public boolean eval() {
             // end waiting if stopped as well
-            return isAnimating && isStartedImpl();
-        }
-    }
-    Condition waitForPausedCondition = new WaitForPausedCondition();
+            return isStartedImpl() && isAnimating;
+        } };
 
     public synchronized boolean resume() {
         if ( !isStartedImpl() || !pauseIssued ) {
             return false;
         }
-        stateSync.lock();
-        try {
-            pauseIssued = false;
-        } finally {
-            stateSync.unlock();
-        }
-        notifyAll();
-        finishLifecycleAction(waitForResumeCondition);
-        return true;
+        pauseIssued = false;
+        return finishLifecycleAction(waitForResumeCondition, 0);
     }
-    private class WaitForResumeCondition implements Condition {
-        public boolean result() {
+    private final Condition waitForResumeCondition = new Condition() {
+        public boolean eval() {
             // end waiting if stopped as well
-            return !drawablesEmpty && !isAnimating && isStartedImpl();
-        }
-    }
-    Condition waitForResumeCondition = new WaitForResumeCondition();
+            return isStartedImpl() && ( !drawablesEmpty && !isAnimating || drawablesEmpty && !pauseIssued ) ;
+        } };
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
index 46fc1d9..ef92100 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java
@@ -38,6 +38,7 @@ import java.util.ArrayList;
 
 import javax.media.opengl.GLAnimatorControl;
 import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLException;
 import javax.media.opengl.GLProfile;
 
 /**
@@ -51,69 +52,178 @@ import javax.media.opengl.GLProfile;
  */
 public abstract class AnimatorBase implements GLAnimatorControl {
     protected static final boolean DEBUG = Debug.debug("Animator");
-
-    private static int animatorCount = 0;
-
+    
+    /** A 1s timeout while waiting for a native action response, limiting {@link #finishLifecycleAction(Condition, long)} */
+    protected static final long TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION = 1000;
+    
+    protected static final long POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION = 32; // 2 frames @ 60Hz
+    
+    /**
+     * If present in <code>modeBits</code> field and 
+     * {@link GLProfile#isAWTAvailable() AWT is available},
+     * implementation is aware of the AWT EDT, otherwise not.
+     * <p>
+     * This is the <i>default</i>.
+     * </p>
+     * @see #setModeBits(boolean, int)
+     */
+    public static final int MODE_EXPECT_AWT_RENDERING_THREAD = 1 << 0; 
+    
     public interface AnimatorImpl {
         void display(ArrayList<GLAutoDrawable> drawables, boolean ignoreExceptions, boolean printExceptions);
         boolean blockUntilDone(Thread thread);
     }
 
-    protected ArrayList<GLAutoDrawable> drawables = new ArrayList<GLAutoDrawable>();
-    protected boolean drawablesEmpty;
+    protected int modeBits;
     protected AnimatorImpl impl;
     protected String baseName;
+    
+    protected ArrayList<GLAutoDrawable> drawables = new ArrayList<GLAutoDrawable>();
+    protected boolean drawablesEmpty;
     protected Thread animThread;
     protected boolean ignoreExceptions;
     protected boolean printExceptions;
+    protected boolean exclusiveContext;
+    protected Thread userExclusiveContextThread;
     protected FPSCounterImpl fpsCounter = new FPSCounterImpl();    
     protected RecursiveLock stateSync = LockFactory.createRecursiveLock();
-
-    /** Creates a new, empty Animator. */
-    public AnimatorBase() {
-        if(GLProfile.isAWTAvailable()) {
+    
+    private final static Class<?> awtAnimatorImplClazz;    
+    static {
+        GLProfile.initSingleton();
+        if( GLProfile.isAWTAvailable() ) {
+            Class<?> clazz;
             try {
-                impl = (AnimatorImpl) Class.forName("com.jogamp.opengl.util.AWTAnimatorImpl").newInstance();
-                baseName = "AWTAnimator";
-            } catch (Exception e) { e.printStackTrace(); }
-        }
-        if(null==impl) {
-            impl = new DefaultAnimatorImpl();
-            baseName = "Animator";
-        }
-        synchronized (Animator.class) {
-            animatorCount++;
-            baseName = baseName.concat("-"+animatorCount);
-            drawablesEmpty = true;
+                clazz = Class.forName("com.jogamp.opengl.util.AWTAnimatorImpl");
+            } catch (Exception e) {
+                clazz = null;                
+            }
+            awtAnimatorImplClazz =  clazz;
+        } else {
+            awtAnimatorImplClazz = null;
         }
     }
 
+    /**
+     * Creates a new, empty Animator instance 
+     * while expecting an AWT rendering thread if AWT is available.
+     * 
+     * @see GLProfile#isAWTAvailable()
+     */
+    public AnimatorBase() {
+        modeBits = MODE_EXPECT_AWT_RENDERING_THREAD; // default!        
+        drawablesEmpty = true;
+    }
+    
+    private static final boolean useAWTAnimatorImpl(int modeBits) {
+        return 0 != ( MODE_EXPECT_AWT_RENDERING_THREAD & modeBits ) && null != awtAnimatorImplClazz;
+    }
+    
+    /**
+     * Initializes implementation details post setup,
+     * invoked at {@link #add(GLAutoDrawable)}, {@link #start()}, ..
+     * <p>
+     * Operation is a NOP if <code>force</code> is <code>false</code> 
+     * and this instance is already initialized.
+     * </p> 
+     * 
+     * @throws GLException if Animator is {@link #isStarted()}  
+     */
+    protected synchronized void initImpl(boolean force) {
+        if( force || null == impl ) {
+            if( useAWTAnimatorImpl( modeBits ) ) {
+                try {
+                    impl = (AnimatorImpl) awtAnimatorImplClazz.newInstance();
+                    baseName = getBaseName("AWT");
+                } catch (Exception e) { e.printStackTrace(); }
+            }
+            if( null == impl ) {
+                impl = new DefaultAnimatorImpl();
+                baseName = getBaseName("");
+            }
+            if(DEBUG) {
+                System.err.println("Animator.initImpl: baseName "+baseName+", implClazz "+impl.getClass().getName()+" - "+toString()+" - "+getThreadName());
+            }
+        }
+    }
     protected abstract String getBaseName(String prefix);
 
-    public synchronized void add(GLAutoDrawable drawable) {
+    /**
+     * Enables or disables the given <code>bitValues</code>
+     * in this Animators <code>modeBits</code>.
+     * @param enable
+     * @param bitValues
+     * 
+     * @throws GLException if Animator is {@link #isStarted()} and {@link #MODE_EXPECT_AWT_RENDERING_THREAD} about to change 
+     * @see AnimatorBase#MODE_EXPECT_AWT_RENDERING_THREAD
+     */
+    public synchronized void setModeBits(boolean enable, int bitValues) throws GLException {
+        final int _oldModeBits = modeBits;
+        if(enable) {
+            modeBits |=  bitValues;
+        } else {
+            modeBits &= ~bitValues;
+        }
+        if( useAWTAnimatorImpl( _oldModeBits ) != useAWTAnimatorImpl( modeBits ) ) {
+            if( isStarted() ) {
+                throw new GLException("Animator already started");
+            }
+            initImpl(true);
+        }
+    }
+    public synchronized int getModeBits() { return modeBits; }
+    
+    
+    @Override
+    public synchronized void add(final GLAutoDrawable drawable) {
         if(DEBUG) {
-            System.err.println("Animator add: "+drawable.hashCode()+" - "+Thread.currentThread().getName());
+            System.err.println("Animator add: 0x"+Integer.toHexString(drawable.hashCode())+" - "+toString()+" - "+getThreadName());
+        }
+        if( drawables.contains(drawable) ) {
+            throw new IllegalArgumentException("Drawable already added to animator: "+this+", "+drawable);
+        }
+        initImpl(false);
+        pause();
+        if( isStarted() ) {
+            drawable.setExclusiveContextThread( exclusiveContext ? getExclusiveContextThread() : null ); // if already running ..
         }
-        boolean paused = pause();
         drawables.add(drawable);
         drawablesEmpty = drawables.size() == 0;
         drawable.setAnimator(this);
-        if(paused) {
+        if( isPaused() ) { // either paused by pause() above, or if previously drawablesEmpty==true 
             resume();
         }
-        if(impl.blockUntilDone(animThread)) {
-            while(isStarted() && !isPaused() && !isAnimating()) {
-                try {
-                    wait();
-                } catch (InterruptedException ie) { }
-            }
+        final Condition waitForAnimatingAndECTCondition = new Condition() {
+            public boolean eval() {
+                final Thread dect = drawable.getExclusiveContextThread();
+                return isStarted() && !isPaused() && !isAnimating() && ( exclusiveContext && null == dect || !exclusiveContext && null != dect );
+            } };
+        final boolean res = finishLifecycleAction(waitForAnimatingAndECTCondition, 0);
+        if(DEBUG) {
+            System.err.println("Animator add: Wait for Animating/ECT OK: "+res+", "+toString()+", dect "+drawable.getExclusiveContextThread());
         }
         notifyAll();
     }
 
-    public synchronized void remove(GLAutoDrawable drawable) {
+    @Override
+    public synchronized void remove(final GLAutoDrawable drawable) {
         if(DEBUG) {
-            System.err.println("Animator remove: "+drawable.hashCode()+" - "+Thread.currentThread().getName() + ": "+toString());
+            System.err.println("Animator remove: 0x"+Integer.toHexString(drawable.hashCode())+" - "+toString()+" - "+getThreadName());
+        }
+        if( !drawables.contains(drawable) ) {
+            throw new IllegalArgumentException("Drawable not added to animator: "+this+", "+drawable);
+        }
+        
+        if( exclusiveContext && isAnimating() ) {
+            drawable.setExclusiveContextThread( null );
+            final Condition waitForNullECTCondition = new Condition() {
+                public boolean eval() {
+                    return null != drawable.getExclusiveContextThread();
+                } };
+            final boolean res = finishLifecycleAction(waitForNullECTCondition, POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION);
+            if(DEBUG) {
+                System.err.println("Animator remove: Wait for Null-ECT OK: "+res+", "+toString()+", dect "+drawable.getExclusiveContextThread());
+            }
         }
 
         boolean paused = pause();
@@ -123,14 +233,202 @@ public abstract class AnimatorBase implements GLAnimatorControl {
         if(paused) {
             resume();
         }
-        if(impl.blockUntilDone(animThread)) {
-            while(isStarted() && drawablesEmpty && isAnimating()) {
+        final boolean res = finishLifecycleAction(waitForNotAnimatingIfEmptyCondition, 0);
+        if(DEBUG) {
+            System.err.println("Animator remove: Wait for !Animating-if-empty OK: "+res+", "+toString());
+        }
+        notifyAll();
+    }
+    private final Condition waitForNotAnimatingIfEmptyCondition = new Condition() {
+        public boolean eval() {
+            return isStarted() && drawablesEmpty && isAnimating();
+        } };
+
+    
+    /**
+     * Dedicate all {@link GLAutoDrawable}'s context to the given exclusive context thread.
+     * <p>
+     * The given thread will be exclusive to all {@link GLAutoDrawable}'s context while {@link #isAnimating()}.
+     * </p>
+     * <p>
+     * If already started and disabling, method waits
+     * until change is propagated to all {@link GLAutoDrawable} if not 
+     * called from the animator thread or {@link #getExclusiveContextThread() exclusive context thread}.
+     * </p>
+     * <p>
+     * Note: Utilizing this feature w/ AWT could lead to an AWT-EDT deadlock, depending on the AWT implementation.
+     * Hence it is advised not to use it with native AWT GLAutoDrawable like GLCanvas.
+     * </p>
+     * 
+     * @param enable
+     * @return previous value
+     * @see #setExclusiveContext(boolean)
+     * @see #getExclusiveContextThread()
+     * @see #isExclusiveContextEnabled()
+     */
+    // @Override
+    public final Thread setExclusiveContext(Thread t) {
+        final Thread old;
+        final boolean enable = null != t;
+        stateSync.lock();
+        try {
+            old = userExclusiveContextThread;            
+            if( enable && t != animThread ) { // disable: will be cleared at end after propagation && filter out own animThread usae
+                userExclusiveContextThread=t;
+            }
+        } finally {
+            stateSync.unlock();
+        }
+        setExclusiveContext(enable);
+        return old;
+    }
+    
+    /**
+     * Dedicate all {@link GLAutoDrawable}'s context to this animator thread.
+     * <p>
+     * The given thread will be exclusive to all {@link GLAutoDrawable}'s context while {@link #isAnimating()}.
+     * </p>
+     * <p>
+     * If already started and disabling, method waits
+     * until change is propagated to all {@link GLAutoDrawable} if not 
+     * called from the animator thread or {@link #getExclusiveContextThread() exclusive context thread}.
+     * </p>
+     * <p>
+     * Note: Utilizing this feature w/ AWT could lead to an AWT-EDT deadlock, depending on the AWT implementation.
+     * Hence it is advised not to use it with native AWT GLAutoDrawable like GLCanvas.
+     * </p>
+     * 
+     * @param enable
+     * @return previous value
+     * @see #setExclusiveContext(Thread)
+     * @see #getExclusiveContextThread()
+     * @see #isExclusiveContextEnabled()
+     */
+    // @Override
+    public final boolean setExclusiveContext(boolean enable) {
+        final boolean propagateState;
+        final boolean oldExclusiveContext;
+        final Thread _exclusiveContextThread;
+        synchronized (AnimatorBase.this) {
+            propagateState = isStarted() && !drawablesEmpty;
+            _exclusiveContextThread = userExclusiveContextThread;
+            oldExclusiveContext = exclusiveContext;
+            exclusiveContext = enable;
+            if(DEBUG) {
+                System.err.println("AnimatorBase.setExclusiveContextThread: "+oldExclusiveContext+" -> "+exclusiveContext+", propagateState "+propagateState+", "+this);
+            }
+        }
+        final Thread dECT = enable ? ( null != userExclusiveContextThread ? userExclusiveContextThread : animThread ) : null ;
+        if( propagateState ) {
+            setDrawablesExclCtxState(enable);
+            if( !enable ) {
+                if( Thread.currentThread() == getThread() || Thread.currentThread() == _exclusiveContextThread ) {
+                    display();
+                } else {
+                    final boolean resumed = isAnimating() ? false : resume();
+                    int counter = 10;
+                    while( 0<counter && isAnimating() && !validateDrawablesExclCtxState(dECT) ) {
+                        try {
+                            Thread.sleep(20);
+                        } catch (InterruptedException e) { }
+                        counter--;
+                    }
+                    if(resumed) {
+                        pause();
+                    }
+                }
+                stateSync.lock();
                 try {
-                    wait();
-                } catch (InterruptedException ie) { }
+                    userExclusiveContextThread=null;
+                } finally {
+                    stateSync.unlock();
+                }
             }
         }
-        notifyAll();
+        if(DEBUG) {
+            System.err.println("AnimatorBase.setExclusiveContextThread: all-GLAD Ok: "+validateDrawablesExclCtxState(dECT)+", "+this);
+        }
+        return oldExclusiveContext;
+    }    
+    
+    /**
+     * Returns <code>true</code>, if the exclusive context thread is enabled, otherwise <code>false</code>.
+     * 
+     * @see #setExclusiveContext(boolean)
+     * @see #setExclusiveContext(Thread)
+     */
+    // @Override
+    public final boolean isExclusiveContextEnabled() { 
+        stateSync.lock();
+        try {
+            return exclusiveContext; 
+        } finally {
+            stateSync.unlock();
+        }
+    }
+    
+    /**
+     * Returns the exclusive context thread if {@link #isExclusiveContextEnabled()} and {@link #isStarted()}, otherwise <code>null</code>.
+     * <p>
+     * If exclusive context is enabled via {@link #setExclusiveContext(boolean)}
+     * the {@link #getThread() animator thread} is returned if above conditions are met.
+     * </p>
+     * <p>
+     * If exclusive context is enabled via {@link #setExclusiveContext(Thread)}
+     * the user passed thread is returned if above conditions are met.
+     * </p>
+     * @see #setExclusiveContext(boolean)
+     * @see #setExclusiveContext(Thread)
+     */
+    // @Override
+    public final Thread getExclusiveContextThread() { 
+        stateSync.lock();
+        try {
+            return ( isStartedImpl() && exclusiveContext ) ? ( null != userExclusiveContextThread ? userExclusiveContextThread : animThread ) : null ;
+        } finally {
+            stateSync.unlock();
+        }
+    }
+    
+    /**
+     * Should be called at {@link #start()} and {@link #stop()}
+     * from within the animator thread.
+     * <p>
+     * At {@link #stop()} an additional {@link #display()} call shall be issued
+     * to allow propagation of releasing the exclusive thread.
+     * </p>
+     */
+    protected final synchronized void setDrawablesExclCtxState(boolean enable) {
+        if(DEBUG) {
+            System.err.println("AnimatorBase.setExclusiveContextImpl exlusive "+exclusiveContext+": Enable "+enable+" for "+this+" - "+Thread.currentThread());
+            // Thread.dumpStack();
+        }
+        final Thread ect = getExclusiveContextThread();
+        for (int i=0; i<drawables.size(); i++) {
+            try {
+                drawables.get(i).setExclusiveContextThread( enable ? ect : null );
+            } catch (RuntimeException e) { 
+                e.printStackTrace();
+            }
+        }
+    }
+    protected final boolean validateDrawablesExclCtxState(Thread expected) {
+        for (int i=0; i<drawables.size(); i++) {
+            if( expected != drawables.get(i).getExclusiveContextThread() ) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    @Override
+    public final Thread getThread() {
+        stateSync.lock();
+        try {
+            return animThread;
+        } finally {
+            stateSync.unlock();
+        }
     }
 
     /** Called every frame to cause redrawing of all of the
@@ -143,55 +441,56 @@ public abstract class AnimatorBase implements GLAnimatorControl {
         fpsCounter.tickFPS();
     }
 
+    @Override
     public final void setUpdateFPSFrames(int frames, PrintStream out) {
         fpsCounter.setUpdateFPSFrames(frames, out);
     }
     
+    @Override
     public final void resetFPSCounter() {
         fpsCounter.resetFPSCounter();
     }
 
+    @Override
     public final int getUpdateFPSFrames() {
         return fpsCounter.getUpdateFPSFrames();
     }
     
+    @Override
     public final long getFPSStartTime()   {
         return fpsCounter.getFPSStartTime();
     }
 
+    @Override
     public final long getLastFPSUpdateTime() {
         return fpsCounter.getLastFPSUpdateTime();
     }
 
+    @Override
     public final long getLastFPSPeriod() {
         return fpsCounter.getLastFPSPeriod();
     }
     
+    @Override
     public final float getLastFPS() {
         return fpsCounter.getLastFPS();
     }
     
+    @Override
     public final int getTotalFPSFrames() {
         return fpsCounter.getTotalFPSFrames();
     }
 
+    @Override
     public final long getTotalFPSDuration() {
         return fpsCounter.getTotalFPSDuration();
     }
     
+    @Override
     public final float getTotalFPS() {
         return fpsCounter.getTotalFPS();
     }        
 
-    public final Thread getThread() {
-        stateSync.lock();
-        try {
-            return animThread;
-        } finally {
-            stateSync.unlock();
-        }
-    }
-
     /** Sets a flag causing this Animator to ignore exceptions produced
     while redrawing the drawables. By default this flag is set to
     false, causing any exception thrown to halt the Animator. */
@@ -207,7 +506,80 @@ public abstract class AnimatorBase implements GLAnimatorControl {
         this.printExceptions = printExceptions;
     }
 
+    protected interface Condition {
+        /**
+         * @return true if branching (continue waiting, action), otherwise false
+         */
+        boolean eval();
+    }
+    
+    /**
+     * @param waitCondition method will wait until TO is reached or {@link Condition#eval() waitCondition.eval()} returns <code>false</code>.
+     * @param pollPeriod if <code>0</code>, method will wait until TO is reached or being notified. 
+     *                   if > <code>0</code>, method will wait for the given <code>pollPeriod</code> in milliseconds.
+     * @return <code>true</code> if {@link Condition#eval() waitCondition.eval()} returned <code>false</code>, otherwise <code>false</code>.
+     */
+    protected synchronized boolean finishLifecycleAction(Condition waitCondition, long pollPeriod) {
+        // It's hard to tell whether the thread which changes the lifecycle has
+        // dependencies on the Animator's internal thread. Currently we
+        // use a couple of heuristics to determine whether we should do
+        // the blocking wait().
+        initImpl(false);
+        final boolean blocking = impl.blockUntilDone(animThread);
+        long remaining = blocking ? TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION : 0;
+        if( 0 >= pollPeriod ) {
+            pollPeriod = remaining;
+        }
+        boolean nok = waitCondition.eval();
+        while ( nok && remaining>0 ) {
+            final long t1 = System.currentTimeMillis();
+            if( pollPeriod > remaining ) { pollPeriod = remaining; }
+            notifyAll();
+            try {
+                wait(pollPeriod);
+            } catch (InterruptedException ie) {  }
+            remaining -= System.currentTimeMillis() - t1 ;
+            nok = waitCondition.eval();
+        }
+        if(DEBUG || blocking && nok) { // Info only if DEBUG or ( blocking && not-ok ) ; !blocking possible if AWT
+            if( remaining<=0 && nok ) {
+                System.err.println("finishLifecycleAction(" + waitCondition.getClass().getName() + "): ++++++ timeout reached ++++++ " + getThreadName());
+            }
+            stateSync.lock(); // avoid too many lock/unlock ops 
+            try {
+                System.err.println("finishLifecycleAction(" + waitCondition.getClass().getName() + "): OK "+(!nok)+
+                        "- pollPeriod "+pollPeriod+", blocking "+blocking+
+                        ", waited " + (blocking ? ( TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION - remaining ) : 0 ) + "/" + TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION +                         
+                        " - " + getThreadName());
+                System.err.println(" - "+toString());
+            } finally {
+                stateSync.unlock();
+            }
+            if(nok) {
+                Thread.dumpStack();
+            }
+        }
+        return !nok;
+    }
+
+    protected final boolean isStartedImpl() {
+        return animThread != null ;
+    }
+    @Override
+    public boolean isStarted() {
+        stateSync.lock();
+        try {
+            return animThread != null ;
+        } finally {
+            stateSync.unlock();
+        }
+    }
+
+    protected static String getThreadName() { return Thread.currentThread().getName(); }
+
     public String toString() {
-        return getClass().getName()+"[started "+isStarted()+", animating "+isAnimating()+", paused "+isPaused()+", drawable "+drawables.size()+", totals[dt "+getTotalFPSDuration()+", frames "+getTotalFPSFrames()+", fps "+getTotalFPS()+"]]";
+        return getClass().getName()+"[started "+isStarted()+", animating "+isAnimating()+", paused "+isPaused()+", drawable "+drawables.size()+
+               ", totals[dt "+getTotalFPSDuration()+", frames "+getTotalFPSFrames()+", fps "+getTotalFPS()+
+               "], modeBits "+modeBits+", init'ed "+(null!=impl)+", animThread "+getThread()+", exclCtxThread "+exclusiveContext+"("+getExclusiveContextThread()+")]";
     }
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
index 23b0845..bbd2951 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java
@@ -61,6 +61,6 @@ class DefaultAnimatorImpl implements AnimatorBase.AnimatorImpl {
     }
 
     public boolean blockUntilDone(Thread thread) {
-        return (Thread.currentThread() != thread);
+        return Thread.currentThread() != thread;
     }
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
index f7fc581..7613efe 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java
@@ -39,18 +39,30 @@
  */
 package com.jogamp.opengl.util;
 
-import java.util.*;
-import javax.media.opengl.*;
+import java.util.Timer;
+import java.util.TimerTask;
 
-/** An Animator subclass which attempts to achieve a target
-frames-per-second rate to avoid using all CPU time. The target FPS
-is only an estimate and is not guaranteed. */
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLException;
+
+/** 
+ * An Animator subclass which attempts to achieve a target
+ * frames-per-second rate to avoid using all CPU time. The target FPS
+ * is only an estimate and is not guaranteed. 
+ * <p>
+ * The Animator execution thread does not run as a daemon thread,
+ * so it is able to keep an application from terminating.<br>
+ * Call {@link #stop() } to terminate the animation and it's execution thread.
+ * </p>
+ */
 public class FPSAnimator extends AnimatorBase {
     private Timer timer = null;
-    private TimerTask task = null;
+    private MainTask task = null;
     private int fps;
     private boolean scheduleAtFixedRate;
-    private volatile boolean shouldRun;
+    private boolean isAnimating;         // MainTask feedback
+    private volatile boolean shouldRun;  // MainTask trigger
+    private volatile boolean shouldStop; // MainTask trigger
 
     protected String getBaseName(String prefix) {
         return "FPS" + prefix + "Animator" ;
@@ -81,6 +93,7 @@ public class FPSAnimator extends AnimatorBase {
     value, an initial drawable to animate, and a flag indicating
     whether to use fixed-rate scheduling. */
     public FPSAnimator(GLAutoDrawable drawable, int fps, boolean scheduleAtFixedRate) {
+        super();
         this.fps = fps;
         if (drawable != null) {
             add(drawable);
@@ -88,131 +101,260 @@ public class FPSAnimator extends AnimatorBase {
         this.scheduleAtFixedRate = scheduleAtFixedRate;
     }
 
-    public final boolean isStarted() {
-        stateSync.lock();
-        try {
-            return (timer != null);
-        } finally {
-            stateSync.unlock();
+    /**
+     * @param fps
+     * @throws GLException if the animator has already been started
+     */
+    public final synchronized void setFPS(int fps) throws GLException { 
+        if ( isStartedImpl() ) {
+            throw new GLException("Animator already started.");
         }
+        this.fps = fps; 
     }
+    public final int getFPS() { return fps; }
+    
+    class MainTask extends TimerTask {
+        private boolean justStarted;
+        private boolean alreadyStopped;
+        private boolean alreadyPaused;
+        
+        public MainTask() {
+        }
+        
+        public void start(Timer timer) {
+            fpsCounter.resetFPSCounter();
+            shouldRun = true;
+            shouldStop = false;
+            
+            justStarted = true;
+            alreadyStopped = false;
+            alreadyPaused = false;
 
+            final long period = 0 < fps ? (long) (1000.0f / (float) fps) : 1; // 0 -> 1: IllegalArgumentException: Non-positive period         
+            if (scheduleAtFixedRate) {
+                timer.scheduleAtFixedRate(this, 0, period);
+            } else {
+                timer.schedule(this, 0, period);
+            }
+        }
+        
+        public boolean isActive() { return !alreadyStopped && !alreadyPaused; }
+        
+        public String toString() {
+            return "Task[thread "+animThread+", stopped "+alreadyStopped+", paused "+alreadyPaused+" shouldRun "+shouldRun+", shouldStop "+shouldStop+" -- started "+isStartedImpl()+", animating "+isAnimatingImpl()+", paused "+isPausedImpl()+", drawable "+drawables.size()+", drawablesEmpty "+drawablesEmpty+"]";
+        }
+                    
+        public void run() {
+            if( justStarted ) {
+                justStarted = false;
+                synchronized (FPSAnimator.this) {
+                    animThread = Thread.currentThread();
+                    if(DEBUG) {
+                        System.err.println("FPSAnimator start/resume:" + Thread.currentThread() + ": " + toString());
+                    }
+                    isAnimating = true;
+                    if( drawablesEmpty ) {
+                        shouldRun = false; // isAnimating:=false @ pause below
+                    } else {
+                        shouldRun = true;
+                        setDrawablesExclCtxState(exclusiveContext);
+                        FPSAnimator.this.notifyAll();
+                    }
+                    System.err.println("FPSAnimator P1:" + Thread.currentThread() + ": " + toString());
+                }
+            }
+            if( shouldRun ) {
+                display();
+            } else if( shouldStop ) { // STOP
+                System.err.println("FPSAnimator P4: "+alreadyStopped+", "+ Thread.currentThread() + ": " + toString());
+                this.cancel();                
+                
+                if( !alreadyStopped ) {
+                    alreadyStopped = true;
+                    if( exclusiveContext && !drawablesEmpty ) {
+                        setDrawablesExclCtxState(false);
+                        display(); // propagate exclusive change!
+                    }
+                    synchronized (FPSAnimator.this) {
+                        if(DEBUG) {
+                            System.err.println("FPSAnimator stop " + Thread.currentThread() + ": " + toString());
+                        }
+                        animThread = null;
+                        isAnimating = false;
+                        FPSAnimator.this.notifyAll();
+                    }
+                }
+            } else { 
+                System.err.println("FPSAnimator P5: "+alreadyPaused+", "+ Thread.currentThread() + ": " + toString());
+                this.cancel();
+                
+                if( !alreadyPaused ) { // PAUSE
+                    alreadyPaused = true;
+                    if( exclusiveContext && !drawablesEmpty ) {
+                        setDrawablesExclCtxState(false);
+                        display(); // propagate exclusive change!
+                    }
+                    synchronized (FPSAnimator.this) {                        
+                        if(DEBUG) {
+                            System.err.println("FPSAnimator pause " + Thread.currentThread() + ": " + toString());
+                        }
+                        isAnimating = false;
+                        FPSAnimator.this.notifyAll();
+                    }    
+                }
+            }
+        }
+    }
+    private final boolean isAnimatingImpl() {
+        return animThread != null && isAnimating ;
+    }
     public final boolean isAnimating() {
         stateSync.lock();
         try {
-            return (timer != null) && (task != null);
+            return animThread != null && isAnimating ;
         } finally {
             stateSync.unlock();
         }
     }
 
+    private final boolean isPausedImpl() {
+        return animThread != null && ( !shouldRun && !shouldStop ) ;
+    }
     public final boolean isPaused() {
         stateSync.lock();
         try {
-            return (timer != null) && (task == null);
+            return animThread != null && ( !shouldRun && !shouldStop ) ;
         } finally {
             stateSync.unlock();
         }
     }
 
-    private void startTask() {
-        if(null != task) {
-            return;
-        }
-        long delay = (long) (1000.0f / (float) fps);
-        task = new TimerTask() {
-            public void run() {
-                if(FPSAnimator.this.shouldRun) {
-                    FPSAnimator.this.animThread = Thread.currentThread();
-                    // display impl. uses synchronized block on the animator instance
-                    display();
-                }
-            }
-        };
-
-        fpsCounter.resetFPSCounter();
-        shouldRun = true;
-
-        if (scheduleAtFixedRate) {
-            timer.scheduleAtFixedRate(task, 0, delay);
-        } else {
-            timer.schedule(task, 0, delay);
-        }
-    }
-
-    public synchronized boolean  start() {
-        if (timer != null) {
+    static int timerNo = 0;
+    
+    public synchronized boolean start() {
+        if ( null != timer || null != task || isStartedImpl() ) {
             return false;
         }
-        stateSync.lock();
-        try {
-            timer = new Timer();
-            startTask();
-        } finally {
-            stateSync.unlock();
+        timer = new Timer( getThreadName()+"-"+baseName+"-Timer"+(timerNo++) );
+        task = new MainTask();
+        if(DEBUG) {
+            System.err.println("FPSAnimator.start() START: "+task+", "+ Thread.currentThread() + ": " + toString());
+        }
+        task.start(timer);
+        
+        final boolean res = finishLifecycleAction( drawablesEmpty ? waitForStartedEmptyCondition : waitForStartedAddedCondition, 
+                                                   POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION);
+        if(DEBUG) {
+            System.err.println("FPSAnimator.start() END: "+task+", "+ Thread.currentThread() + ": " + toString());
         }
-        return true;
+        if( drawablesEmpty ) {
+            task.cancel();
+            task = null;
+        }
+        return res;
     }
+    private final Condition waitForStartedAddedCondition = new Condition() {
+        public boolean eval() {
+            return !isStartedImpl() || !isAnimating ;
+        } };    
+    private final Condition waitForStartedEmptyCondition = new Condition() {
+        public boolean eval() {
+            return !isStartedImpl() || isAnimating ;
+        } };    
 
     /** Stops this FPSAnimator. Due to the implementation of the
     FPSAnimator it is not guaranteed that the FPSAnimator will be
     completely stopped by the time this method returns. */
     public synchronized boolean stop() {
-        if (timer == null) {
+        if ( null == timer || !isStartedImpl() ) {
             return false;
+        }        
+        if(DEBUG) {
+            System.err.println("FPSAnimator.stop() START: "+task+", "+ Thread.currentThread() + ": " + toString());
         }
-        stateSync.lock();
-        try {
+        final boolean res;
+        if( null == task ) {
+            // start/resume case w/ drawablesEmpty
+            res = true;
+        } else {
             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) { }
-        } finally {
-            stateSync.unlock();
+            shouldStop = true;
+            res = finishLifecycleAction(waitForStoppedCondition, POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION);
+        }
+        
+        if(DEBUG) {
+            System.err.println("FPSAnimator.stop() END: "+task+", "+ Thread.currentThread() + ": " + toString());
+        }
+        if(null != task) {
+            task.cancel();
+            task = null;
+        }
+        if(null != timer) {
+            timer.cancel();
+            timer = null;
         }
-        return true;
+        animThread = null;
+        return res;
     }
+    private final Condition waitForStoppedCondition = new Condition() {
+        public boolean eval() {
+            return isStartedImpl();
+        } };
 
     public synchronized boolean pause() {
-        if (timer == null) {
+        if ( !isStartedImpl() || ( null != task && isPausedImpl() ) ) {
             return false;
         }
-        stateSync.lock();
-        try {
+        if(DEBUG) {
+            System.err.println("FPSAnimator.pause() START: "+task+", "+ Thread.currentThread() + ": " + toString());
+        }
+        final boolean res;
+        if( null == task ) {
+            // start/resume case w/ drawablesEmpty
+            res = true;
+        } else {
             shouldRun = false;
-            if(null != task) {
-                task.cancel();
-                task = null;
-            }
-            animThread = null;
-            try {
-                Thread.sleep(20); // ~ 1/60 hz wait, since we can't ctrl stopped threads
-            } catch (InterruptedException e) { }
-        } finally {
-            stateSync.unlock();
+            res = finishLifecycleAction(waitForPausedCondition, POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION);
+        }
+        
+        if(DEBUG) {
+            System.err.println("FPSAnimator.pause() END: "+task+", "+ Thread.currentThread() + ": " + toString());
+        }
+        if(null != task) {
+            task.cancel();
+            task = null;
         }
-        return true;
+        return res;
     }
+    private final Condition waitForPausedCondition = new Condition() {
+        public boolean eval() {
+            // end waiting if stopped as well
+            return isAnimating && isStartedImpl();
+        } };
 
     public synchronized boolean resume() {
-        if (timer == null) {
+        if ( null != task || !isStartedImpl() || !isPausedImpl() ) {
             return false;
         }
-        stateSync.lock();
-        try {
-            startTask();
-        } finally {
-            stateSync.unlock();
+        if(DEBUG) {
+            System.err.println("FPSAnimator.resume() START: "+ Thread.currentThread() + ": " + toString());
+        }
+        final boolean res;
+        if( drawablesEmpty ) {
+            res = true;
+        } else {
+            task = new MainTask();
+            task.start(timer);
+            res = finishLifecycleAction(waitForResumeCondition, POLLP_WAIT_FOR_FINISH_LIFECYCLE_ACTION);
+        }
+        if(DEBUG) {
+            System.err.println("FPSAnimator.resume() END: "+task+", "+ Thread.currentThread() + ": " + toString());
         }
-        return true;
+        return res;
     }
+    private final Condition waitForResumeCondition = new Condition() {
+        public boolean eval() {
+            // end waiting if stopped as well
+            return !drawablesEmpty && !isAnimating && isStartedImpl();
+        } };
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java
index 88cb330..e0bbbc3 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java
@@ -1,3 +1,30 @@
+/**
+ * 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.util;
 
@@ -120,6 +147,17 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
       return adc;
   }
 
+  @Override
+  public void associate(Object obj, boolean enable) {
+      if(obj instanceof ShaderState) {
+          if(enable) {
+              shaderState = (ShaderState)obj;
+          } else {
+              shaderState = null;
+          }
+      }
+  }
+  
   // 
   // Data read access
   //
@@ -157,7 +195,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
     seal(seal);
     enableBuffer(gl, seal);
   }
-
+  
   @Override
   public void enableBuffer(GL gl, boolean enable) {
     if( enableBufferAlways || bufferEnabled != enable ) { 
@@ -166,16 +204,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
             // init/generate VBO name if not done yet
             init_vbo(gl);
         }
-        final Object ext;
-        if(usesGLSL) {
-            ext = ShaderState.getShaderState(gl);
-            if(null == ext) {
-                throw new GLException("A ShaderState must be bound to the GL context, use 'ShaderState.setShaderState(gl)'");
-            }
-        } else {
-            ext = null;
-        }
-        glArrayHandler.enableState(gl, enable, ext);
+        glArrayHandler.enableState(gl, enable, usesGLSL ? shaderState : null);
         bufferEnabled = enable;
     }
   }
@@ -297,6 +326,8 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
                        ", index "+index+
                        ", location "+location+
                        ", isVertexAttribute "+isVertexAttribute+
+                       ", usesGLSL "+usesGLSL+
+                       ", usesShaderState "+(null!=shaderState)+
                        ", dataType 0x"+Integer.toHexString(componentType)+ 
                        ", bufferClazz "+componentClazz+ 
                        ", elements "+getElementCount()+
@@ -421,5 +452,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData
 
   protected GLArrayHandler glArrayHandler;
   protected boolean usesGLSL;
+  protected ShaderState shaderState;
+    
 }
 
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java
index c9dd987..7e7d27b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java
@@ -1,3 +1,30 @@
+/**
+ * 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.util;
 
@@ -332,6 +359,8 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE
                        ", index "+index+
                        ", location "+location+
                        ", isVertexAttribute "+isVertexAttribute+
+                       ", usesGLSL "+usesGLSL+
+                       ", usesShaderState "+(null!=shaderState)+
                        ", dataType 0x"+Integer.toHexString(componentType)+ 
                        ", bufferClazz "+componentClazz+ 
                        ", elements "+getElementCount()+
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java
index f4a197b..f8b1750 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java
@@ -1,3 +1,30 @@
+/**
+ * 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.util;
 
@@ -97,53 +124,91 @@ public class GLArrayDataWrapper implements GLArrayData {
     return glp.isValidArrayDataType(getIndex(), getComponentCount(), getComponentType(), isVertexAttribute(), throwException);
   }
     
+  @Override
+  public void associate(Object obj, boolean enable) {
+      // nop
+  }
+  
   // 
   // Data read access
   //
 
+  @Override
   public final boolean isVertexAttribute() { return isVertexAttribute; }
 
+  @Override
   public final int getIndex() { return index; }
 
+  @Override
   public final int getLocation() { return location; }
 
-  public final void setLocation(int v) { location = v; }
+  @Override
+  public final int setLocation(int v) { location = v; return location; }
 
+  @Override
+  public final int setLocation(GL2ES2 gl, int program) {
+      location = gl.glGetAttribLocation(program, name);
+      return location;
+  }
+  
+  @Override
+  public final int setLocation(GL2ES2 gl, int program, int location) {
+      this.location = location;
+      gl.glBindAttribLocation(program, location, name);
+      return location;
+  }
+  
+  @Override
   public final String getName() { return name; }
 
+  @Override
   public final long getVBOOffset() { return vboEnabled?vboOffset:0; }
 
+  @Override
   public final int getVBOName() { return vboEnabled?vboName:0; }
 
+  @Override
   public final boolean isVBO() { return vboEnabled; }
 
+  @Override
   public final int getVBOUsage() { return vboEnabled?vboUsage:0; }
   
+  @Override
   public final int getVBOTarget() { return vboEnabled?vboTarget:0; }
   
+  @Override
   public final Buffer getBuffer() { return buffer; }
 
+  @Override
   public final int getComponentCount() { return components; }
 
+  @Override
   public final int getComponentType() { return componentType; }
 
+  @Override
   public final int getComponentSizeInBytes() { return componentByteSize; }
   
+  @Override
   public final int getElementCount() {
     if(null==buffer) return 0;
     return ( buffer.position()==0 ) ? ( buffer.limit() / components ) : ( buffer.position() / components ) ;
   }
+  
+  @Override
   public final int getSizeInBytes() {
     if(null==buffer) return 0;
     return ( buffer.position()==0 ) ? ( buffer.limit() * componentByteSize ) : ( buffer.position() * componentByteSize ) ;      
   }
   
+  @Override
   public final boolean getNormalized() { return normalized; }
 
+  @Override
   public final int getStride() { return strideB; }
 
-  public final Class getBufferClass() { return componentClazz; }
+  public final Class<?> getBufferClass() { return componentClazz; }
 
+  @Override
   public void destroy(GL gl) {
     buffer = null;
     vboName=0;
@@ -152,6 +217,7 @@ public class GLArrayDataWrapper implements GLArrayData {
     alive = false;
   }
 
+  @Override
   public String toString() {
     return "GLArrayDataWrapper["+name+
                        ", index "+index+
@@ -172,7 +238,7 @@ public class GLArrayDataWrapper implements GLArrayData {
                        "]";
   }
 
-  public static final Class getBufferClass(int dataType) {
+  public static final Class<?> getBufferClass(int dataType) {
     switch(dataType) {
         case GL.GL_BYTE:
         case GL.GL_UNSIGNED_BYTE:
@@ -180,7 +246,9 @@ public class GLArrayDataWrapper implements GLArrayData {
         case GL.GL_SHORT:
         case GL.GL_UNSIGNED_SHORT:
             return ShortBuffer.class;
+        case GL.GL_UNSIGNED_INT:
         case GL2ES1.GL_FIXED:
+        case GL2ES2.GL_INT:
             return IntBuffer.class;
         case GL.GL_FLOAT:
             return FloatBuffer.class;
@@ -189,6 +257,7 @@ public class GLArrayDataWrapper implements GLArrayData {
     }
   }
 
+  @Override  
   public void setName(String newName) {
     location = -1;
     name = newName;
@@ -240,9 +309,9 @@ public class GLArrayDataWrapper implements GLArrayData {
     // We can't have any dependence on the FixedFuncUtil class here for build bootstrapping reasons
     
     if( GL.GL_ELEMENT_ARRAY_BUFFER == vboTarget ) {
-        // ok ..
-    } else if( GL.GL_ARRAY_BUFFER == vboTarget ) {
-        // check name ..
+        // OK ..
+    } else if( ( 0 == vboUsage && 0 == vboTarget ) || GL.GL_ARRAY_BUFFER == vboTarget ) {
+        // Set/Check name .. - Required for GLSL case. Validation and debug-name for FFP. 
         this.name = ( null == name ) ? GLPointerFuncUtil.getPredefinedArrayIndexName(index) : name ;
         if(null == this.name ) {
             throw new GLException("Not a valid array buffer index: "+index);
@@ -310,14 +379,13 @@ public class GLArrayDataWrapper implements GLArrayData {
   protected String name;
   protected int components;
   protected int componentType;
-  protected Class componentClazz;
+  protected Class<?> componentClazz;
   protected int componentByteSize;
   protected boolean normalized;
   protected int strideB; // stride in bytes
   protected int strideL; // stride in logical components
   protected Buffer buffer;
   protected boolean isVertexAttribute;
-
   protected long vboOffset;
   protected int vboName;
   protected boolean vboEnabled;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
index 174935d..033e4a5 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
@@ -342,7 +342,7 @@ public class GLBuffers extends Buffers {
      * 
      * @param tmp a pass through integer array of size >= 1 used to store temp data (performance)
      * 
-     * @param bytesPerElement bytes per element
+     * @param bytesPerPixel bytes per pixel, i.e. via {@link #bytesPerPixel(int, int)}.
      * @param width in pixels
      * @param height in pixels
      * @param depth in pixels
@@ -351,7 +351,7 @@ public class GLBuffers extends Buffers {
      * @throws GLException if alignment is invalid. Please contact the maintainer if this is our bug.
      */
     public static final int sizeof(GL gl, int tmp[], 
-                                   int bytesPerElement, int width, int height, int depth, 
+                                   int bytesPerPixel, int width, int height, int depth, 
                                    boolean pack) {
         int rowLength = 0;
         int skipRows = 0;
@@ -396,8 +396,8 @@ public class GLBuffers extends Buffers {
         imageHeight = ( imageHeight > 0 ) ? imageHeight : height;
         rowLength   = ( rowLength   > 0 ) ? rowLength   : width;
   
-        int rowLengthInBytes = rowLength  * bytesPerElement;
-        int skipBytes        = skipPixels * bytesPerElement;
+        int rowLengthInBytes = rowLength  * bytesPerPixel;
+        int skipBytes        = skipPixels * bytesPerPixel;
         
         switch(alignment) {
             case 1:
@@ -434,7 +434,7 @@ public class GLBuffers extends Buffers {
             skipBytes +                                                  // aligned skipPixels * bpp
           ( skipImages + depth  - 1 ) * imageHeight * rowLengthInBytes + // aligned whole images 
           ( skipRows   + height - 1 ) * rowLengthInBytes +               // aligned lines
-            width                     * bytesPerElement;                 // last line        
+            width                     * bytesPerPixel;                 // last line        
     }
   
     /** 
@@ -444,7 +444,9 @@ public class GLBuffers extends Buffers {
      * <p>This method is security critical, hence it throws an exception (fail-fast)
      * in case either the format, type or alignment is unhandled. In case we forgot to handle 
      * proper values, please contact the maintainer.</p> 
-     *   
+     * 
+     * <p> See {@link #bytesPerPixel(int, int)}. </p>
+     * 
      * @param gl the current GL object
      * 
      * @param tmp a pass through integer array of size >= 1 used to store temp data (performance)
@@ -500,85 +502,101 @@ public class GLBuffers extends Buffers {
     public static final int sizeof(GL gl, int tmp[], 
                                    int format, int type, int width, int height, int depth,
                                    boolean pack) throws GLException {
-        int elements = 0;
-        int esize = 0;
-
         if (width < 0) return 0;
         if (height < 0) return 0;
         if (depth < 0) return 0;
         
-        switch (format) /* 26 */ {
-            case GL2.GL_COLOR_INDEX:
-            case GL2GL3.GL_STENCIL_INDEX:
-            case GL2GL3.GL_DEPTH_COMPONENT:
-            case GL2GL3.GL_DEPTH_STENCIL:
-            case GL2GL3.GL_RED:
-            case GL2GL3.GL_RED_INTEGER:
-            case GL2GL3.GL_GREEN:
-            case GL2GL3.GL_GREEN_INTEGER:
-            case GL2GL3.GL_BLUE:
-            case GL2GL3.GL_BLUE_INTEGER:
-            case GL.GL_ALPHA:
-            case GL.GL_LUMINANCE:
-              elements = 1;
-              break;
-            case GL.GL_LUMINANCE_ALPHA:
-            case GL2GL3.GL_RG:
-            case GL2GL3.GL_RG_INTEGER:
-            case GL2.GL_HILO_NV:
-            case GL2.GL_SIGNED_HILO_NV:
-              elements = 2;
-              break;
-            case GL.GL_RGB:
-            case GL2GL3.GL_RGB_INTEGER:
-            case GL2GL3.GL_BGR:
-            case GL2GL3.GL_BGR_INTEGER: 
-              elements = 3;
-              break;
-            case GL.GL_RGBA:
-            case GL2GL3.GL_RGBA_INTEGER:
-            case GL.GL_BGRA:
-            case GL2GL3.GL_BGRA_INTEGER:
-            case GL2.GL_ABGR_EXT:
-              elements = 4;
-              break;
-            /* FIXME ?? 
-             case GL.GL_HILO_NV:
-              elements = 2;
-              break; */              
-            default:
-              throw new GLException("format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug.");
-        }
-                
+        final int bytesPerPixel = bytesPerPixel(format, type);
+        return sizeof(gl, tmp, bytesPerPixel, width, height, depth, pack);
+    }
+    
+    /** 
+     * Returns the number of bytes required for one pixel with the the given OpenGL format and type.
+     * 
+     * <p>This method is security critical, hence it throws an exception (fail-fast)
+     * in case either the format, type or alignment is unhandled. In case we forgot to handle 
+     * proper values, please contact the maintainer.</p> 
+     * 
+     * <p> See {@link #componentCount(int)}. </p>
+     * 
+     * @param format must be one of (26) <br/> 
+     *              GL_COLOR_INDEX GL_STENCIL_INDEX <br/> 
+     *              GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/> 
+     *              GL_RED GL_RED_INTEGER <br/> 
+     *              GL_GREEN GL_GREEN_INTEGER <br/> 
+     *              GL_BLUE GL_BLUE_INTEGER <br/> 
+     *              GL_ALPHA GL_LUMINANCE (12) <br/> 
+     *              <br/> 
+     *              GL_LUMINANCE_ALPHA GL_RG <br/>
+     *              GL_RG_INTEGER GL_HILO_NV <br/> 
+     *              GL_SIGNED_HILO_NV (5) <br/> 
+     *              <br/> 
+     *              GL_RGB GL_RGB_INTEGER <br/> 
+     *              GL_BGR GL_BGR_INTEGER (4)<br/>  
+     *              <br/> 
+     *              GL_RGBA GL_RGBA_INTEGER <br/> 
+     *              GL_BGRA GL_BGRA_INTEGER <br/>
+     *              GL_ABGR_EXT (5)<br/> 
+     *           
+     * @param type must be one of (30) <br/>  
+     *              GL_BITMAP, <br/> 
+     *              GL_BYTE, GL_UNSIGNED_BYTE, <br/>
+     *              GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, <br/>
+     *              <br/>
+     *              GL_SHORT, GL_UNSIGNED_SHORT, <br/>
+     *              GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, <br/> 
+     *              GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, <br/>
+     *              GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, <br/>
+     *              GL_HALF_FLOAT, GL_HALF_FLOAT_OES <br/>
+     *              <br/>
+     *              GL_FIXED, GL_INT <br/>
+     *              GL_UNSIGNED_INT, GL_UNSIGNED_INT_8_8_8_8, <br/>
+     *              GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, <br/> 
+     *              GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, <br/>
+     *              GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV <br/> 
+     *              GL_HILO16_NV, GL_SIGNED_HILO16_NV <br/>
+     *              <br/>
+     *              GL_FLOAT_32_UNSIGNED_INT_24_8_REV <br/>
+     *              <br/>
+     *              GL_FLOAT, GL_DOUBLE <br/> 
+     * 
+     * @return required size of one pixel in bytes
+     * @throws GLException if format or type alignment is not handled. Please contact the maintainer if this is our bug.
+     */
+    public static final int bytesPerPixel(int format, int type) throws GLException {
+        int compSize = 0;
+
+        int compCount = componentCount(format);
+        
         switch (type) /* 30 */ {
             case GL2.GL_BITMAP:
               if (GL2.GL_COLOR_INDEX == format || GL2GL3.GL_STENCIL_INDEX == format) {
-                return (depth * (height * ((width+7)/8)));
+                  compSize = 1;
               }
             case GL.GL_BYTE:
             case GL.GL_UNSIGNED_BYTE:                
-              esize = 1;
+              compSize = 1;
               break;
             case GL.GL_SHORT:
             case GL.GL_UNSIGNED_SHORT:
             case GL.GL_HALF_FLOAT:
             case GLES2.GL_HALF_FLOAT_OES:
-              esize = 2;
+              compSize = 2;
               break;
             case GL.GL_FIXED:
             case GL2ES2.GL_INT:
             case GL.GL_UNSIGNED_INT:
             case GL.GL_FLOAT:
-              esize = 4;
+              compSize = 4;
               break;
             case GL2GL3.GL_DOUBLE:
-              esize = 8;
+              compSize = 8;
               break;
               
             case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
             case GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV:
-              esize = 1;
-              elements = 1;
+              compSize = 1;
+              compCount = 1;
               break;
             case GL.GL_UNSIGNED_SHORT_5_6_5:
             case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
@@ -586,13 +604,13 @@ public class GLBuffers extends Buffers {
             case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
             case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
             case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
-              esize = 2;
-              elements = 1;
+              compSize = 2;
+              compCount = 1;
               break;
             case GL2.GL_HILO16_NV:
             case GL2.GL_SIGNED_HILO16_NV:
-              esize = 2;
-              elements = 2;
+              compSize = 2;
+              compCount = 2;
               break;                
             case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
             case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:
@@ -601,19 +619,95 @@ public class GLBuffers extends Buffers {
             case GL2GL3.GL_UNSIGNED_INT_24_8:
             case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV:
             case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV:
-              esize = 4;
-              elements = 1;
+              compSize = 4;
+              compCount = 1;
               break;              
             case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
-              esize = 8;
-              elements = 1;
+              compSize = 8;
+              compCount = 1;
               break;              
                 
             default:
               throw new GLException("type 0x"+Integer.toHexString(type)+"/"+"format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug.");
-        }
+        }        
+        return compCount * compSize;
+    }
+    
+    /** 
+     * Returns the number of components required for the given OpenGL format.
+     * 
+     * <p>This method is security critical, hence it throws an exception (fail-fast)
+     * in case either the format, type or alignment is unhandled. In case we forgot to handle 
+     * proper values, please contact the maintainer.</p> 
+     *   
+     * @param format must be one of (26) <br/> 
+     *              GL_COLOR_INDEX GL_STENCIL_INDEX <br/> 
+     *              GL_DEPTH_COMPONENT GL_DEPTH_STENCIL <br/> 
+     *              GL_RED GL_RED_INTEGER <br/> 
+     *              GL_GREEN GL_GREEN_INTEGER <br/> 
+     *              GL_BLUE GL_BLUE_INTEGER <br/> 
+     *              GL_ALPHA GL_LUMINANCE (12) <br/> 
+     *              <br/> 
+     *              GL_LUMINANCE_ALPHA GL_RG <br/>
+     *              GL_RG_INTEGER GL_HILO_NV <br/> 
+     *              GL_SIGNED_HILO_NV (5) <br/> 
+     *              <br/> 
+     *              GL_RGB GL_RGB_INTEGER <br/> 
+     *              GL_BGR GL_BGR_INTEGER (4)<br/>  
+     *              <br/> 
+     *              GL_RGBA GL_RGBA_INTEGER <br/> 
+     *              GL_BGRA GL_BGRA_INTEGER <br/>
+     *              GL_ABGR_EXT (5)<br/> 
+     *           
+     * @return number of components required for the given OpenGL format
+     * @throws GLException if format is not handled. Please contact the maintainer if this is our bug.
+     */
+    public static final int componentCount(int format) throws GLException {
+        final int compCount;
         
-        return sizeof(gl, tmp, elements * esize, width, height, depth, pack);
+        switch (format) /* 26 */ {
+            case GL2.GL_COLOR_INDEX:
+            case GL2GL3.GL_STENCIL_INDEX:
+            case GL2GL3.GL_DEPTH_COMPONENT:
+            case GL2GL3.GL_DEPTH_STENCIL:
+            case GL2GL3.GL_RED:
+            case GL2GL3.GL_RED_INTEGER:
+            case GL2GL3.GL_GREEN:
+            case GL2GL3.GL_GREEN_INTEGER:
+            case GL2GL3.GL_BLUE:
+            case GL2GL3.GL_BLUE_INTEGER:
+            case GL.GL_ALPHA:
+            case GL.GL_LUMINANCE:
+              compCount = 1;
+              break;
+            case GL.GL_LUMINANCE_ALPHA:
+            case GL2GL3.GL_RG:
+            case GL2GL3.GL_RG_INTEGER:
+            case GL2.GL_HILO_NV:
+            case GL2.GL_SIGNED_HILO_NV:
+              compCount = 2;
+              break;
+            case GL.GL_RGB:
+            case GL2GL3.GL_RGB_INTEGER:
+            case GL2GL3.GL_BGR:
+            case GL2GL3.GL_BGR_INTEGER: 
+              compCount = 3;
+              break;
+            case GL.GL_RGBA:
+            case GL2GL3.GL_RGBA_INTEGER:
+            case GL.GL_BGRA:
+            case GL2GL3.GL_BGRA_INTEGER:
+            case GL2.GL_ABGR_EXT:
+              compCount = 4;
+              break;
+            /* FIXME ?? 
+             case GL.GL_HILO_NV:
+              elements = 2;
+              break; */              
+            default:
+              throw new GLException("format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug.");
+        }
+        return compCount;
     }
     
     public static final int getNextPowerOf2(int number) {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
new file mode 100644
index 0000000..28349b2
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
@@ -0,0 +1,167 @@
+/**
+ * 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.util;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+
+import com.jogamp.opengl.GLEventListenerState;
+
+import jogamp.opengl.Debug;
+
+/**
+ * Providing utility functions dealing w/ {@link GLDrawable}s, {@link GLAutoDrawable} and their {@link GLEventListener}.
+ */
+public class GLDrawableUtil {
+  protected static final boolean DEBUG = Debug.debug("GLDrawable");
+  
+  public static final boolean isAnimatorStartedOnOtherThread(GLAnimatorControl animatorCtrl) {
+    return ( null != animatorCtrl ) ? animatorCtrl.isStarted() && animatorCtrl.getThread() != Thread.currentThread() : false ;
+  }
+
+  public static final boolean isAnimatorStarted(GLAnimatorControl animatorCtrl) {
+    return ( null != animatorCtrl ) ? animatorCtrl.isStarted() : false ;
+  }
+
+  public static final boolean isAnimatorAnimatingOnOtherThread(GLAnimatorControl animatorCtrl) {
+    return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() && animatorCtrl.getThread() != Thread.currentThread() : false ;
+  }
+  
+  public static final boolean isAnimatorAnimating(GLAnimatorControl animatorCtrl) {
+    return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() : false ;
+  }
+  
+  /**
+   * Moves the designated {@link GLEventListener} from {@link GLAutoDrawable} <code>src</code> to <code>dest</code>.
+   * If <code>preserveInitState</code> is <code>true</code>, it's initialized state is preserved
+   * and {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape(..)} issued w/ the next {@link GLAutoDrawable#display()} call.
+   * <p>
+   * Note that it is only legal to pass <code>preserveInitState := true</code>,
+   * if the {@link GLContext} of both <code>src</code> and <code>dest</code> are shared, or has itself moved from <code>src</code> to <code>dest</code>.
+   * </p>
+   * <p>
+   * Also note that the caller is encouraged to pause an attached {@link GLAnimatorControl}.
+   * </p>
+   * @param src
+   * @param dest
+   * @param listener
+   * @param preserveInitState
+   */
+  public static final void moveGLEventListener(GLAutoDrawable src, GLAutoDrawable dest, GLEventListener listener, boolean preserveInitState) {
+    final boolean initialized = src.getGLEventListenerInitState(listener);
+    src.removeGLEventListener(listener);
+    dest.addGLEventListener(listener);
+    if(preserveInitState && initialized) {
+        dest.setGLEventListenerInitState(listener, true);
+        dest.invoke(false, new GLEventListenerState.ReshapeGLEventListener(listener));
+    } // else .. !init state is default
+  }
+  
+  /**
+   * Moves all {@link GLEventListener} from {@link GLAutoDrawable} <code>src</code> to <code>dest</code>.
+   * If <code>preserveInitState</code> is <code>true</code>, it's initialized state is preserved
+   * and {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape(..)} issued w/ the next {@link GLAutoDrawable#display()} call.
+   * <p>
+   * Note that it is only legal to pass <code>preserveInitState := true</code>,
+   * if the {@link GLContext} of both <code>src</code> and <code>dest</code> are shared, or has itself moved from <code>src</code> to <code>dest</code>.
+   * </p>
+   * <p>
+   * Also note that the caller is encouraged to pause an attached {@link GLAnimatorControl}.
+   * </p>
+   * @param src
+   * @param dest
+   * @param listener
+   * @param preserveInitState
+   */
+  public static final void moveAllGLEventListener(GLAutoDrawable src, GLAutoDrawable dest, boolean preserveInitState) {
+    for(int count = src.getGLEventListenerCount(); 0<count; count--) {
+        final GLEventListener listener = src.getGLEventListener(0);
+        moveGLEventListener(src, dest, listener, preserveInitState);
+    }
+  }
+
+  /**
+   * Swaps the {@link GLContext} and all {@link GLEventListener} between {@link GLAutoDrawable} <code>a</code> and <code>b</code>,
+   * while preserving it's initialized state, resets the GL-Viewport and issuing {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape(..)}.
+   * <p>
+   * If an {@link GLAnimatorControl} is being attached to {@link GLAutoDrawable} <code>a</code> or <code>b</code> 
+   * and the current thread is different than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+   * </p>
+   * @param a
+   * @param b
+   * @throws GLException if the {@link AbstractGraphicsDevice} are incompatible w/ each other.
+   */
+  public static final void swapGLContextAndAllGLEventListener(GLAutoDrawable a, GLAutoDrawable b) {
+    final GLEventListenerState gllsA = GLEventListenerState.moveFrom(a);
+    final GLEventListenerState gllsB = GLEventListenerState.moveFrom(b);
+    
+    gllsA.moveTo(b);
+    gllsB.moveTo(a);
+  }
+  
+  /** 
+   * Swaps the {@link GLContext} of given {@link GLAutoDrawable} 
+   * and {@link GLAutoDrawable#disposeGLEventListener(GLEventListener, boolean) disposes} 
+   * each {@link GLEventListener} w/o removing it.
+   * <p>
+   * The GL-Viewport is reset and {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape(..)} issued implicit.
+   * </p> 
+   * <p>
+   * If an {@link GLAnimatorControl} is being attached to GLAutoDrawable src or dest and the current thread is different 
+   * than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+   * </p>
+   * @param src
+   * @param dest
+   */
+  public static final void swapGLContext(GLAutoDrawable src, GLAutoDrawable dest) {    
+    final GLAnimatorControl aAnim = src.getAnimator();
+    final GLAnimatorControl bAnim = dest.getAnimator();    
+    final boolean aIsPaused = isAnimatorAnimatingOnOtherThread(aAnim) && aAnim.pause();
+    final boolean bIsPaused = isAnimatorAnimatingOnOtherThread(bAnim) && bAnim.pause();
+    
+    for(int i = src.getGLEventListenerCount() - 1; 0 <= i; i--) {
+        src.disposeGLEventListener(src.getGLEventListener(i), false);
+    }
+    for(int i = dest.getGLEventListenerCount() - 1; 0 <= i; i--) {
+        dest.disposeGLEventListener(dest.getGLEventListener(i), false);
+    }
+    dest.setContext( src.setContext( dest.getContext(), false ), false );
+    
+    src.invoke(true, GLEventListenerState.setViewport);
+    dest.invoke(true, GLEventListenerState.setViewport);
+    
+    if(aIsPaused) { aAnim.resume(); }
+    if(bIsPaused) { bAnim.resume(); }
+  }
+    
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
new file mode 100644
index 0000000..b0fc7f3
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
@@ -0,0 +1,269 @@
+/**
+ * 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.util;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLContext;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.texture.TextureData;
+
+/** 
+ * OpenGL pixel data buffer, allowing user to provide buffers via their {@link GLPixelBufferProvider} implementation.
+ * <p>
+ * {@link GLPixelBufferProvider} produces a {@link GLPixelBuffer}.
+ * </p> 
+ * <p>
+ * You may use {@link #defaultProvider}.
+ * </p>
+ */
+public class GLPixelBuffer {
+    
+    /** Allows user to interface with another toolkit to define {@link GLPixelAttributes} and memory buffer to produce {@link TextureData}. */ 
+    public static interface GLPixelBufferProvider {
+        /** Called first to determine {@link GLPixelAttributes}. */
+        GLPixelAttributes getAttributes(GL gl, int componentCount);
+        
+        /** 
+         * Allocates a new {@link GLPixelBuffer} object.
+         * <p>
+         * Being called to gather the initial {@link GLPixelBuffer},
+         * or a new replacement {@link GLPixelBuffer} if {@link GLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+         * </p>
+         * <p>
+         * The minimum required {@link Buffer#remaining() remaining} byte size equals to <code>minByteSize</code>, if > 0, 
+         * otherwise utilize {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean)}
+         * to calculate it.
+         * </p>
+         * 
+         * @param gl the corresponding current GL context object
+         * @param pixelAttributes the desired {@link GLPixelAttributes}
+         * @param width in pixels
+         * @param height in pixels
+         * @param depth in pixels
+         * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
+         * @param minByteSize if > 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore.   
+         */
+        GLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize);
+    }
+
+    /** Single {@link GLPixelBuffer} provider. */ 
+    public static interface SingletonGLPixelBufferProvider extends GLPixelBufferProvider {
+        /** Return the last {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated} {@link GLPixelBuffer} w/ {@link GLPixelAttributes#componentCount}. */ 
+        GLPixelBuffer getSingleBuffer(GLPixelAttributes pixelAttributes);
+        /** 
+         * Initializes the single {@link GLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+         * @return the newly initialized single {@link GLPixelBuffer}, or null if already allocated.
+         */
+        GLPixelBuffer initSingleton(int componentCount, int width, int height, int depth, boolean pack);        
+    }
+
+    /** 
+     * Default {@link GLPixelBufferProvider} utilizing best match for {@link GLPixelAttributes}
+     * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}.
+     */
+    public static GLPixelBufferProvider defaultProvider = new GLPixelBufferProvider() {
+        
+        @Override
+        public GLPixelAttributes getAttributes(GL gl, int componentCount) {
+            final GLContext ctx = gl.getContext();
+            final int dFormat, dType;
+            
+            if(gl.isGL2GL3() && 3 == componentCount) {
+                dFormat = GL.GL_RGB;
+                dType   = GL.GL_UNSIGNED_BYTE;            
+            } else {
+                dFormat = ctx.getDefaultPixelDataFormat();
+                dType   = ctx.getDefaultPixelDataType();
+            }
+            return new GLPixelAttributes(componentCount, dFormat, dType);
+        }
+        
+        /**
+         * {@inheritDoc}
+         * <p>
+         * Returns an NIO {@link ByteBuffer}.
+         * </p>
+         */
+        @Override
+        public GLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize) {
+            if( minByteSize > 0 ) {
+                return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(minByteSize));                
+            } else {
+                int[] tmp = { 0 };
+                final int byteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.bytesPerPixel, width, height, depth, pack);
+                return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(byteSize));
+            }
+        }
+    };
+        
+    /** Pixel attributes. */ 
+    public static class GLPixelAttributes {
+        /** Undefined instance of {@link GLPixelAttributes}, having componentCount:=0, format:=0 and type:= 0. */ 
+        public static final GLPixelAttributes UNDEF = new GLPixelAttributes(0, 0, 0);
+        
+        /** Pixel <i>source</i> component count, i.e. number of meaningful components. */
+        public final int componentCount;
+        /** The OpenGL pixel data format */
+        public final int format;
+        /** The OpenGL pixel data type  */
+        public final int type;
+        /** The OpenGL pixel size in bytes  */
+        public final int bytesPerPixel;
+        
+        /**
+         * Deriving {@link #componentCount} via GL <code>dataFormat</code>, i.e. {@link GLBuffers#componentCount(int)} if > 0.
+         * @param dataFormat GL data format
+         * @param dataType GL data type
+         */
+        public GLPixelAttributes(int dataFormat, int dataType) {
+            this(0 < dataFormat ? GLBuffers.componentCount(dataFormat) : 0, dataFormat, dataType);
+        }
+        /**
+         * Using user specified source {@link #componentCount}. 
+         * @param componentCount source component count
+         * @param dataFormat GL data format
+         * @param dataType GL data type
+         */
+        public GLPixelAttributes(int componentCount, int dataFormat, int dataType) {
+            this.componentCount = componentCount;
+            this.format = dataFormat;
+            this.type = dataType;
+            this.bytesPerPixel = ( 0 < dataFormat && 0 < dataType ) ? GLBuffers.bytesPerPixel(dataFormat, dataType) : 0;
+        }
+        public String toString() {
+            return "PixelAttributes[comp "+componentCount+", fmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+", bytesPerPixel "+bytesPerPixel+"]";
+        }
+    }
+    
+    /** The {@link GLPixelAttributes}. */
+    public final GLPixelAttributes pixelAttributes;
+    /** Width in pixels. */
+    public final int width;
+    /** Height in pixels. */
+    public final int height;
+    /** Depth in pixels. */
+    public final int depth;
+    /** Data packing direction. If <code>true</code> for read mode GPU -> CPU, <code>false</code> for write mode CPU -> GPU. */
+    public final boolean pack;
+    /** Byte size of the buffer. Actually the number of {@link Buffer#remaining()} bytes when passed in ctor. */
+    public final int byteSize;
+    /** 
+     * Buffer holding the pixel data. If {@link #rewind()}, it holds <code>byteSize</code> {@link Buffer#remaining()} bytes. 
+     * <p>
+     * By default the {@link Buffer} is a {@link ByteBuffer}, due to {@link DefProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int)}.
+     * However, other {@link GLPixelBufferProvider} may utilize different {@link Buffer} types.
+     * </p>
+     */   
+    public final Buffer buffer;
+    /** Buffer element size in bytes. */
+    public final int bufferElemSize;
+    
+    private boolean disposed = false;
+    
+    public StringBuffer toString(StringBuffer sb) {
+        if(null == sb) {
+            sb = new StringBuffer();
+        }
+        sb.append(pixelAttributes).append(", dim ").append(width).append("x").append(height).append("x").append(depth).append(", pack ").append(pack)
+        .append(", disposed ").append(disposed).append(", valid ").append(isValid()).append(", buffer[sz [bytes ").append(byteSize).append(", elemSize ").append(bufferElemSize).append(", ").append(buffer).append("]");
+        return sb;
+    }
+    public String toString() {
+        return "GLPixelBuffer["+toString(null).toString()+"]";
+    }
+    
+    public GLPixelBuffer(GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, Buffer buffer) {
+        this.pixelAttributes = pixelAttributes; 
+        this.width = width;
+        this.height = height;
+        this.depth = depth;
+        this.pack = pack;
+        this.buffer = buffer;
+        this.byteSize = Buffers.remainingBytes(buffer);
+        this.bufferElemSize = Buffers.sizeOfBufferElem(buffer);
+    }
+    
+    /** Is not {@link #dispose() disposed} and has {@link #byteSize} > 0. */
+    public boolean isValid() {
+        return !disposed && 0 < byteSize;
+    }
+    
+    public Buffer rewind() {
+        return buffer.rewind();
+    }
+
+    /** Returns the byte position of the {@link #buffer}. */
+    public int position() {
+        return buffer.position() * bufferElemSize;
+    }
+    
+    /** Sets the byte position of the {@link #buffer}. */
+    public Buffer position(int bytePos) {
+        return buffer.position( bytePos / bufferElemSize );
+    }
+    
+    public Buffer flip() {
+        return buffer.flip();        
+    }
+    
+    public Buffer clear() {
+        return buffer.clear();        
+    }
+    
+    /** 
+     * Returns true, if {@link #isValid() invalid} or implementation requires a new buffer based on the new size
+     * due to pixel alignment or byte size, otherwise false.
+     * <p>
+     * It is assumed that <code>pixelAttributes</code>, <code>depth</code> and <code>pack</code> stays the same!
+     * </p>
+     * <p>
+     * The minimum required byte size equals to <code>minByteSize</code>, if > 0, 
+     * otherwise utilize {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean) GLBuffers.sizeof(..)}
+     * to calculate it.
+     * </p>
+     * @param gl the corresponding current GL context object
+     * @param newWidth new width in pixels
+     * @param newHeight new height in pixels
+     * @param minByteSize if > 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore.   
+     * @see GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int)
+     */
+    public boolean requiresNewBuffer(GL gl, int newWidth, int newHeight, int minByteSize) {
+        return !isValid() || byteSize < minByteSize;
+    }
+    
+    /** Dispose resources. See {@link #isValid()}. */
+    public void dispose() {
+        disposed = true;
+        buffer.clear();
+    }
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
index 05eb672..fab80b1 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
@@ -43,32 +43,56 @@ public class GLPixelStorageModes {
     private int[] savedAlignment = new int[2];
     private boolean saved = false;
 
+    /** Create instance w/o {@link #save(GL)} */
+    public GLPixelStorageModes() {}
+    
+    /** Create instance w/ {@link #save(GL)} */
+    public GLPixelStorageModes(GL gl) { save(gl); }
+    
     /**
-     * Sets the {@link GL2ES2.GL_PACK_ALIGNMENT}. Saves the pixel storage modes if not saved yet.
+     * Sets the {@link GL2ES2.GL_PACK_ALIGNMENT}.
+     * <p> 
+     * Saves the pixel storage modes if not saved yet.
+     * </p>
      */
     public final void setPackAlignment(GL gl, int packAlignment) {
-        if(!saved) { save(gl); }
+        save(gl);
         gl.glPixelStorei(GL2ES2.GL_PACK_ALIGNMENT, packAlignment);        
     }
 
     /**
-     * Sets the {@link GL2ES2.GL_UNPACK_ALIGNMENT}. Saves the pixel storage modes if not saved yet.
+     * Sets the {@link GL2ES2.GL_UNPACK_ALIGNMENT}.
+     * <p> 
+     * Saves the pixel storage modes if not saved yet.
+     * </p>
      */
     public final void setUnpackAlignment(GL gl, int unpackAlignment) {
-        if(!saved) { save(gl); }
+        save(gl);
         gl.glPixelStorei(GL2ES2.GL_UNPACK_ALIGNMENT, unpackAlignment);        
     }
     
     /**
      * Sets the {@link GL2ES2.GL_PACK_ALIGNMENT} and {@link GL2ES2.GL_UNPACK_ALIGNMENT}. 
+     * <p> 
      * Saves the pixel storage modes if not saved yet.
+     * </p>
      */
     public final void setAlignment(GL gl, int packAlignment, int unpackAlignment) {
         setPackAlignment(gl, packAlignment);
         setUnpackAlignment(gl, unpackAlignment);
     }
     
-    private final void save(GL gl) {
+    /**
+     * Save the pixel storage mode, if not saved yet.
+     * <p>
+     * Restore via {@link #restore(GL)}
+     * </p>
+     */
+    public final void save(GL gl) {
+        if(saved) {
+            return;
+        }
+        
         if(gl.isGL2GL3()) {  
             if(gl.isGL2()) {
                 gl.getGL2().glPushClientAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT);
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index b8709f3..ae1b459 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -28,16 +28,21 @@
  
 package com.jogamp.opengl.util;
 
-import com.jogamp.common.nio.Buffers;
-
 import java.io.File;
 import java.io.IOException;
-import java.nio.*;
-import javax.media.opengl.*;
 
-import com.jogamp.opengl.GLExtensions;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
+
+import com.jogamp.common.nio.Buffers;
 import com.jogamp.opengl.util.texture.Texture;
 import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.GLPixelBuffer;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelBufferProvider;
 import com.jogamp.opengl.util.texture.TextureIO;
 
 /**
@@ -45,12 +50,12 @@ import com.jogamp.opengl.util.texture.TextureIO;
  * <p>May be used directly to write the TextureData to file (screenshot).</p>
  */
 public class GLReadBufferUtil {
-    protected final int components, alignment; 
+    protected final GLPixelBufferProvider pixelBufferProvider;
+    protected final int componentCount, alignment; 
     protected final Texture readTexture;
-    protected final GLPixelStorageModes psm;
+    protected final GLPixelStorageModes psm;    
     
-    protected int readPixelSizeLast = 0;
-    protected ByteBuffer readPixelBuffer = null;
+    protected GLPixelBuffer readPixelBuffer = null;
     protected TextureData readTextureData = null;
 
     /**
@@ -58,24 +63,32 @@ public class GLReadBufferUtil {
      * @param write2Texture true if readPixel's TextureData shall be written to a 2d Texture
      */
     public GLReadBufferUtil(boolean alpha, boolean write2Texture) {
-        components = alpha ? 4 : 3 ;
-        alignment = alpha ? 4 : 1 ; 
-        readTexture = write2Texture ? new Texture(GL.GL_TEXTURE_2D) : null ;
-        psm = new GLPixelStorageModes();
+        this(GLPixelBuffer.defaultProvider, alpha, write2Texture);
+    }
+    
+    public GLReadBufferUtil(GLPixelBufferProvider pixelBufferProvider, boolean alpha, boolean write2Texture) {
+        this.pixelBufferProvider = pixelBufferProvider;
+        this.componentCount = alpha ? 4 : 3 ;
+        this.alignment = alpha ? 4 : 1 ; 
+        this.readTexture = write2Texture ? new Texture(GL.GL_TEXTURE_2D) : null ;
+        this.psm = new GLPixelStorageModes();
     }
     
+    /** Returns the {@link GLPixelBufferProvider} used by this instance. */
+    public GLPixelBufferProvider getPixelBufferProvider() { return pixelBufferProvider; }
+    
     public boolean isValid() {
-      return null!=readTextureData && null!=readPixelBuffer ;
+      return null!=readTextureData && null!=readPixelBuffer && readPixelBuffer.isValid();
     }
     
-    public boolean hasAlpha() { return 4 == components ? true : false ; }
+    public boolean hasAlpha() { return 4 == componentCount ? true : false ; }
     
     public GLPixelStorageModes getGLPixelStorageModes() { return psm; }
     
     /**
-     * @return the raw pixel ByteBuffer, filled by {@link #readPixels(GLAutoDrawable, boolean)}
+     * Returns the {@link GLPixelBuffer}, created and filled by {@link #readPixels(GLAutoDrawable, boolean)}.
      */
-    public ByteBuffer getPixelBuffer() { return readPixelBuffer; }
+    public GLPixelBuffer getPixelBuffer() { return readPixelBuffer; }
     
     /**
      * rewind the raw pixel ByteBuffer
@@ -107,89 +120,116 @@ public class GLReadBufferUtil {
     }
 
     /**
-     * Read the drawable's pixels to TextureData and Texture, if requested at construction
+     * Read the drawable's pixels to TextureData and Texture, if requested at construction.
      * 
      * @param gl the current GL context object. It's read drawable is being used as the pixel source.
-     * @param drawable the drawable to read from
-     * @param flip weather to flip the data vertically or not
+     * @param mustFlipVertically indicates whether to flip the data vertically or not.
+     *                           The context's drawable {@link GLDrawable#isGLOriented()} state
+     *                           is taken into account.
+     *                           Vertical flipping is propagated to TextureData
+     *                           and handled in a efficient manner there (TextureCoordinates and TextureIO writer).
      * 
      * @see #GLReadBufferUtil(boolean, boolean)
      */
-    public boolean readPixels(GL gl, boolean flip) {
+    public boolean readPixels(GL gl, boolean mustFlipVertically) {
+        return readPixels(gl, 0, 0, null, null, mustFlipVertically);
+    }
+    
+    /**
+     * Read the drawable's pixels to TextureData and Texture, if requested at construction.
+     * 
+     * @param gl the current GL context object. It's read drawable is being used as the pixel source.
+     * @param inX readPixel x offset
+     * @param inY readPixel y offset
+     * @param ioWidth readPixel width
+     * @param ioHeight readPixel height
+     * @param mustFlipVertically indicates whether to flip the data vertically or not.
+     *                           The context's drawable {@link GLDrawable#isGLOriented()} state
+     *                           is taken into account.
+     *                           Vertical flipping is propagated to TextureData
+     *                           and handled in a efficient manner there (TextureCoordinates and TextureIO writer).
+     * 
+     * @see #GLReadBufferUtil(boolean, boolean)
+     */
+    public boolean readPixels(GL gl, int inX, int inY, int ioWidth[], int ioHeight[], boolean mustFlipVertically) {
         final int glerr0 = gl.glGetError();
         if(GL.GL_NO_ERROR != glerr0) {
             System.err.println("Info: GLReadBufferUtil.readPixels: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
         }
+        final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
+        final int internalFormat;
+        if(gl.isGL2GL3() && 3 == componentCount) {
+            internalFormat = GL.GL_RGB;
+        } else {
+            internalFormat = (4 == componentCount) ? GL.GL_RGBA : GL.GL_RGB;
+        }
         final GLDrawable drawable = gl.getContext().getGLReadDrawable();
-        final int textureInternalFormat, textureDataFormat, textureDataType;
-        final int[] glImplColorReadVals = new int[] { 0, 0 };
+        final int width, height;
+        if( null == ioWidth || drawable.getWidth() < ioWidth[0] ) {
+            width = drawable.getWidth();
+        } else {
+            width = ioWidth[0];
+        }
+        if( null == ioHeight || drawable.getHeight() < ioHeight[0] ) {
+            height = drawable.getHeight();
+        } else {
+            height= ioHeight[0];
+        }
         
-        if(gl.isGL2GL3() && 3 == components) {
-            textureInternalFormat=GL.GL_RGB;
-            textureDataFormat=GL.GL_RGB;
-            textureDataType = GL.GL_UNSIGNED_BYTE;            
-        } else if(gl.isGLES2Compatible() || gl.isExtensionAvailable(GLExtensions.OES_read_format)) {
-            gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
-            gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);            
-            textureInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
-            textureDataFormat = glImplColorReadVals[0];
-            textureDataType = glImplColorReadVals[1];
+        final boolean flipVertically;
+        if( drawable.isGLOriented() ) {
+            flipVertically = mustFlipVertically;
         } else {
-            // RGBA read is safe for all GL profiles 
-            textureInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
-            textureDataFormat=GL.GL_RGBA;
-            textureDataType = GL.GL_UNSIGNED_BYTE;
+            flipVertically = !mustFlipVertically;
         }
         
         final int tmp[] = new int[1];
-        final int readPixelSize = GLBuffers.sizeof(gl, tmp, textureDataFormat, textureDataType, 
-                                                   drawable.getWidth(), drawable.getHeight(), 1, true);
+        final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, width, height, 1, true);
         
         boolean newData = false;
-        if(readPixelSize>readPixelSizeLast) {
-            readPixelBuffer = Buffers.newDirectByteBuffer(readPixelSize);
-            readPixelSizeLast = readPixelSize ;
+        if( null == readPixelBuffer || readPixelBuffer.requiresNewBuffer(gl, width, height, readPixelSize) ) {
+            readPixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, width, height, 1, true, readPixelSize);
+            Buffers.rangeCheckBytes(readPixelBuffer.buffer, readPixelSize);
             try {
                 readTextureData = new TextureData(
                            gl.getGLProfile(),
-                           textureInternalFormat,
-                           drawable.getWidth(), drawable.getHeight(),
+                           internalFormat,
+                           width, height,
                            0, 
-                           textureDataFormat,
-                           textureDataType,
+                           pixelAttribs,
                            false, false, 
-                           flip,
-                           readPixelBuffer,
+                           flipVertically,
+                           readPixelBuffer.buffer,
                            null /* Flusher */);
                 newData = true;
             } catch (Exception e) {
                 readTextureData = null;
                 readPixelBuffer = null;
-                readPixelSizeLast = 0;
                 throw new RuntimeException("can not fetch offscreen texture", e);
             }
         } else {
-            readTextureData.setInternalFormat(textureInternalFormat);
-            readTextureData.setWidth(drawable.getWidth());
-            readTextureData.setHeight(drawable.getHeight());
-            readTextureData.setPixelFormat(textureDataFormat);
-            readTextureData.setPixelType(textureDataType);
+            readTextureData.setInternalFormat(internalFormat);
+            readTextureData.setWidth(width);
+            readTextureData.setHeight(height);
+            readTextureData.setPixelAttributes(pixelAttribs);
         }
-        boolean res = null!=readPixelBuffer;
+        boolean res = null!=readPixelBuffer && readPixelBuffer.isValid();
         if(res) {
             psm.setAlignment(gl, alignment, alignment);
+            if(gl.isGL2GL3()) {
+                gl.getGL2GL3().glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, readPixelBuffer.width);
+            }
             readPixelBuffer.clear();
             try {
-                gl.glReadPixels(0, 0, drawable.getWidth(), drawable.getHeight(), textureDataFormat, textureDataType, readPixelBuffer);
+                gl.glReadPixels(inX, inY, width, height, pixelAttribs.format, pixelAttribs.type, readPixelBuffer.buffer);
             } catch(GLException gle) { res = false; gle.printStackTrace(); }
-            readPixelBuffer.position(readPixelSize);
+            readPixelBuffer.position( readPixelSize );
             readPixelBuffer.flip();
             final int glerr1 = gl.glGetError();
             if(GL.GL_NO_ERROR != glerr1) {
                 System.err.println("GLReadBufferUtil.readPixels: readPixels error 0x"+Integer.toHexString(glerr1)+
-                                   " "+drawable.getWidth()+"x"+drawable.getHeight()+
-                                   ", fmt 0x"+Integer.toHexString(textureDataFormat)+", type 0x"+Integer.toHexString(textureDataType)+
-                                   ", impl-fmt 0x"+Integer.toHexString(glImplColorReadVals[0])+", impl-type 0x"+Integer.toHexString(glImplColorReadVals[1])+
+                                   " "+width+"x"+height+
+                                   ", "+pixelAttribs+
                                    ", "+readPixelBuffer+", sz "+readPixelSize);
                 res = false;                
             }
@@ -200,7 +240,7 @@ public class GLReadBufferUtil {
                     readTexture.updateSubImage(gl, readTextureData, 0, 
                                                0, 0, // src offset
                                                0, 0, // dst offset
-                                               drawable.getWidth(), drawable.getHeight());
+                                               width, height);
                 }
                 readPixelBuffer.rewind();
             }
@@ -215,10 +255,9 @@ public class GLReadBufferUtil {
             readTextureData = null;
         }
         if(null != readPixelBuffer) {
-            readPixelBuffer.clear();
+            readPixelBuffer.dispose();
             readPixelBuffer = null;
         }
-        readPixelSizeLast = 0;
     }
 
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
index f01896b..27ce7d8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java
@@ -35,7 +35,7 @@ import com.jogamp.opengl.util.glsl.ShaderState;
  * via {@link #glEnd(GL, boolean) glEnd(gl, false)} for deferred rendering via {@link #draw(GL, boolean)}.
  * </p>
  * <a name="storageDetails"><h5>Buffer storage and it's creation via {@link #createFixed(int, int, int, int, int, int, int, int, int, int) createFixed(..)} 
- * and {@link #createGLSL(int, int, int, int, int, int, int, int, int, int) createGLSL(..)}</h5></a> 
+ * and {@link #createGLSL(int, int, int, int, int, int, int, int, int, int, ShaderState) createGLSL(..)}</h5></a> 
  * <p>
  * If unsure whether <i>colors</i>, <i>normals</i> and <i>textures</i> will be used, 
  * simply add them with an expected component count.
@@ -82,13 +82,11 @@ public class ImmModeSink {
                                         int glBufferUsage) {
     return new ImmModeSink(initialElementCount, 
                            vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, 
-                           false, glBufferUsage);
+                           false, glBufferUsage, null, 0);
   }
 
   /**
-   * Uses a GL2ES2 GLSL shader immediate mode sink.
-   * To issue the draw() command,
-   * a ShaderState must be current, using ShaderState.glUseProgram().
+   * Uses a GL2ES2 GLSL shader immediate mode sink, utilizing the given ShaderState.
    * <p>
    * See <a href="#storageDetails"> buffer storage details</a>.
    * </p>
@@ -104,7 +102,7 @@ public class ImmModeSink {
    * @param tDataType optional texture-coordinate data type, e.g. {@link GL#GL_FLOAT}
    * @param glBufferUsage VBO <code>usage</code> parameter for {@link GL#glBufferData(int, long, Buffer, int)}, e.g. {@link GL#GL_STATIC_DRAW}, 
    *                      set to <code>0</code> for no VBO usage
-   * 
+   * @param st ShaderState to locate the vertex attributes
    * @see #draw(GL, boolean)
    * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
    * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
@@ -114,12 +112,45 @@ public class ImmModeSink {
                                        int cComps, int cDataType,
                                        int nComps, int nDataType, 
                                        int tComps, int tDataType, 
-                                       int glBufferUsage) {
+                                       int glBufferUsage, ShaderState st) {
     return new ImmModeSink(initialElementCount, 
                            vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, 
-                           true, glBufferUsage);
+                           true, glBufferUsage, st, 0);
   }
 
+  /**
+   * Uses a GL2ES2 GLSL shader immediate mode sink, utilizing the given shader-program.
+   * <p>
+   * See <a href="#storageDetails"> buffer storage details</a>.
+   * </p>
+   * 
+   * @param initialElementCount initial buffer size, if subsequent mutable operations are about to exceed the buffer size, the buffer will grow about the initial size.
+   * @param vComps mandatory vertex component count, should be 2, 3 or 4.
+   * @param vDataType mandatory vertex data type, e.g. {@link GL#GL_FLOAT}
+   * @param cComps optional color component count, may be 0, 3 or 4
+   * @param cDataType optional color data type, e.g. {@link GL#GL_FLOAT}
+   * @param nComps optional normal component count, may be 0, 3 or 4
+   * @param nDataType optional normal data type, e.g. {@link GL#GL_FLOAT}
+   * @param tComps optional texture-coordinate  component count, may be 0, 2 or 3
+   * @param tDataType optional texture-coordinate data type, e.g. {@link GL#GL_FLOAT}
+   * @param glBufferUsage VBO <code>usage</code> parameter for {@link GL#glBufferData(int, long, Buffer, int)}, e.g. {@link GL#GL_STATIC_DRAW}, 
+   *                      set to <code>0</code> for no VBO usage
+   * @param shaderProgram shader-program name to locate the vertex attributes
+   * @see #draw(GL, boolean)
+   * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
+   * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
+   */
+  public static ImmModeSink createGLSL(int initialElementCount, 
+                                       int vComps, int vDataType,
+                                       int cComps, int cDataType,
+                                       int nComps, int nDataType, 
+                                       int tComps, int tDataType, 
+                                       int glBufferUsage, int shaderProgram) {
+    return new ImmModeSink(initialElementCount, 
+                           vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, 
+                           true, glBufferUsage, null, shaderProgram);
+  }
+  
   public void destroy(GL gl) {
     destroyList(gl);
 
@@ -330,10 +361,10 @@ public class ImmModeSink {
                         int cComps, int cDataType, 
                         int nComps, int nDataType, 
                         int tComps, int tDataType, 
-                        boolean useGLSL, int glBufferUsage) {
-    vboSet = new  VBOSet(initialElementCount, 
-                         vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, 
-                         useGLSL, glBufferUsage);
+                        boolean useGLSL, int glBufferUsage, ShaderState st, int shaderProgram) {
+    vboSet = new VBOSet(initialElementCount, 
+                        vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, 
+                        useGLSL, glBufferUsage, st, shaderProgram);
     this.vboSetList   = new ArrayList<VBOSet>();
   }
   
@@ -349,7 +380,7 @@ public class ImmModeSink {
    * Sets the additional element count if buffer resize is required,
    * defaults to <code>initialElementCount</code> of factory method.
    * @see #createFixed(int, int, int, int, int, int, int, int, int, int)
-   * @see #createGLSL(int, int, int, int, int, int, int, int, int, int)
+   * @see #createGLSL(int, int, int, int, int, int, int, int, int, int, ShaderState)
    */
   public void setResizeElementCount(int v) { vboSet.setResizeElementCount(v); }
   
@@ -369,9 +400,19 @@ public class ImmModeSink {
                       int cComps, int cDataType, 
                       int nComps, int nDataType, 
                       int tComps, int tDataType, 
-                      boolean useGLSL, int glBufferUsage) {
+                      boolean useGLSL, int glBufferUsage, ShaderState st, int shaderProgram) {
+        // final ..
         this.glBufferUsage=glBufferUsage;
         this.initialElementCount=initialElementCount;
+        this.useVBO = 0 != glBufferUsage;
+        this.useGLSL=useGLSL;
+        this.shaderState = st;
+        this.shaderProgram = shaderProgram;
+        
+        if(useGLSL && null == shaderState && 0 == shaderProgram) {
+            throw new IllegalArgumentException("Using GLSL but neither a valid shader-program nor ShaderState has been passed!");
+        }
+        // variable ..
         this.resizeElementCount=initialElementCount;
         this.vDataType=vDataType;
         this.vDataTypeSigned=GLBuffers.isSignedGLType(vDataType);
@@ -389,8 +430,6 @@ public class ImmModeSink {
         this.tDataTypeSigned=GLBuffers.isSignedGLType(tDataType);
         this.tComps=tComps;
         this.tCompsBytes=tComps * GLBuffers.sizeOfGLType(tDataType); 
-        this.useGLSL=useGLSL;
-        this.useVBO = 0 != glBufferUsage;
         this.vboName = 0;
                 
         this.vCount=0;
@@ -414,6 +453,7 @@ public class ImmModeSink {
         this.bufferEnabled=false;
         this.bufferWritten=false;
         this.bufferWrittenOnce=false;
+        this.glslLocationSet = false;
     }
 
     protected int getResizeElementCount() { return resizeElementCount; }
@@ -423,7 +463,8 @@ public class ImmModeSink {
     
     protected final VBOSet regenerate(GL gl) {
         return new VBOSet(initialElementCount, vComps, 
-                          vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL, glBufferUsage);
+                          vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, 
+                          useGLSL, glBufferUsage, shaderState, shaderProgram);
     }
 
     protected void checkSeal(boolean test) throws GLException {
@@ -439,10 +480,27 @@ public class ImmModeSink {
         }
     }
 
+    private boolean usingShaderProgram = false;
+    
+    protected void useShaderProgram(GL2ES2 gl, boolean force) {
+        if( force || !usingShaderProgram ) {
+            if(null != shaderState) {
+                shaderState.useProgram(gl, true);
+            } else /* if( 0 != shaderProgram) */ {
+                gl.glUseProgram(shaderProgram);
+            }
+            usingShaderProgram = true;
+        }
+    }
+    
     protected void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw, int i)
     {
         enableBuffer(gl, true);
-
+        
+        if(null != shaderState || 0 != shaderProgram) {
+            useShaderProgram(gl.getGL2ES2(), false);
+        }
+        
         if(DEBUG_DRAW) {
             System.err.println("ImmModeSink.draw["+i+"].0 (disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this);
         }
@@ -788,6 +846,51 @@ public class ImmModeSink {
         }
     }
 
+    public void setShaderProgram(int program) {
+        if(null == shaderState && 0 == program) {
+            throw new IllegalArgumentException("Not allowed to zero shader program if no ShaderState is set");
+        }
+        shaderProgram = program;
+        glslLocationSet = false; // enforce location reset!
+    }
+    
+    /**
+     * @param gl
+     * @return true if all locations for all used arrays are found (min 1 array), otherwise false.
+     *         Also sets 'glslLocationSet' to the return value! 
+     */
+    private boolean resetGLSLArrayLocation(GL2ES2 gl) {
+        int iA = 0;
+        int iL = 0;
+        
+        if(null != vArrayData) {
+            iA++;
+            if( vArrayData.setLocation(gl, shaderProgram) >= 0 ) {
+                iL++;  
+            }
+        }
+        if(null != cArrayData) {
+            iA++;
+            if( cArrayData.setLocation(gl, shaderProgram) >= 0 ) {
+                iL++;
+            }
+        }
+        if(null != nArrayData) {
+            iA++;
+            if( nArrayData.setLocation(gl, shaderProgram) >= 0 ) {
+                iL++;
+            }
+        }
+        if(null != tArrayData) {
+            iA++;
+            if( tArrayData.setLocation(gl, shaderProgram) >= 0 ) {
+                iL++;
+            }
+        }
+        glslLocationSet = iA == iL;
+        return glslLocationSet;
+    }
+    
     public void destroy(GL gl) {
         reset(gl);
 
@@ -868,8 +971,13 @@ public class ImmModeSink {
             checkSeal(true);
         }
         bufferEnabled = enable;
-        if(useGLSL) { 
-            enableBufferGLSL(gl, enable);
+        if(useGLSL) {
+            useShaderProgram(gl.getGL2ES2(), true);
+            if(null != shaderState) {
+                enableBufferGLSLShaderState(gl, enable);
+            } else {
+                enableBufferGLSLSimple(gl, enable);
+            }
         } else {
             enableBufferFixed(gl, enable);
         }
@@ -901,7 +1009,7 @@ public class ImmModeSink {
     }                      
   }
   
-  public void enableBufferFixed(GL gl, boolean enable) {
+  private void enableBufferFixed(GL gl, boolean enable) {
     GL2ES1 glf = gl.getGL2ES1();
     
     final boolean useV = vComps>0 && vElems>0 ;
@@ -969,11 +1077,75 @@ public class ImmModeSink {
     }
   }
 
-  public void enableBufferGLSL(GL gl, boolean enable) {
-    ShaderState st = ShaderState.getShaderState(gl);
-    if(null==st) {
-        throw new GLException("No ShaderState in "+gl);
-    }      
+  private void enableBufferGLSLShaderState(GL gl, boolean enable) {
+    GL2ES2 glsl = gl.getGL2ES2();
+ 
+    final boolean useV = vComps>0 && vElems>0 ;
+    final boolean useC = cComps>0 && cElems>0 ;
+    final boolean useN = nComps>0 && nElems>0 ;
+    final boolean useT = tComps>0 && tElems>0 ;
+    
+    if(DEBUG_DRAW) {
+        System.err.println("ImmModeSink.enableGLSL.A.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer);        
+    }
+    
+    if(enable) {
+        if(useVBO) {
+            if(0 == vboName) {
+                throw new InternalError("Using VBO but no vboName");
+            }
+            glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName);
+            if(!bufferWritten) {
+                writeBuffer(gl);
+            }
+        }
+        bufferWritten=true;        
+    }
+    
+    if(useV) {
+       if(enable) {
+           shaderState.enableVertexAttribArray(glsl, vArrayData);
+           shaderState.vertexAttribPointer(glsl, vArrayData);
+       } else {
+           shaderState.disableVertexAttribArray(glsl, vArrayData);
+       }
+    }
+    if(useC) {
+       if(enable) {
+           shaderState.enableVertexAttribArray(glsl, cArrayData);
+           shaderState.vertexAttribPointer(glsl, cArrayData);
+       } else {
+           shaderState.disableVertexAttribArray(glsl, cArrayData);
+       }
+    }
+    if(useN) {
+       if(enable) {
+           shaderState.enableVertexAttribArray(glsl, nArrayData);
+           shaderState.vertexAttribPointer(glsl, nArrayData);
+       } else {
+           shaderState.disableVertexAttribArray(glsl, nArrayData);
+       }
+    }
+    if(useT) {
+       if(enable) {
+           shaderState.enableVertexAttribArray(glsl, tArrayData);
+           shaderState.vertexAttribPointer(glsl, tArrayData);
+       } else {
+           shaderState.disableVertexAttribArray(glsl, tArrayData);
+       }
+    }    
+    glslLocationSet = true; // ShaderState does set the location implicit
+    
+    if(enable && useVBO) {
+        glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+    }
+    
+    if(DEBUG_DRAW) {
+        System.err.println("ImmModeSink.enableGLSL.A.X ");        
+    }
+  }
+
+  private void enableBufferGLSLSimple(GL gl, boolean enable) {
     GL2ES2 glsl = gl.getGL2ES2();
  
     final boolean useV = vComps>0 && vElems>0 ;
@@ -982,7 +1154,20 @@ public class ImmModeSink {
     final boolean useT = tComps>0 && tElems>0 ;
     
     if(DEBUG_DRAW) {
-        System.err.println("ImmModeSink.enableGLSL.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer);        
+        System.err.println("ImmModeSink.enableGLSL.B.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer);        
+    }
+    
+    if(!glslLocationSet) {
+        if( !resetGLSLArrayLocation(glsl) ) {
+            if(DEBUG_DRAW) {
+                final int vLoc = null != vArrayData ? vArrayData.getLocation() : -1;
+                final int cLoc = null != cArrayData ? cArrayData.getLocation() : -1;
+                final int nLoc = null != nArrayData ? nArrayData.getLocation() : -1;
+                final int tLoc = null != tArrayData ? tArrayData.getLocation() : -1;
+                System.err.println("ImmModeSink.enableGLSL.B.X attribute locations in shader program "+shaderProgram+", incomplete ["+vLoc+", "+cLoc+", "+nLoc+", "+tLoc+"] - glslLocationSet "+glslLocationSet);
+            }
+            return;
+        }
     }
     
     if(enable) {
@@ -1000,34 +1185,34 @@ public class ImmModeSink {
 
     if(useV) {
        if(enable) {
-           st.enableVertexAttribArray(glsl, vArrayData);
-           st.vertexAttribPointer(glsl, vArrayData);
+           glsl.glEnableVertexAttribArray(vArrayData.getLocation());
+           glsl.glVertexAttribPointer(vArrayData);
        } else {
-           st.disableVertexAttribArray(glsl, vArrayData);
+           glsl.glDisableVertexAttribArray(vArrayData.getLocation());
        }
     }
     if(useC) {
        if(enable) {
-           st.enableVertexAttribArray(glsl, cArrayData);
-           st.vertexAttribPointer(glsl, cArrayData);
+           glsl.glEnableVertexAttribArray(cArrayData.getLocation());
+           glsl.glVertexAttribPointer(cArrayData);
        } else {
-           st.disableVertexAttribArray(glsl, cArrayData);
+           glsl.glDisableVertexAttribArray(cArrayData.getLocation());
        }
     }
     if(useN) {
        if(enable) {
-           st.enableVertexAttribArray(glsl, nArrayData);
-           st.vertexAttribPointer(glsl, nArrayData);
+           glsl.glEnableVertexAttribArray(nArrayData.getLocation());
+           glsl.glVertexAttribPointer(nArrayData);
        } else {
-           st.disableVertexAttribArray(glsl, nArrayData);
+           glsl.glDisableVertexAttribArray(nArrayData.getLocation());
        }
     }
     if(useT) {
        if(enable) {
-           st.enableVertexAttribArray(glsl, tArrayData);
-           st.vertexAttribPointer(glsl, tArrayData);
+           glsl.glEnableVertexAttribArray(tArrayData.getLocation());
+           glsl.glVertexAttribPointer(tArrayData);
        } else {
-           st.disableVertexAttribArray(glsl, tArrayData);
+           glsl.glDisableVertexAttribArray(tArrayData.getLocation());
        }
     }
     
@@ -1036,11 +1221,16 @@ public class ImmModeSink {
     }
     
     if(DEBUG_DRAW) {
-        System.err.println("ImmModeSink.enableGLSL.X ");        
+        System.err.println("ImmModeSink.enableGLSL.B.X ");        
     }
   }
-
+  
     public String toString() {
+        final String glslS = useGLSL ? 
+                       ", useShaderState "+(null!=shaderState)+
+                       ", shaderProgram "+shaderProgram+
+                       ", glslLocationSet "+glslLocationSet : "";
+        
         return "VBOSet[mode "+mode+ 
                        ", modeOrig "+modeOrig+ 
                        ", use/count "+getElemUseCountStr()+
@@ -1049,6 +1239,8 @@ public class ImmModeSink {
                        ", bufferEnabled "+bufferEnabled+ 
                        ", bufferWritten "+bufferWritten+" (once "+bufferWrittenOnce+")"+
                        ", useVBO "+useVBO+", vboName "+vboName+
+                       ", useGLSL "+useGLSL+
+                       glslS+
                        ",\n\t"+vArrayData+
                        ",\n\t"+cArrayData+
                        ",\n\t"+nArrayData+
@@ -1264,7 +1456,9 @@ public class ImmModeSink {
     }
 
     final private int glBufferUsage, initialElementCount;
-    final private boolean useVBO;
+    final private boolean useVBO, useGLSL;
+    final private ShaderState shaderState;
+    private int shaderProgram;
     private int mode, modeOrig, resizeElementCount;
 
     private ByteBuffer buffer;
@@ -1286,8 +1480,9 @@ public class ImmModeSink {
     private Buffer vertexArray, colorArray, normalArray, textCoordArray;
     private GLArrayDataWrapper vArrayData, cArrayData, nArrayData, tArrayData;
 
-    private boolean sealed, sealedGL, useGLSL;
+    private boolean sealed, sealedGL;    
     private boolean bufferEnabled, bufferWritten, bufferWrittenOnce;
+    private boolean glslLocationSet;
   }
 
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
index 80df9cd..5815185 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
@@ -37,8 +37,6 @@ package com.jogamp.opengl.util;
 import java.nio.Buffer;
 import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
-import java.util.ArrayList;
-import java.util.List;
 
 import javax.media.opengl.GL;
 import javax.media.opengl.GLException;
@@ -46,9 +44,11 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc;
 
 import jogamp.opengl.ProjectFloat;
 
-import com.jogamp.opengl.FloatUtil;
 import com.jogamp.common.nio.Buffers;
 import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.FloatStack;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.geom.Frustum;
 
 /**
  * PMVMatrix implements a subset of the fixed function pipeline
@@ -57,7 +57,8 @@ import com.jogamp.common.os.Platform;
  * <p>
  * Further more, PMVMatrix provides the {@link #glGetMviMatrixf() inverse modelview matrix (Mvi)} and 
  * {@link #glGetMvitMatrixf() inverse transposed modelview matrix (Mvit)}.
- * To keep both synchronized after mutable Mv operations like {@link #glRotatef(float, float, float, float) glRotatef(..)}
+ * {@link Frustum} is also provided by {@link #glGetFrustum()}.
+ * To keep these derived values synchronized after mutable Mv operations like {@link #glRotatef(float, float, float, float) glRotatef(..)}
  * in {@link #glMatrixMode(int) glMatrixMode}({@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}), 
  * users have to call {@link #update()} before using Mvi and Mvit. 
  * </p>
@@ -100,8 +101,10 @@ public class PMVMatrix implements GLMatrixFunc {
     public static final int DIRTY_INVERSE_MODELVIEW             = 1 << 0;
     /** Bit value stating a dirty {@link #glGetMvitMatrixf() inverse transposed modelview matrix (Mvit)}. */
     public static final int DIRTY_INVERSE_TRANSPOSED_MODELVIEW  = 1 << 1;    
+    /** Bit value stating a dirty {@link #glGetFrustum() frustum}. */
+    public static final int DIRTY_FRUSTUM                       = 1 << 2;    
     /** Bit value stating all is dirty */
-    public static final int DIRTY_ALL                           = DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
+    public static final int DIRTY_ALL                           = DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM;
     
     /**
      * @param matrixModeName One of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}  
@@ -256,9 +259,11 @@ public class PMVMatrix implements GLMatrixFunc {
           FloatUtil.makeIdentityf(matrixOrtho, 0);
           FloatUtil.makeZero(matrixFrustum, 0);
 
-          matrixPStack = new ArrayList<float[]>();
-          matrixMvStack= new ArrayList<float[]>();
-
+          // Start w/ zero size to save memory
+          matrixTStack = new FloatStack( 0,  2*16); // growSize: GL-min size (2)
+          matrixPStack = new FloatStack( 0,  2*16); // growSize: GL-min size (2)
+          matrixMvStack= new FloatStack( 0, 16*16); // growSize: half GL-min size (32)
+          
           // default values and mode
           glMatrixMode(GL_PROJECTION);
           glLoadIdentity();
@@ -270,6 +275,9 @@ public class PMVMatrix implements GLMatrixFunc {
           dirtyBits = DIRTY_ALL;
           requestMask = 0;
           matrixMode = GL_MODELVIEW;
+          
+          mulPMV = null;
+          frustum = null;
     }
 
     /** @see #PMVMatrix(boolean) */
@@ -293,16 +301,16 @@ public class PMVMatrix implements GLMatrixFunc {
         matrixFrustum = null;
         
         if(null!=matrixPStack) {
-            matrixPStack.clear(); matrixPStack=null;
+            matrixPStack=null;
         }
         if(null!=matrixMvStack) {
-            matrixMvStack.clear(); matrixMvStack=null;
+            matrixMvStack=null;
         }
         if(null!=matrixPStack) {
-            matrixPStack.clear(); matrixPStack=null;
+            matrixPStack=null;
         }
         if(null!=matrixTStack) {
-            matrixTStack.clear(); matrixTStack=null;
+            matrixTStack=null;
         }
     }
 
@@ -351,7 +359,7 @@ public class PMVMatrix implements GLMatrixFunc {
      * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
      * </p>
      * @see #update()
-     * @see #disableMviMvitUpdate()
+     * @see #clearAllUpdateRequests()
      */
     public final FloatBuffer glGetMviMatrixf() {
         requestMask |= DIRTY_INVERSE_MODELVIEW ;
@@ -368,7 +376,7 @@ public class PMVMatrix implements GLMatrixFunc {
      * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
      * </p>
      * @see #update()
-     * @see #disableMviMvitUpdate()
+     * @see #clearAllUpdateRequests()
      */
     public final FloatBuffer glGetMvitMatrixf() {
         requestMask |= DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
@@ -385,7 +393,7 @@ public class PMVMatrix implements GLMatrixFunc {
     public final FloatBuffer glGetPMvMatrixf() {
         return matrixPMv;
     }
-
+    
     /** 
      * Returns 3 matrices within one FloatBuffer: {@link #glGetPMatrixf() P}, {@link #glGetMvMatrixf() Mv} and {@link #glGetMviMatrixf() Mvi}.  
      * <p>
@@ -395,7 +403,7 @@ public class PMVMatrix implements GLMatrixFunc {
      * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
      * </p>
      * @see #update()
-     * @see #disableMviMvitUpdate()
+     * @see #clearAllUpdateRequests()
      */
     public final FloatBuffer glGetPMvMviMatrixf() {
         requestMask |= DIRTY_INVERSE_MODELVIEW ;
@@ -412,7 +420,7 @@ public class PMVMatrix implements GLMatrixFunc {
      * See {@link #update()} and <a href="#storageDetails"> matrix storage details</a>.
      * </p>
      * @see #update()
-     * @see #disableMviMvitUpdate()
+     * @see #clearAllUpdateRequests()
      */
     public final FloatBuffer glGetPMvMvitMatrixf() {
         requestMask |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
@@ -420,6 +428,13 @@ public class PMVMatrix implements GLMatrixFunc {
         return matrixPMvMvit;
     }
     
+    /** Returns the frustum, derived from projection * modelview */
+    public Frustum glGetFrustum() {
+        requestMask |= DIRTY_FRUSTUM;
+        updateImpl(false);
+        return frustum;
+    }
+        
     /*
      * @return the matrix of the current matrix-mode
      */
@@ -473,7 +488,7 @@ public class PMVMatrix implements GLMatrixFunc {
         if(matrixGetName==GL_MATRIX_MODE) {
             params.put((float)matrixMode);
         } else {
-            FloatBuffer matrix = glGetMatrixf(matrixGetName);
+            final FloatBuffer matrix = glGetMatrixf(matrixGetName);
             params.put(matrix); // matrix -> params
             matrix.reset();
         }
@@ -485,7 +500,7 @@ public class PMVMatrix implements GLMatrixFunc {
         if(matrixGetName==GL_MATRIX_MODE) {
             params[params_offset]=(float)matrixMode;
         } else {
-            FloatBuffer matrix = glGetMatrixf(matrixGetName);
+            final FloatBuffer matrix = glGetMatrixf(matrixGetName);
             matrix.get(params, params_offset, 16); // matrix -> params
             matrix.reset();
         }
@@ -513,18 +528,18 @@ public class PMVMatrix implements GLMatrixFunc {
 
     @Override
     public final void glLoadMatrixf(final float[] values, final int offset) {
-        int len = values.length-offset;
         if(matrixMode==GL_MODELVIEW) {
-            matrixMv.put(values, offset, len);
+            matrixMv.put(values, offset, 16);
             matrixMv.reset();
-            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
+            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
             modifiedBits |= MODIFIED_MODELVIEW;
         } else if(matrixMode==GL_PROJECTION) {
-            matrixP.put(values, offset, len);
+            matrixP.put(values, offset, 16);
             matrixP.reset();
+            dirtyBits |= DIRTY_FRUSTUM ;
             modifiedBits |= MODIFIED_PROJECTION;            
         } else if(matrixMode==GL.GL_TEXTURE) {
-            matrixTex.put(values, offset, len);
+            matrixTex.put(values, offset, 16);
             matrixTex.reset();
             modifiedBits |= MODIFIED_TEXTURE;
         } 
@@ -536,11 +551,12 @@ public class PMVMatrix implements GLMatrixFunc {
         if(matrixMode==GL_MODELVIEW) {
             matrixMv.put(m);
             matrixMv.reset();
-            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
+            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
             modifiedBits |= MODIFIED_MODELVIEW;
         } else if(matrixMode==GL_PROJECTION) {
             matrixP.put(m);
             matrixP.reset();
+            dirtyBits |= DIRTY_FRUSTUM ;
             modifiedBits |= MODIFIED_PROJECTION;            
         } else if(matrixMode==GL.GL_TEXTURE) {
             matrixTex.put(m);
@@ -552,32 +568,31 @@ public class PMVMatrix implements GLMatrixFunc {
 
     @Override
     public final void glPopMatrix() {
-        float[] stackEntry=null;
+        final FloatStack stack;
         if(matrixMode==GL_MODELVIEW) {
-            stackEntry = matrixMvStack.remove(0);
+            stack = matrixMvStack;
         } else if(matrixMode==GL_PROJECTION) {
-            stackEntry = matrixPStack.remove(0);
+            stack = matrixPStack;
         } else if(matrixMode==GL.GL_TEXTURE) {
-            stackEntry = matrixTStack.remove(0);
-        } 
-        glLoadMatrixf(stackEntry, 0);
+            stack = matrixTStack;
+        } else {
+            throw new InternalError("XXX: mode "+matrixMode);
+        }
+        stack.position(stack.position() - 16);
+        glLoadMatrixf(stack.buffer(), stack.position());
     }
 
     @Override
     public final void glPushMatrix() {
-        float[] stackEntry = new float[1*16];
-        if(matrixMode==GL_MODELVIEW) {
-            matrixMv.get(stackEntry);
-            matrixMv.reset();
-            matrixMvStack.add(0, stackEntry);
+        if(matrixMode==GL_MODELVIEW) { 
+            matrixMvStack.putOnTop(matrixMv, 16);
+            matrixMv.reset();            
         } else if(matrixMode==GL_PROJECTION) {
-            matrixP.get(stackEntry);
+            matrixPStack.putOnTop(matrixP, 16);
             matrixP.reset();
-            matrixPStack.add(0, stackEntry);
         } else if(matrixMode==GL.GL_TEXTURE) {
-            matrixTex.get(stackEntry);
+            matrixTStack.putOnTop(matrixTex, 16);
             matrixTex.reset();
-            matrixTStack.add(0, stackEntry);
         }
     }
 
@@ -586,12 +601,13 @@ public class PMVMatrix implements GLMatrixFunc {
         if(matrixMode==GL_MODELVIEW) {
             matrixMv.put(matrixIdent);
             matrixMv.reset();
-            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
+            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
             modifiedBits |= MODIFIED_MODELVIEW;
         } else if(matrixMode==GL_PROJECTION) {
             matrixP.put(matrixIdent);
             matrixP.reset();
-            modifiedBits |= MODIFIED_PROJECTION;            
+            dirtyBits |= DIRTY_FRUSTUM ;
+            modifiedBits |= MODIFIED_PROJECTION;
         } else if(matrixMode==GL.GL_TEXTURE) {
             matrixTex.put(matrixIdent);
             matrixTex.reset();
@@ -603,14 +619,15 @@ public class PMVMatrix implements GLMatrixFunc {
     @Override
     public final void glMultMatrixf(final FloatBuffer m) {
         if(matrixMode==GL_MODELVIEW) {
-            FloatUtil.multMatrixf(matrixMv, m, matrixMv);
-            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
+            FloatUtil.multMatrixf(matrixMv, m);
+            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
             modifiedBits |= MODIFIED_MODELVIEW;
         } else if(matrixMode==GL_PROJECTION) {
-            FloatUtil.multMatrixf(matrixP, m, matrixP);
+            FloatUtil.multMatrixf(matrixP, m);
+            dirtyBits |= DIRTY_FRUSTUM ;
             modifiedBits |= MODIFIED_PROJECTION;
         } else if(matrixMode==GL.GL_TEXTURE) {
-            FloatUtil.multMatrixf(matrixTex, m, matrixTex);
+            FloatUtil.multMatrixf(matrixTex, m);
             modifiedBits |= MODIFIED_TEXTURE;
         } 
     }
@@ -618,14 +635,15 @@ public class PMVMatrix implements GLMatrixFunc {
     @Override
     public final void glMultMatrixf(float[] m, int m_offset) {
         if(matrixMode==GL_MODELVIEW) {
-            FloatUtil.multMatrixf(matrixMv, m, m_offset, matrixMv);
-            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW ;
+            FloatUtil.multMatrixf(matrixMv, m, m_offset);
+            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
             modifiedBits |= MODIFIED_MODELVIEW;
         } else if(matrixMode==GL_PROJECTION) {
-            FloatUtil.multMatrixf(matrixP, m, m_offset, matrixP);
+            FloatUtil.multMatrixf(matrixP, m, m_offset);
+            dirtyBits |= DIRTY_FRUSTUM ;
             modifiedBits |= MODIFIED_PROJECTION;
         } else if(matrixMode==GL.GL_TEXTURE) {
-            FloatUtil.multMatrixf(matrixTex, m, m_offset, matrixTex);
+            FloatUtil.multMatrixf(matrixTex, m, m_offset);
             modifiedBits |= MODIFIED_TEXTURE;
         } 
     }
@@ -795,8 +813,8 @@ public class PMVMatrix implements GLMatrixFunc {
                             float[] win_pos, int win_pos_offset ) {
         if(usesBackingArray) {
             return projectFloat.gluProject(objx, objy, objz,
-                                           matrixMv.array(), 0,
-                                           matrixP.array(), 0,
+                                           matrixMv.array(), matrixMv.position(),
+                                           matrixP.array(), matrixP.position(),
                                            viewport, viewport_offset, 
                                            win_pos, win_pos_offset);
         } else {
@@ -820,13 +838,13 @@ public class PMVMatrix implements GLMatrixFunc {
      * @param obj_pos_offset
      * @return
      */
-    public boolean gluUnProject(float winx, float winy, float winz,
-                              int[] viewport, int viewport_offset,
-                              float[] obj_pos, int obj_pos_offset) {
+    public final boolean gluUnProject(float winx, float winy, float winz,
+                                      int[] viewport, int viewport_offset,
+                                      float[] obj_pos, int obj_pos_offset) {
         if(usesBackingArray) {
             return projectFloat.gluUnProject(winx, winy, winz,
-                                             matrixMv.array(), 0,
-                                             matrixP.array(), 0,
+                                             matrixMv.array(), matrixMv.position(),
+                                             matrixP.array(), matrixP.position(),
                                              viewport, viewport_offset, 
                                              obj_pos, obj_pos_offset);
         } else {
@@ -850,15 +868,17 @@ public class PMVMatrix implements GLMatrixFunc {
         }
         final boolean mviDirty  = 0 != (DIRTY_INVERSE_MODELVIEW & dirtyBits);
         final boolean mvitDirty = 0 != (DIRTY_INVERSE_TRANSPOSED_MODELVIEW & dirtyBits);
+        final boolean frustumDirty = 0 != (DIRTY_FRUSTUM & dirtyBits);
         final boolean mviReq = 0 != (DIRTY_INVERSE_MODELVIEW & requestMask);
         final boolean mvitReq = 0 != (DIRTY_INVERSE_TRANSPOSED_MODELVIEW & requestMask);
+        final boolean frustumReq = 0 != (DIRTY_FRUSTUM & requestMask);
         final boolean modP = 0 != ( MODIFIED_PROJECTION & modifiedBits );
         final boolean modMv = 0 != ( MODIFIED_MODELVIEW & modifiedBits );
-        final boolean modT = 0 != ( MODIFIED_TEXTURE & modifiedBits );
+        final boolean modT = 0 != ( MODIFIED_TEXTURE & modifiedBits );        
         
         sb.append("PMVMatrix[backingArray ").append(this.usesBackingArray());
         sb.append(", modified[P ").append(modP).append(", Mv ").append(modMv).append(", T ").append(modT);
-        sb.append("], dirty/req[Mvi ").append(mviDirty).append("/").append(mviReq).append(", Mvit ").append(mvitDirty).append("/").append(mvitReq);
+        sb.append("], dirty/req[Mvi ").append(mviDirty).append("/").append(mviReq).append(", Mvit ").append(mvitDirty).append("/").append(mvitReq).append(", Frustum ").append(frustumDirty).append("/").append(frustumReq);
         sb.append("], Projection").append(Platform.NEWLINE);
         matrixToString(sb, f, matrixP);
         sb.append(", Modelview").append(Platform.NEWLINE);
@@ -905,17 +925,20 @@ public class PMVMatrix implements GLMatrixFunc {
      * Returns the dirty bits due to mutable operations.
      * <p>
      * A dirty bit is set , if the corresponding matrix had been modified by a mutable operation
-     * since last {@link #update()} call. The latter clears the dirty state only if the dirty matrix (Mvi or Mvit)
-     * has been requested by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods.
+     * since last {@link #update()} call. The latter clears the dirty state only if the dirty matrix (Mvi or Mvit) or {@link Frustum}
+     * has been requested by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get} 
+     * or {@link #glGetFrustum() Frustum get} methods.
      * </p>
      * 
      * @deprecated Function is exposed for debugging purposes only.
      * @see #DIRTY_INVERSE_MODELVIEW
      * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW
+     * @see #DIRTY_FRUSTUM
      * @see #glGetMviMatrixf()
      * @see #glGetMvitMatrixf()
      * @see #glGetPMvMviMatrixf()
      * @see #glGetPMvMvitMatrixf()
+     * @see #glGetFrustum()
      */
     public final int getDirtyBits() {
         return dirtyBits;
@@ -924,17 +947,20 @@ public class PMVMatrix implements GLMatrixFunc {
     /** 
      * Returns the request bit mask, which uses bit values equal to the dirty mask.
      * <p>
-     * The request bit mask is set by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods.
+     * The request bit mask is set by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get} 
+     * or {@link #glGetFrustum() Frustum get} methods.
      * </p> 
      *
      * @deprecated Function is exposed for debugging purposes only.
-     * @see #disableMviMvitUpdate()
+     * @see #clearAllUpdateRequests()
      * @see #DIRTY_INVERSE_MODELVIEW
      * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW
+     * @see #DIRTY_FRUSTUM
      * @see #glGetMviMatrixf()
      * @see #glGetMvitMatrixf()
      * @see #glGetPMvMviMatrixf()
      * @see #glGetPMvMvitMatrixf()
+     * @see #glGetFrustum()
      */
     public final int getRequestMask() {
         return requestMask;
@@ -942,38 +968,39 @@ public class PMVMatrix implements GLMatrixFunc {
     
     
     /**
-     * Disable {@link #update()} of the Mvi and Mvit matrix
-     * after it has been enabled by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods.
+     * Clears all {@link #update()} requests of the Mvi and Mvit matrix and Frustum
+     * after it has been enabled by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get} 
+     * or {@link #glGetFrustum() Frustum get} methods.
      * <p>
-     * This cleans the request bit mask used internally.
-     * </p>
-     * <p>
-     * Function may be useful to disable subsequent Mvi and Mvit updates if no more required.
+     * Allows user to disable subsequent Mvi, Mvit and {@link Frustum} updates if no more required.
      * </p>  
      * 
      * @see #glGetMviMatrixf()
      * @see #glGetMvitMatrixf()
      * @see #glGetPMvMviMatrixf()
      * @see #glGetPMvMvitMatrixf()
+     * @see #glGetFrustum()
      * @see #getRequestMask()
      */
-    public final void disableMviMvitUpdate() {
+    public final void clearAllUpdateRequests() {
         requestMask &= ~DIRTY_ALL;        
     }
     
     /**
-     * Update the derived {@link #glGetMviMatrixf() inverse modelview (Mvi)} 
-     * and {@link #glGetMvitMatrixf() inverse transposed modelview (Mvit)} matrices
-     * <b>if</b> they are dirty <b>and</b> their usage/update has been requested 
-     * by one of the {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} methods.
+     * Update the derived {@link #glGetMviMatrixf() inverse modelview (Mvi)},
+     * {@link #glGetMvitMatrixf() inverse transposed modelview (Mvit)} matrices and {@link Frustum} 
+     * <b>if</b> they are dirty <b>and</b> they were requested 
+     * by one of the {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get} 
+     * or {@link #glGetFrustum() Frustum get} methods.
      * <p>
-     * The Mvi and Mvit matrices are considered dirty, if their corresponding
+     * The Mvi and Mvit matrices and {@link Frustum} are considered dirty, if their corresponding
      * {@link #glGetMvMatrixf() Mv matrix} has been modified since their last update.
      * </p>
      * <p>
      * Method should be called manually in case mutable operations has been called
      * and caller operates on already fetched references, i.e. not calling
-     * {@link #glGetMviMatrixf() Mvi get} or {@link #glGetMvitMatrixf() Mvit get} etc anymore.
+     * {@link #glGetMviMatrixf() Mvi get}, {@link #glGetMvitMatrixf() Mvit get} 
+     * or {@link #glGetFrustum() Frustum get} etc anymore.
      * </p>
      * <p>
      * This method clears the modified bits like {@link #getModifiedBits(boolean) getModifiedBits(true)},
@@ -982,7 +1009,7 @@ public class PMVMatrix implements GLMatrixFunc {
      * </p>
      * 
      * @return true if any matrix has been modified since last update call or 
-     *         if the derived matrices Mvi and Mvit were updated, otherwise false.
+     *         if the derived matrices Mvi and Mvit or {@link Frustum} were updated, otherwise false.
      *         In other words, method returns true if any matrix used by the caller must be updated,
      *         e.g. uniforms in a shader program.
      * 
@@ -992,23 +1019,36 @@ public class PMVMatrix implements GLMatrixFunc {
      * @see #MODIFIED_TEXTURE
      * @see #DIRTY_INVERSE_MODELVIEW
      * @see #DIRTY_INVERSE_TRANSPOSED_MODELVIEW
+     * @see #DIRTY_FRUSTUM
      * @see #glGetMviMatrixf()
      * @see #glGetMvitMatrixf()
      * @see #glGetPMvMviMatrixf()
      * @see #glGetPMvMvitMatrixf()
-     * @see #disableMviMvitUpdate()
+     * @see #glGetFrustum()
+     * @see #clearAllUpdateRequests()
      */
     public final boolean update() {
         return updateImpl(true);
     }
     private final boolean updateImpl(boolean clearModBits) {
-        final boolean mod = 0 != modifiedBits;
+        boolean mod = 0 != modifiedBits;
         if(clearModBits) {
             modifiedBits = 0;
         }
         
+        if( 0 != ( dirtyBits & ( DIRTY_FRUSTUM & requestMask ) ) ) {
+            if( null == frustum ) {
+                frustum = new Frustum();
+                mulPMV = new float[16];
+            }
+            FloatUtil.multMatrixf(matrixP, matrixMv, mulPMV, 0);
+            frustum.updateByPMV(mulPMV, 0);
+            dirtyBits &= ~DIRTY_FRUSTUM;
+            mod = true;
+        }
+        
         if( 0 == ( dirtyBits & requestMask ) ) {
-            return mod; // nothing requested which may have been dirty
+            return mod; // nothing more requested which may have been dirty
         }
 
         if(nioBackupArraySupported>=0) {
@@ -1081,10 +1121,12 @@ public class PMVMatrix implements GLMatrixFunc {
     protected Buffer matrixBuffer;
     protected FloatBuffer matrixIdent, matrixPMvMvit, matrixPMvMvi, matrixPMv, matrixP, matrixTex, matrixMv, matrixMvi, matrixMvit;
     protected float[] matrixMult, matrixTrans, matrixRot, matrixScale, matrixOrtho, matrixFrustum, vec3f;
-    protected List<float[]> matrixTStack, matrixPStack, matrixMvStack;
+    protected FloatStack matrixTStack, matrixPStack, matrixMvStack;
     protected int matrixMode = GL_MODELVIEW;
     protected int modifiedBits = MODIFIED_ALL;
     protected int dirtyBits = DIRTY_ALL; // contains the dirty bits, i.e. hinting for update operation
     protected int requestMask = 0; // may contain the requested dirty bits: DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW
     protected ProjectFloat projectFloat;
+    protected float[] mulPMV; // premultiplied PMV
+    protected Frustum frustum;
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
new file mode 100644
index 0000000..aceb609
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
@@ -0,0 +1,228 @@
+/**
+ * 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.util.awt;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+import java.nio.Buffer;
+import java.nio.IntBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.GLPixelBuffer;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+
+/** 
+ * AWT {@link GLPixelBuffer} backed by an {@link BufferedImage} of type 
+ * {@link BufferedImage#TYPE_INT_ARGB} or {@link BufferedImage#TYPE_INT_RGB}.
+ * <p>
+ * Implementation uses an array backed  {@link IntBuffer}.
+ * </p>
+ * <p>
+ * {@link AWTGLPixelBuffer} can be produced via {@link AWTGLPixelBufferProvider}'s 
+ * {@link AWTGLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocate(..)}. 
+ * </p>
+ * <p>
+ * See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)} for {@link #allowRowStride} details.
+ * </p>
+ */
+public class AWTGLPixelBuffer extends GLPixelBuffer {
+    public static final GLPixelAttributes awtPixelAttributesIntRGBA4 = new GLPixelAttributes(4, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
+    public static final GLPixelAttributes awtPixelAttributesIntRGB3 = new GLPixelAttributes(3, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
+
+    /** Allow {@link GL2GL3#GL_PACK_ROW_LENGTH}, or {@link GL2GL3#GL_UNPACK_ROW_LENGTH}. See {@link #requiresNewBuffer(GL, int, int, int)}. */
+    public final boolean allowRowStride;
+    /** The underlying {@link BufferedImage}. */
+    public final BufferedImage image;
+    
+    /**
+     * @param pixelAttributes the desired {@link GLPixelAttributes}
+     * @param width in pixels
+     * @param height in pixels
+     * @param depth in pixels
+     * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
+     * @param image the AWT image
+     * @param buffer the backing array
+     * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link #requiresNewBuffer(GL, int, int, int)}.
+     */
+    public AWTGLPixelBuffer(GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, BufferedImage image, 
+                            Buffer buffer, boolean allowRowStride) {
+        super(pixelAttributes, width, height, depth, pack, buffer);
+        this.allowRowStride = allowRowStride;
+        this.image = image;
+    }
+    
+    /**
+     * {@inheritDoc}
+     * <p>
+     * If <code>{@link #allowRowStride} = false</code>,
+     * method returns <code>true</code> if the new size ≠ current size.
+     * </p> 
+     * <p>
+     * If <code>{@link #allowRowStride} = true</code>, see {@link AWTGLPixelBufferProvider#AWTGLPixelBufferProvider(boolean)},
+     * method returns <code>true</code> only if the new size > current size. Assuming user utilizes the row-stride
+     * when dealing w/ the data, i.e. {@link GL2GL3#GL_PACK_ROW_LENGTH}.
+     * </p>
+     */
+    @Override
+    public boolean requiresNewBuffer(GL gl, int newWidth, int newHeight, int minByteSize) {
+        if( !isValid() ) {
+            return true;
+        }
+        if( allowRowStride && gl.isGL2GL3() ) {
+            return width < newWidth || height < newHeight;
+        } else {
+            return width != newWidth || height != newHeight;
+        }
+    }
+    
+    @Override
+    public void dispose() {
+        image.flush();
+        super.dispose();
+    }
+    
+    public StringBuffer toString(StringBuffer sb) {
+        sb = super.toString(sb);
+        sb.append(", allowRowStride ").append(allowRowStride).append(", image [").append(image.getWidth()).append("x").append(image.getHeight()).append(", ").append(image.toString()).append("]");
+        return sb;
+    }
+    public String toString() {
+        return "AWTGLPixelBuffer["+toString(null).toString()+"]";
+    }
+    
+    /**
+     * Provider for {@link AWTGLPixelBuffer} instances.
+     */
+    public static class AWTGLPixelBufferProvider implements GLPixelBufferProvider {    
+        /** Allow {@link GL2GL3#GL_PACK_ROW_LENGTH}, or {@link GL2GL3#GL_UNPACK_ROW_LENGTH}. */
+        public final boolean allowRowStride;
+        
+        /**
+         * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+         */
+        public AWTGLPixelBufferProvider(boolean allowRowStride) {
+            this.allowRowStride = allowRowStride;
+        }
+        @Override
+        public GLPixelAttributes getAttributes(GL gl, int componentCount) {
+            return 4 == componentCount ? awtPixelAttributesIntRGBA4 : awtPixelAttributesIntRGB3;
+        }
+            
+        /**
+         * {@inheritDoc}
+         * <p>
+         * Returns an array backed {@link IntBuffer} of size <pre>width*height*{@link Buffers#SIZEOF_INT SIZEOF_INT}</code>.
+         * </p>
+         */
+        @Override
+        public AWTGLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize) {
+            final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+            final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+            final Buffer ibuffer = IntBuffer.wrap( readBackIntBuffer );
+            return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, allowRowStride);
+        }
+    }
+    
+    /**
+     * Provider for singleton {@link AWTGLPixelBuffer} instances.
+     * <p>
+     * Provider instance holds the last {@link AWTGLPixelBuffer} instance
+     * {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+     * A new {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocation} 
+     * will return same instance, if a new buffer is not {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int) required}.
+     * The latter is true if size are compatible, hence <code>allowRowStride</code> should be enabled, if possible. 
+     * </p>
+     */    
+    public static class SingleAWTGLPixelBufferProvider extends AWTGLPixelBufferProvider implements SingletonGLPixelBufferProvider {
+        private AWTGLPixelBuffer singleRGBA4 = null;
+        private AWTGLPixelBuffer singleRGB3 = null;
+        
+        /**
+         * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+         */
+        public SingleAWTGLPixelBufferProvider(boolean allowRowStride) {
+            super(allowRowStride);
+        }
+        
+        /**
+         * {@inheritDoc}
+         * <p>
+         * Returns an array backed {@link IntBuffer} of size <pre>width*height*{@link Buffers#SIZEOF_INT SIZEOF_INT}</code>.
+         * </p>
+         */
+        @Override
+        public AWTGLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize) {
+            if( 4 == pixelAttributes.componentCount ) {
+                if( null == singleRGBA4 || singleRGBA4.requiresNewBuffer(gl, width, height, minByteSize) ) {
+                    singleRGBA4 = allocateImpl(pixelAttributes, width, height, depth, pack, minByteSize); 
+                }
+                return singleRGBA4;
+            } else {
+                if( null == singleRGB3 || singleRGB3.requiresNewBuffer(gl, width, height, minByteSize) ) {
+                    singleRGB3 = allocateImpl(pixelAttributes, width, height, depth, pack, minByteSize);
+                }
+                return singleRGB3;
+            }
+        }
+        
+        private AWTGLPixelBuffer allocateImpl(GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize) {
+            final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+            final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+            final Buffer ibuffer = IntBuffer.wrap( readBackIntBuffer );
+            return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, allowRowStride);
+        }
+        
+        /** Return the last {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated} {@link AWTGLPixelBuffer} w/ {@link GLPixelAttributes#componentCount}. */ 
+        public AWTGLPixelBuffer getSingleBuffer(GLPixelAttributes pixelAttributes) {
+            return 4 == pixelAttributes.componentCount ? singleRGBA4 : singleRGB3;
+        }
+        
+        /** 
+         * Initializes the single {@link AWTGLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+         * @return the newly initialized single {@link AWTGLPixelBuffer}, or null if already allocated.
+         */
+        public AWTGLPixelBuffer initSingleton(int componentCount, int width, int height, int depth, boolean pack) {
+            if( 4 == componentCount ) {
+                if( null != singleRGBA4 ) {
+                    return null; 
+                }
+                singleRGBA4 = allocateImpl(AWTGLPixelBuffer.awtPixelAttributesIntRGBA4, width, height, depth, pack, 0);
+                return singleRGBA4;
+            } else {
+                if( null != singleRGB3 ) {
+                    return null; 
+                }
+                singleRGB3 = allocateImpl(AWTGLPixelBuffer.awtPixelAttributesIntRGB3, width, height, depth, pack, 0);
+                return singleRGB3;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
new file mode 100644
index 0000000..0edd53c
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
@@ -0,0 +1,76 @@
+/**
+ * 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.util.awt;
+
+import java.awt.image.BufferedImage;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.GLReadBufferUtil;
+
+/**
+ * {@link GLReadBufferUtil} specialization allowing to
+ * read out a frambuffer to an AWT BufferedImage
+ * utilizing {@link AWTPixelBufferProviderInt} for further AWT processing.
+ */
+public class AWTGLReadBufferUtil extends GLReadBufferUtil {
+    /**
+     * {@inheritDoc}
+     * 
+     * @param alpha
+     */
+    public AWTGLReadBufferUtil(GLProfile glp, boolean alpha) {
+        super(new AWTGLPixelBuffer.AWTGLPixelBufferProvider( glp.isGL2GL3() /* allowRowStride */ ), alpha, false);
+    }
+
+    public AWTGLPixelBuffer getAWTGLPixelBuffer() { return (AWTGLPixelBuffer)this.getPixelBuffer(); }
+    
+    public BufferedImage readPixelsToBufferedImage(GL gl, boolean awtOrientation) {
+        if( readPixels(gl, awtOrientation) ) {
+            final BufferedImage image = getAWTGLPixelBuffer().image;
+            if( getTextureData().getMustFlipVertically()  ) {
+                ImageUtil.flipImageVertically(image);
+            }
+            return image;
+        }
+        return null;
+    }
+    public BufferedImage readPixelsToBufferedImage(GL gl, int inX, int inY, int inWidth, int inHeight, boolean awtOrientation) {
+        final int[] ioWidth = new int[] { inWidth };
+        final int[] ioHeight= new int[] { inHeight };
+        if( readPixels(gl, inX, inY, ioWidth, ioHeight, awtOrientation) ) {
+            final BufferedImage image = getAWTGLPixelBuffer().image;
+            if( getTextureData().getMustFlipVertically()  ) {
+                ImageUtil.flipImageVertically(image);
+            }
+            return image;
+        }
+        return null;
+    }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
index 0022d5c..2ffc272 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 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
@@ -43,17 +44,26 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 
 import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
 import javax.media.opengl.GL2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
 import javax.media.opengl.GLException;
-import javax.media.opengl.glu.gl2.GLUgl2;
 
 import com.jogamp.common.util.IOUtil;
 import com.jogamp.opengl.GLExtensions;
 import com.jogamp.opengl.util.GLPixelStorageModes;
 import com.jogamp.opengl.util.TGAWriter;
 
-/** Utilities for taking screenshots of OpenGL applications. */
-
+/** 
+ * Utilities for taking screenshots of OpenGL applications.
+ * @deprecated Please consider using {@link com.jogamp.opengl.util.GLReadBufferUtil}, 
+ *             which is AWT independent and does not require a CPU based vertical image flip 
+ *             in case drawable {@link GLDrawable#isGLOriented() is in OpenGL orientation}.
+ *             Further more you may use {@link AWTGLReadBufferUtil} to read out 
+ *             the framebuffer into a BufferedImage for further AWT processing.
+ */
 public class Screenshot {
   private Screenshot() {}
 
@@ -149,17 +159,17 @@ public class Screenshot {
     writer.open(file, width, height, alpha);
     ByteBuffer bgr = writer.getImageData();
 
-    GL2 gl = GLUgl2.getCurrentGL2();
+    GL gl = GLContext.getCurrentGL();
 
     // Set up pixel storage modes
     GLPixelStorageModes psm = new GLPixelStorageModes();
     psm.setPackAlignment(gl, 1);
 
-    int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2.GL_BGR);
+    int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2GL3.GL_BGR);
 
     // read the BGR values into the image buffer
     gl.glReadPixels(x, y, width, height, readbackType,
-                    GL2.GL_UNSIGNED_BYTE, bgr);
+                    GL.GL_UNSIGNED_BYTE, bgr);
 
     // Restore pixel storage modes
     psm.restore(gl);
@@ -247,7 +257,7 @@ public class Screenshot {
                                                   int height,
                                                   boolean alpha) throws GLException {
     int bufImgType = (alpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR);
-    int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2.GL_BGR);
+    int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2GL3.GL_BGR);
 
     if (alpha) {
       checkExtABGR();
@@ -256,7 +266,8 @@ public class Screenshot {
     // Allocate necessary storage
     BufferedImage image = new BufferedImage(width, height, bufImgType);
 
-    GL2 gl = GLUgl2.getCurrentGL2();
+    GLContext glc = GLContext.getCurrent();
+    GL gl = glc.getGL();
 
     // Set up pixel storage modes
     GLPixelStorageModes psm = new GLPixelStorageModes();
@@ -264,14 +275,16 @@ public class Screenshot {
 
     // read the BGR values into the image
     gl.glReadPixels(x, y, width, height, readbackType,
-                    GL2.GL_UNSIGNED_BYTE,
+                    GL.GL_UNSIGNED_BYTE,
                     ByteBuffer.wrap(((DataBufferByte) image.getRaster().getDataBuffer()).getData()));
 
     // Restore pixel storage modes
     psm.restore(gl);
 
-    // Must flip BufferedImage vertically for correct results
-    ImageUtil.flipImageVertically(image);
+    if( glc.getGLDrawable().isGLOriented() ) {
+        // Must flip BufferedImage vertically for correct results
+        ImageUtil.flipImageVertically(image);
+    }
     return image;
   }
 
@@ -392,7 +405,8 @@ public class Screenshot {
   }
 
   private static void checkExtABGR() {
-    GL2 gl = GLUgl2.getCurrentGL2();
+    GL gl = GLContext.getCurrentGL();
+
     if (!gl.isExtensionAvailable(GLExtensions.EXT_abgr)) {
       throw new IllegalArgumentException("Saving alpha channel requires GL_EXT_abgr");
     }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
index e6dde32..edc3d26 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
@@ -45,6 +45,7 @@ import java.util.Set;
 
 import javax.media.opengl.GL;
 import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL3;
 import javax.media.opengl.GLES2;
 import javax.media.opengl.GLContext;
 import javax.media.opengl.GLException;
@@ -53,6 +54,7 @@ import jogamp.opengl.Debug;
 
 import com.jogamp.common.nio.Buffers;
 import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.VersionNumber;
 
 /**
  * Convenient shader code class to use and instantiate vertex or fragment programs.
@@ -72,6 +74,12 @@ public class ShaderCode {
     /** Unique resource suffix for {@link GL2ES2#GL_VERTEX_SHADER} in binary: <code>bvp</code> */
     public static final String SUFFIX_VERTEX_BINARY   = "bvp" ;
     
+    /** Unique resource suffix for {@link GL3#GL_GEOMETRY_SHADER} in source code: <code>gp</code> */
+    public static final String SUFFIX_GEOMETRY_SOURCE =  "gp" ;
+    
+    /** Unique resource suffix for {@link GL3#GL_GEOMETRY_SHADER} in binary: <code>bgp</code> */
+    public static final String SUFFIX_GEOMETRY_BINARY = "bgp" ;
+    
     /** Unique resource suffix for {@link GL2ES2#GL_FRAGMENT_SHADER} in source code: <code>fp</code> */
     public static final String SUFFIX_FRAGMENT_SOURCE =  "fp" ;
     
@@ -82,7 +90,7 @@ public class ShaderCode {
     public static final String SUB_PATH_NVIDIA = "nvidia" ;
 
     /**
-     * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+     * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
      * @param count number of shaders
      * @param source CharSequence array containing the shader sources, organized as <code>source[count][strings-per-shader]</code>.
      *               May be either an immutable <code>String</code> - or mutable <code>StringBuilder</code> array.
@@ -96,6 +104,7 @@ public class ShaderCode {
         switch (type) {
             case GL2ES2.GL_VERTEX_SHADER:
             case GL2ES2.GL_FRAGMENT_SHADER:
+            case GL3.GL_GEOMETRY_SHADER:
                 break;
             default:
                 throw new GLException("Unknown shader type: "+type);
@@ -114,7 +123,7 @@ public class ShaderCode {
     }
 
     /**
-     * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+     * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
      * @param count number of shaders
      * @param binary binary buffer containing the shader binaries, 
      */
@@ -122,6 +131,7 @@ public class ShaderCode {
         switch (type) {
             case GL2ES2.GL_VERTEX_SHADER:
             case GL2ES2.GL_FRAGMENT_SHADER:
+            case GL3.GL_GEOMETRY_SHADER:
                 break;
             default:
                 throw new GLException("Unknown shader type: "+type);
@@ -139,7 +149,7 @@ public class ShaderCode {
      * which location is resolved using the <code>context</code> class, see {@link #readShaderSource(Class, String)}.
      * 
      * @param gl current GL object to determine whether a shader compiler is available. If null, no validation is performed.
-     * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+     * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
      * @param count number of shaders
      * @param context class used to help resolving the source location
      * @param sourceFiles array of source locations, organized as <code>sourceFiles[count]</code>
@@ -183,7 +193,7 @@ public class ShaderCode {
      * Creates a complete {@link ShaderCode} object while reading the shader binary of <code>binaryFile</code>,
      * which location is resolved using the <code>context</code> class, see {@link #readShaderBinary(Class, String)}.
      * 
-     * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+     * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
      * @param count number of shaders
      * @param context class used to help resolving the source location
      * @param binFormat a valid native binary format as they can be queried by {@link ShaderUtil#getShaderBinaryFormats(GL)}.
@@ -215,13 +225,15 @@ public class ShaderCode {
      * <ul>
      *   <li>Source<ul>
      *     <li>{@link GL2ES2#GL_VERTEX_SHADER vertex}: {@link #SUFFIX_VERTEX_SOURCE}</li>
-     *     <li>{@link GL2ES2#GL_FRAGMENT_SHADER fragment}: {@link #SUFFIX_FRAGMENT_SOURCE}</li></ul></li>
+     *     <li>{@link GL2ES2#GL_FRAGMENT_SHADER fragment}: {@link #SUFFIX_FRAGMENT_SOURCE}</li>
+     *     <li>{@link GL3#GL_GEOMETRY_SHADER geometry}: {@link #SUFFIX_GEOMETRY_SOURCE}</li></ul></li>
      *   <li>Binary<ul>
      *     <li>{@link GL2ES2#GL_VERTEX_SHADER vertex}: {@link #SUFFIX_VERTEX_BINARY}</li>
-     *     <li>{@link GL2ES2#GL_FRAGMENT_SHADER fragment}: {@link #SUFFIX_FRAGMENT_BINARY}</li></ul></li>
+     *     <li>{@link GL2ES2#GL_FRAGMENT_SHADER fragment}: {@link #SUFFIX_FRAGMENT_BINARY}</li>
+     *     <li>{@link GL3#GL_GEOMETRY_SHADER geometry}: {@link #SUFFIX_GEOMETRY_BINARY}</li></ul></li>
      * </ul> 
      * @param binary true for a binary resource, false for a source resource 
-     * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+     * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
      * 
      * @throws GLException if <code>type</code> is not supported
      * 
@@ -233,6 +245,8 @@ public class ShaderCode {
                 return binary?SUFFIX_VERTEX_BINARY:SUFFIX_VERTEX_SOURCE;
             case GL2ES2.GL_FRAGMENT_SHADER:
                 return binary?SUFFIX_FRAGMENT_BINARY:SUFFIX_FRAGMENT_SOURCE;
+            case GL3.GL_GEOMETRY_SHADER:
+                return binary?SUFFIX_GEOMETRY_BINARY:SUFFIX_GEOMETRY_SOURCE;
             default:
                 throw new GLException("illegal shader type: "+type);
         }
@@ -311,7 +325,7 @@ public class ShaderCode {
      * 
      * @param gl current GL object to determine whether a shader compiler is available (if <code>source</code> is used),
      *           or to determine the shader binary format (if <code>binary</code> is used).
-     * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+     * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
      * @param count number of shaders
      * @param context class used to help resolving the source and binary location
      * @param srcRoot relative <i>root</i> path for <code>srcBasenames</code>
@@ -411,7 +425,7 @@ public class ShaderCode {
      * 
      * @param gl current GL object to determine whether a shader compiler is available (if <code>source</code> is used),
      *           or to determine the shader binary format (if <code>binary</code> is used).
-     * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+     * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
      * @param context class used to help resolving the source and binary location
      * @param srcRoot relative <i>root</i> path for <code>basename</code>
      * @param binRoot relative <i>root</i> path for <code>basename</code>
@@ -447,6 +461,8 @@ public class ShaderCode {
                 return "VERTEX_SHADER";
             case GL2ES2.GL_FRAGMENT_SHADER:
                 return "FRAGMENT_SHADER";
+            case GL3.GL_GEOMETRY_SHADER:
+                return "GEOMETRY_SHADER";
         }
         return "UNKNOWN_SHADER";
     }
@@ -668,7 +684,7 @@ public class ShaderCode {
      *  
      * @param shaderIdx the shader index to be used.
      * @param position in shader source segments of shader <code>shaderIdx</code>
-     * @param data the text to be inserted. Shall end with an EOL '\n' character.
+     * @param data the text to be inserted. Shall end with an EOL '\n' character
      * @return index after the inserted <code>data</code>
      * 
      * @throws IllegalStateException if the shader source's CharSequence is immutable, i.e. not of type <code>StringBuilder</code>
@@ -701,6 +717,7 @@ public class ShaderCode {
         return -1;
     }
 
+    @SuppressWarnings("resource")
     private static int readShaderSource(Class<?> context, URLConnection conn, StringBuilder result, int lineno) throws IOException  {
         if(DEBUG_CODE) {
             if(0 == lineno) {
@@ -808,11 +825,122 @@ public class ShaderCode {
     }
 
     // Shall we use: #ifdef GL_FRAGMENT_PRECISION_HIGH .. #endif for using highp in fragment shader if avail ?     
-    /** {@value #es2_default_precision_vp} */
+    /** Default precision of {@link GL#isGLES2() ES2} for {@link GL2ES2#GL_VERTEX_SHADER vertex-shader}: {@value #es2_default_precision_vp} */
     public static final String es2_default_precision_vp = "\nprecision highp float;\nprecision highp int;\n";
-    /** {@value #es2_default_precision_fp} */
+    /** Default precision of {@link GL#isGLES2() ES2} for {@link GL2ES2#GL_FRAGMENT_SHADER fragment-shader}: {@value #es2_default_precision_fp} */
     public static final String es2_default_precision_fp = "\nprecision mediump float;\nprecision mediump int;\n/*precision lowp sampler2D;*/\n";
     
+    /** Default precision of GLSL ≥ 1.30 as required until < 1.50 for {@link GL2ES2#GL_VERTEX_SHADER vertex-shader} or {@link GL3#GL_GEOMETRY_SHADER geometry-shader}: {@value #gl3_default_precision_vp_gp}. See GLSL Spec 1.30-1.50 Section 4.5.3. */
+    public static final String gl3_default_precision_vp_gp = "\nprecision highp float;\nprecision highp int;\n";
+    /** Default precision of GLSL ≥ 1.30 as required until < 1.50 for {@link GL2ES2#GL_FRAGMENT_SHADER fragment-shader}: {@value #gl3_default_precision_fp}. See GLSL Spec 1.30-1.50 Section 4.5.3. */
+    public static final String gl3_default_precision_fp = "\nprecision highp float;\nprecision mediump int;\n/*precision mediump sampler2D;*/\n";
+    
+    /** Prefer <code>enable</code> over <code>require</code>, since it won't force a failure. */
+    public static final String extOESDerivativesEnable = "#extension GL_OES_standard_derivatives : enable\n";
+        
+    /**
+     * Add GLSL version at the head of this shader source code.
+     * <p>
+     * Note: The shader source to be edit must be created using a mutable StringBuilder.
+     * </p>
+     * @param gl a GL context, which must have been made current once 
+     * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+     */
+    public final int addGLSLVersion(GL2ES2 gl) {
+        return insertShaderSource(0, 0, gl.getContext().getGLSLVersionString());
+    }
+    
+    /**
+     * Adds default precision to source code at given position if required, i.e.
+     * {@link #es2_default_precision_vp}, {@link #es2_default_precision_fp}, 
+     * {@link #gl3_default_precision_vp_gp}, {@link #gl3_default_precision_fp} or none,
+     * depending on the {@link GLContext#getGLSLVersionNumber() GLSL version} being used.
+     * <p>
+     * Note: The shader source to be edit must be created using a mutable StringBuilder.
+     * </p>
+     * @param gl a GL context, which must have been made current once 
+     * @param pos position within this mutable shader source.
+     * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+     */
+    public final int addDefaultShaderPrecision(GL2ES2 gl, int pos) {
+        final String defaultPrecision;
+        if( gl.isGLES2() ) {
+            switch ( shaderType ) {
+                case GL2ES2.GL_VERTEX_SHADER:
+                    defaultPrecision = es2_default_precision_vp; break;
+                case GL2ES2.GL_FRAGMENT_SHADER:
+                    defaultPrecision = es2_default_precision_vp; break;
+                default:
+                    defaultPrecision = null; 
+                    break;
+            }
+        } else if( requiresGL3DefaultPrecision(gl) ) {
+            // GLSL [ 1.30 .. 1.50 [ needs at least fragement float default precision!
+            switch ( shaderType ) {
+                case GL2ES2.GL_VERTEX_SHADER:
+                case GL3.GL_GEOMETRY_SHADER:
+                    defaultPrecision = gl3_default_precision_vp_gp; break;
+                case GL2ES2.GL_FRAGMENT_SHADER:
+                    defaultPrecision = gl3_default_precision_fp; break;
+                default:
+                    defaultPrecision = null; 
+                    break;
+            }
+        } else {
+            defaultPrecision = null;
+        }
+        if( null != defaultPrecision ) {
+            pos = insertShaderSource(0, pos, defaultPrecision);
+        }
+        return pos;
+    }
+    
+    /** Returns true, if GLSL version requires default precision, i.e. ES2 or GLSL [1.30 .. 1.50[. */
+    public static final boolean requiresDefaultPrecision(GL2ES2 gl) {
+        if( gl.isGLES2() ) {
+            return true;
+        }
+        return requiresGL3DefaultPrecision(gl);
+    }
+    
+    /** Returns true, if GL3 GLSL version requires default precision, i.e. GLSL [1.30 .. 1.50[. */
+    public static final boolean requiresGL3DefaultPrecision(GL2ES2 gl) {
+        if( gl.isGL3() ) {
+            final VersionNumber glslVersion = gl.getContext().getGLSLVersionNumber();
+            return glslVersion.compareTo(GLContext.Version130) >= 0 && glslVersion.compareTo(GLContext.Version150) < 0 ;
+        } else {
+            return false;
+        }
+    }
+    
+    /**
+     * Default customization of this shader source code.
+     * <p>
+     * Note: The shader source to be edit must be created using a mutable StringBuilder.
+     * </p>
+     * @param gl a GL context, which must have been made current once 
+     * @param preludeVersion if true {@link GLContext#getGLSLVersionString()} is preluded, otherwise not.
+     * @param addDefaultPrecision if <code>true</code> default precision source code line(s) are added, i.e. 
+     *                            {@link #es2_default_precision_vp}, {@link #es2_default_precision_fp}, 
+     *                            {@link #gl3_default_precision_vp_gp}, {@link #gl3_default_precision_fp} or none,
+     *                            depending on the {@link GLContext#getGLSLVersionNumber() GLSL version} being used.
+     * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+     * @see #addGLSLVersion(GL2ES2)
+     * @see #addDefaultShaderPrecision(GL2ES2, int)
+     */
+    public final int defaultShaderCustomization(GL2ES2 gl, boolean preludeVersion, boolean addDefaultPrecision) {
+        int pos;
+        if( preludeVersion ) {
+            pos = addGLSLVersion(gl);
+        } else {
+            pos = 0;
+        }
+        if( addDefaultPrecision ) {
+            pos = addDefaultShaderPrecision(gl, pos);
+        }
+        return pos;
+    }
+        
     /**
      * Default customization of this shader source code.
      * <p>
@@ -820,18 +948,23 @@ public class ShaderCode {
      * </p>
      * @param gl a GL context, which must have been made current once 
      * @param preludeVersion if true {@link GLContext#getGLSLVersionString()} is preluded, otherwise not.
-     * @param es2DefaultPrecision optional default precision source code line(s) preluded if not null and if {@link GL#isGLES()}.
+     * @param esDefaultPrecision optional default precision source code line(s) preluded if not null and if {@link GL#isGLES()}.
      *        You may use {@link #es2_default_precision_fp} for fragment shader and {@link #es2_default_precision_vp} for vertex shader.
      * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+     * @see #addGLSLVersion(GL2ES2)
+     * @see #addDefaultShaderPrecision(GL2ES2, int)
      */
-    public final int defaultShaderCustomization(GL2ES2 gl, boolean preludeVersion, String es2DefaultPrecision) {
-        int pos = 0;
-        if(preludeVersion) {
-            final String glslVersion_prelude = gl.getContext().getGLSLVersionString();
-            pos = insertShaderSource(0, pos, glslVersion_prelude);
-        }
-        if( gl.isGLES() && null != es2DefaultPrecision ) {
-            pos = insertShaderSource(0, pos, es2DefaultPrecision);
+    public final int defaultShaderCustomization(GL2ES2 gl, boolean preludeVersion, String esDefaultPrecision) {
+        int pos;
+        if( preludeVersion ) {
+            pos = addGLSLVersion(gl);
+        } else {
+            pos = 0;
+        }
+        if( gl.isGLES2() && null != esDefaultPrecision ) {
+            pos = insertShaderSource(0, pos, esDefaultPrecision);
+        } else {
+            pos = addDefaultShaderPrecision(gl, pos);
         }
         return pos;
     }    
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java
index 9cade1e..1337a7e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java
@@ -85,7 +85,9 @@ public class ShaderProgram {
      * If <code>destroyShaderCode</code> is true it destroys the shader codes as well.
      */
     public synchronized void release(GL2ES2 gl, boolean destroyShaderCode) {
-        useProgram(gl, false);
+        if( programLinked ) {
+            useProgram(gl, false);
+        }
         for(Iterator<ShaderCode> iter=allShaderCode.iterator(); iter.hasNext(); ) {
             ShaderCode shaderCode = iter.next();
             if(attachedShaderCode.remove(shaderCode)) {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
index ff8982d..9683919 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java
@@ -35,7 +35,6 @@ import java.util.Iterator;
 import javax.media.opengl.GL;
 import javax.media.opengl.GL2ES2;
 import javax.media.opengl.GLArrayData;
-import javax.media.opengl.GLContext;
 import javax.media.opengl.GLException;
 import javax.media.opengl.GLUniformData;
 
@@ -58,7 +57,6 @@ import com.jogamp.opengl.util.GLArrayDataEditable;
  */
 public class ShaderState {
     public static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLSLState", true);
-    private static final String currentStateKey = "jogamp.opengl.glsl.ShaderState" ;
     
     public ShaderState() {
     }
@@ -68,46 +66,6 @@ public class ShaderState {
     public void setVerbose(boolean v) { verbose = DEBUG || v; }
 
     /**
-     * Fetches the current shader state from this thread (TLS) current GLContext
-     *
-     * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
-     */
-    public static ShaderState getCurrentShaderState() { 
-        return getShaderState(GLContext.getCurrentGL());
-    }
-
-    /**
-     * Gets the shader state attached to the GL object's GLContext
-     *
-     * @param gl the GL object referencing the GLContext
-     * 
-     * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
-     */
-    public static ShaderState getShaderState(GL gl) { 
-        return (ShaderState) gl.getContext().getAttachedObject(currentStateKey);
-    }
-
-    /**
-     * Attaches the shader state to the GL object's GLContext
-     *
-     * @param gl the GL object referencing the GLContext
-     * 
-     * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
-     */
-    public final ShaderState setShaderState(GL gl) { 
-        return (ShaderState) gl.getContext().attachObject(currentStateKey, this);
-    }
-
-    /**
      * Returns the attached user object for the given name to this ShaderState.
      */
     public final Object getAttachedObject(String name) {
@@ -135,19 +93,14 @@ public class ShaderState {
     
     /**
      * Turns the shader program on or off.<br>
-     * Puts this ShaderState to to the thread local storage (TLS),
-     * if <code>on</code> is <code>true</code>.
      *
      * @throws GLException if no program is attached
      *
      * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL)
-     * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState()
      */
     public synchronized void useProgram(GL2ES2 gl, boolean on) throws GLException {
         if(null==shaderProgram) { throw new GLException("No program is attached"); }        
         if(on) {
-            setShaderState(gl);
             if(shaderProgram.linked()) {
                 shaderProgram.useProgram(gl, true);
                 if(resetAllShaderData) {
@@ -278,7 +231,7 @@ public class ShaderState {
      * @see ShaderProgram#release(GL2ES2, boolean)
      */
     public synchronized void release(GL2ES2 gl, boolean destroyBoundAttributes, boolean destroyShaderProgram, boolean destroyShaderCode) {
-        if(null!=shaderProgram) {            
+        if(null!=shaderProgram && shaderProgram.linked() ) {
             shaderProgram.useProgram(gl, false);
         }
         if(destroyBoundAttributes) {
@@ -332,6 +285,10 @@ public class ShaderState {
         return activeAttribDataMap.get(name);
     }
     
+    public boolean isActiveAttribute(GLArrayData attribute) {
+        return attribute == activeAttribDataMap.get(attribute.getName());
+    }
+    
     /**
      * Binds or unbinds the {@link GLArrayData} lifecycle to this ShaderState.
      *  
@@ -343,11 +300,14 @@ public class ShaderState {
      *  
      * <p>The data will not be transfered to the GPU, use {@link #vertexAttribPointer(GL2ES2, GLArrayData)} additionally.</p>
      * 
+     * <p>The data will also be {@link GLArrayData#associate(Object, boolean) associated} with this ShaderState.</p>
+     * 
      * @param attribute the {@link GLArrayData} which lifecycle shall be managed
      * @param own true if <i>owning</i> shall be performs, false if <i>disowning</i>.
      * 
      * @see #bindAttribLocation(GL2ES2, int, String)
      * @see #getAttribute(String)
+     * @see GLArrayData#associate(Object, boolean)
      */
     public void ownAttribute(GLArrayData attribute, boolean own) {
         if(own) {
@@ -359,6 +319,7 @@ public class ShaderState {
         } else {
             managedAttributes.remove(attribute);
         }
+        attribute.associate(this, own);
     }
     
     public boolean ownsAttribute(GLArrayData attribute) {
@@ -402,13 +363,16 @@ public class ShaderState {
      * @see #getAttribute(String)
      */
     public void bindAttribLocation(GL2ES2 gl, int location, GLArrayData data) {
-        bindAttribLocation(gl, location, data.getName());
-        data.setLocation(location);
+        if(null==shaderProgram) throw new GLException("No program is attached");
+        if(shaderProgram.linked()) throw new GLException("Program is already linked");
+        final String name = data.getName();
+        activeAttribLocationMap.put(name, new Integer(location));
+        data.setLocation(gl, shaderProgram.program(), location);
         activeAttribDataMap.put(data.getName(), data);
     }
 
     /**
-     * Gets the location of a shader attribute.<br>
+     * Gets the location of a shader attribute with given <code>name</code>.<br>
      * Uses either the cached value {@link #getCachedAttribLocation(String)} if valid,
      * or the GLSL queried via {@link GL2ES2#glGetAttribLocation(int, String)}.<br>
      * The location will be cached.
@@ -430,8 +394,7 @@ public class ShaderState {
             if(!shaderProgram.linked()) throw new GLException("Program is not linked");
             location = gl.glGetAttribLocation(shaderProgram.program(), name);
             if(0<=location) {
-                Integer idx = new Integer(location);
-                activeAttribLocationMap.put(name, idx);
+                activeAttribLocationMap.put(name, new Integer(location));
                 if(DEBUG) {
                     System.err.println("ShaderState: glGetAttribLocation: "+name+", loc: "+location);
                 }
@@ -444,7 +407,7 @@ public class ShaderState {
         }
         return location;
     }
-
+    
     /**
      * Validates and returns the location of a shader attribute.<br>
      * Uses either the cached value {@link #getCachedAttribLocation(String)} if valid, 
@@ -465,8 +428,27 @@ public class ShaderState {
      * @see #getAttribute(String)
      */
     public int getAttribLocation(GL2ES2 gl, GLArrayData data) {
-        int location = getAttribLocation(gl, data.getName());
-        data.setLocation(location);
+        if(null==shaderProgram) throw new GLException("No program is attached");
+        final String name = data.getName();
+        int location = getCachedAttribLocation(name);
+        if(0<=location) {
+            data.setLocation(location);
+        } else {
+            if(!shaderProgram.linked()) throw new GLException("Program is not linked");
+            location = data.setLocation(gl, shaderProgram.program());
+            if(0<=location) {
+                Integer idx = new Integer(location);
+                activeAttribLocationMap.put(name, idx);
+                if(DEBUG) {
+                    System.err.println("ShaderState: glGetAttribLocation: "+name+", loc: "+location);
+                }
+            } else if(verbose) {
+                System.err.println("ShaderState: glGetAttribLocation failed, no location for: "+name+", loc: "+location);
+                if(DEBUG) {
+                    Thread.dumpStack();
+                }                    
+            }
+        }        
         activeAttribDataMap.put(data.getName(), data);
         return location;
     }
@@ -638,11 +620,12 @@ public class ShaderState {
     }
     
     /**
-     * Set the {@link GLArrayData} vertex attribute data.
-     * 
-     * This method uses the {@link GLArrayData}'s location if set.
-     * If data location is unset it will be retrieved via {@link #getAttribLocation(GL2ES2, GLArrayData)}, set
-     * and cached in this state.
+     * Set the {@link GLArrayData} vertex attribute data, if it's location is valid, i.e. ≥ 0.
+     * <p>
+     * This method uses the {@link GLArrayData}'s location if valid, i.e. ≥ 0.<br/>
+     * If data's location is invalid, it will be retrieved via {@link #getAttribLocation(GL2ES2, GLArrayData)}, 
+     * set and cached in this state.
+     * </p>
      * 
      * @return false, if the location could not be determined, otherwise true
      *
@@ -729,12 +712,14 @@ public class ShaderState {
     }
 
     private final void relocateAttribute(GL2ES2 gl, GLArrayData attribute) {
-        // get new location ..
+        // get new location .. note: 'activeAttribLocationMap' is cleared before 
         final String name = attribute.getName();
-        final int loc = getAttribLocation(gl, name);
-        attribute.setLocation(loc);
-
+        final int loc = attribute.setLocation(gl, shaderProgram.program());
         if(0<=loc) {
+            activeAttribLocationMap.put(name, new Integer(loc));
+            if(DEBUG) {
+                System.err.println("ShaderState: relocateAttribute: "+name+", loc: "+loc);
+            }
             if(isVertexAttribArrayEnabled(name)) {
                 // enable attrib, VBO and pass location/data
                 gl.glEnableVertexAttribArray(loc);
@@ -753,13 +738,20 @@ public class ShaderState {
     /**
      * Reset all previously enabled mapped vertex attribute data.
      * 
-     * <p>Attribute data is bound to the GL state</p>
-     * <p>Attribute location is bound to the program</p>
+     * <p>
+     * Attribute data is bound to the GL state, i.e. VBO data itself will not be updated.
+     * </p>
+     * 
+     * <p>
+     * Attribute location and it's data assignment is bound to the program,
+     * hence both are updated.
+     * </p>
+     * 
+     * <p>
+     * Note: Such update could only be prevented, 
+     * if tracking am attribute/program dirty flag.
+     * </p>
      * 
-     * <p>However, since binding an attribute to a location via {@link #bindAttribLocation(GL2ES2, int, GLArrayData)}
-     * <i>must</i> happen before linking <b>and</b> we try to promote the attributes to the new program,
-     * we have to gather the probably new location etc.</p>
-     *
      * @throws GLException is the program is not linked
      *
      * @see #attachShaderProgram(GL2ES2, ShaderProgram)
@@ -851,7 +843,7 @@ public class ShaderState {
     }
     
     /**
-     * Gets the location of a shader uniform.<br>
+     * Gets the location of a shader uniform with given <code>name</code>.<br>
      * Uses either the cached value {@link #getCachedUniformLocation(String)} if valid,
      * or the GLSL queried via {@link GL2ES2#glGetUniformLocation(int, String)}.<br>
      * The location will be cached.
@@ -873,6 +865,7 @@ public class ShaderState {
         if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
         int location = getCachedUniformLocation(name);
         if(0>location) {
+            if(!shaderProgram.linked()) throw new GLException("Program is not linked");
             location = gl.glGetUniformLocation(shaderProgram.program(), name);
             if(0<=location) {
                 Integer idx = new Integer(location);
@@ -886,7 +879,7 @@ public class ShaderState {
         }
         return location;
     }
-
+   
     /**
      * Validates and returns the location of a shader uniform.<br>
      * Uses either the cached value {@link #getCachedUniformLocation(String)} if valid,
@@ -908,26 +901,36 @@ public class ShaderState {
      * @see ShaderProgram#glReplaceShader
      */
     public int getUniformLocation(GL2ES2 gl, GLUniformData data) {
-        int location = getUniformLocation(gl, data.getName());
-        data.setLocation(location);
-        activeUniformDataMap.put(data.getName(), data);        
+        if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+        final String name = data.getName();
+        int location = getCachedUniformLocation(name);
+        if(0<=location) {
+            data.setLocation(location);
+        } else {
+            if(!shaderProgram.linked()) throw new GLException("Program is not linked");
+            location = data.setLocation(gl, shaderProgram.program());
+            if(0<=location) {
+                activeUniformLocationMap.put(name, new Integer(location));
+            } else if(verbose) {
+                System.err.println("ShaderState: glUniform failed, no location for: "+name+", index: "+location);
+                if(DEBUG) {
+                    Thread.dumpStack();
+                }
+            }
+        }        
+        activeUniformDataMap.put(name, data);        
         return location;
     }
     
     /**
-     * Set the uniform data.
-     *
-     * Even if the uniform is not found in the current shader,
-     * it is stored in this state.
-     *
-     * @param data the GLUniforms's name must match the uniform one,
-     *      it's index will be set with the uniforms's location,
-     *      if found.
-     *
-     *
-     * @return false, if the name is not found, otherwise true
+     * Set the uniform data, if it's location is valid, i.e. ≥ 0.
+     * <p>
+     * This method uses the {@link GLUniformData}'s location if valid, i.e. ≥ 0.<br/>
+     * If data's location is invalid, it will be retrieved via {@link #getUniformLocation(GL2ES2, GLUniformData)}, 
+     * set and cached in this state.
+     * </p>
      *
-     * @throws GLException if the program is not in use
+     * @return false, if the location could not be determined, otherwise true
      *
      * @see #glGetUniformLocation
      * @see javax.media.opengl.GL2ES2#glGetUniformLocation
@@ -947,10 +950,11 @@ public class ShaderState {
                 System.err.println("ShaderState: glUniform: "+data);
             }
             gl.glUniform(data);
+            return true;
         }
-        return true;
+        return false;
     }
-
+    
     /**
      * Get the uniform data, previously set.
      *
@@ -972,10 +976,15 @@ public class ShaderState {
         
     /**
      * Reset all previously mapped uniform data
-     * 
+     * <p>
      * Uniform data and location is bound to the program,
-     * hence both are updated here
-     *
+     * hence both are updated.
+     * </p>
+     * <p>
+     * Note: Such update could only be prevented, 
+     * if tracking a uniform/program dirty flag.
+     * </p>
+     * 
      * @throws GLException is the program is not in use
      * 
      * @see #attachShaderProgram(GL2ES2, ShaderProgram)
@@ -987,9 +996,16 @@ public class ShaderState {
             iter.next().setLocation(-1);
         }        
         for(Iterator<GLUniformData> iter = activeUniformDataMap.values().iterator(); iter.hasNext(); ) {
-            final GLUniformData uniform = iter.next();
-            uniform.setLocation(-1);
-            uniform(gl, uniform);
+            final GLUniformData data = iter.next();
+            final int loc = data.setLocation(gl, shaderProgram.program());
+            if( 0 <= loc ) {
+                // only pass the data, if the uniform exists in the current shader
+                activeUniformLocationMap.put(data.getName(), new Integer(loc));
+                if(DEBUG) {
+                    System.err.println("ShaderState: resetAllUniforms: "+data);
+                }
+                gl.glUniform(data);
+            }
         }
     }
 
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
index 5afc5e3..7d11065 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
@@ -40,6 +40,7 @@ import java.util.*;
 import javax.media.opengl.*;
 
 import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.GLExtensions;
 
 public class ShaderUtil {
     public static String getShaderInfoLog(GL _gl, int shaderObj) {
@@ -171,7 +172,10 @@ public class ShaderUtil {
                             info.shaderBinaryFormats.add(new Integer(formats[i]));
                         }
                     }
-                } catch (GLException gle) { System.err.println("Catched Exception: "+gle.getMessage()); gle.printStackTrace(); }                    
+                } catch (GLException gle) { 
+                    System.err.println("Catched Exception on thread "+Thread.currentThread().getName()); 
+                    gle.printStackTrace(); 
+                }
             }
         }
         return info.shaderBinaryFormats;
@@ -198,7 +202,10 @@ public class ShaderUtil {
                     }
                     info.shaderCompilerAvailable = new Boolean(v);
                     queryOK = true;
-                } catch (GLException gle) { System.err.println("Catched Exception: "+gle.getMessage()); gle.printStackTrace(); }
+                } catch (GLException gle) { 
+                    System.err.println("Catched Exception on thread "+Thread.currentThread().getName()); 
+                    gle.printStackTrace(); 
+                }
                 if(!queryOK) {
                     info.shaderCompilerAvailable = new Boolean(true);
                 }                
@@ -210,6 +217,13 @@ public class ShaderUtil {
         }
         return info.shaderCompilerAvailable.booleanValue();
     }
+    
+    /** Returns true if GeometryShader is supported, i.e. whether GLContext is ≥ 3.2 or ARB_geometry_shader4 extension is available. */ 
+    public static boolean isGeometryShaderSupported(GL _gl) {
+      final GLContext ctx = _gl.getContext();
+      return ctx.getGLVersionNumber().compareTo(GLContext.Version32) >= 0 ||
+             ctx.isExtensionAvailable(GLExtensions.ARB_geometry_shader4);
+    }
 
     public static void shaderSource(GL _gl, int shader, CharSequence[] source)
     {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
index 6e66e3d..bf85bea 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 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
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java
index 3964703..3931b72 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 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
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
index 96ee233..dec1b43 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 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
@@ -41,6 +42,7 @@ import java.nio.Buffer;
 import javax.media.opengl.GLProfile;
 
 import com.jogamp.opengl.util.GLBuffers;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
 
 /**
  * Represents the data for an OpenGL texture. This is separated from
@@ -54,11 +56,13 @@ import com.jogamp.opengl.util.GLBuffers;
  */
 
 public class TextureData {
+    /** ColorSpace of pixel data. */
+    public static enum ColorSpace { RGB, YCbCr, YCCK, CMYK };   
+    
     protected int width;
     protected int height;
     private int border;
-    protected int pixelFormat;
-    protected int pixelType;
+    protected GLPixelAttributes pixelAttributes;
     protected int internalFormat; // perhaps inferred from pixelFormat?
     protected boolean mipmap; // indicates whether mipmaps should be generated
     // (ignored if mipmaps are supplied from the file)
@@ -77,6 +81,7 @@ public class TextureData {
     protected boolean haveEXTABGR;
     protected boolean haveGL12;
     protected GLProfile glProfile;
+    protected ColorSpace pixelCS = ColorSpace.RGB;
 
     /** 
      * Constructs a new TextureData object with the specified parameters
@@ -130,6 +135,60 @@ public class TextureData {
                        boolean mustFlipVertically,
                        Buffer buffer,
                        Flusher flusher) throws IllegalArgumentException {
+        this(glp, internalFormat, width, height, border, new GLPixelAttributes(pixelFormat, pixelType), 
+             mipmap, dataIsCompressed, mustFlipVertically, buffer, flusher);
+    }
+
+    /** 
+     * Constructs a new TextureData object with the specified parameters
+     * and data contained in the given Buffer. The optional Flusher can
+     * be used to clean up native resources associated with this
+     * TextureData when processing is complete; for example, closing of
+     * memory-mapped files that might otherwise require a garbage
+     * collection to reclaim and close.
+     *
+     * @param glp the OpenGL Profile this texture data should be
+     *                  created for.
+     * @param internalFormat the OpenGL internal format for the
+     *                       resulting texture; must be specified, may
+     *                       not be 0
+     * @param width          the width in pixels of the texture
+     * @param height         the height in pixels of the texture
+     * @param border         the number of pixels of border this texture
+     *                       data has (0 or 1)
+     * @param pixelAttributes the OpenGL pixel format and type for the
+     *                       resulting texture; must be specified, may
+     *                       not be 0
+     * @param mipmap         indicates whether mipmaps should be
+     *                       autogenerated (using GLU) for the resulting
+     *                       texture. Currently if mipmap is true then
+     *                       dataIsCompressed may not be true.
+     * @param dataIsCompressed indicates whether the texture data is in
+     *                       compressed form
+     *                       (e.g. GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
+     * @param mustFlipVertically indicates whether the texture
+     *                           coordinates must be flipped vertically
+     *                           in order to properly display the
+     *                           texture
+     * @param buffer         the buffer containing the texture data
+     * @param flusher        optional flusher to perform cleanup tasks
+     *                       upon call to flush()
+     *
+     * @throws IllegalArgumentException if any parameters of the texture
+     *   data were invalid, such as requesting mipmap generation for a
+     *   compressed texture
+     */
+    public TextureData(GLProfile glp, 
+                       int internalFormat,
+                       int width,
+                       int height,
+                       int border,
+                       GLPixelAttributes pixelAttributes,
+                       boolean mipmap,
+                       boolean dataIsCompressed,
+                       boolean mustFlipVertically,
+                       Buffer buffer,
+                       Flusher flusher) throws IllegalArgumentException {
         if (mipmap && dataIsCompressed) {
             throw new IllegalArgumentException("Can not generate mipmaps for compressed textures");
         }
@@ -138,8 +197,7 @@ public class TextureData {
         this.width = width;
         this.height = height;
         this.border = border;
-        this.pixelFormat = pixelFormat;
-        this.pixelType = pixelType;
+        this.pixelAttributes = pixelAttributes;
         this.internalFormat = internalFormat;
         this.mipmap = mipmap;
         this.dataIsCompressed = dataIsCompressed;
@@ -149,7 +207,7 @@ public class TextureData {
         alignment = 1;  // FIXME: is this correct enough in all situations?
         estimatedMemorySize = estimatedMemorySize(buffer);
     }
-
+    
     /** 
      * Constructs a new TextureData object with the specified parameters
      * and data for multiple mipmap levels contained in the given array
@@ -200,12 +258,63 @@ public class TextureData {
                        boolean mustFlipVertically,
                        Buffer[] mipmapData,
                        Flusher flusher) throws IllegalArgumentException {
+        this(glp, internalFormat, width, height, border, new GLPixelAttributes(pixelFormat, pixelType), 
+             dataIsCompressed, mustFlipVertically, mipmapData, flusher);
+    }
+
+    /** 
+     * Constructs a new TextureData object with the specified parameters
+     * and data for multiple mipmap levels contained in the given array
+     * of Buffers. The optional Flusher can be used to clean up native
+     * resources associated with this TextureData when processing is
+     * complete; for example, closing of memory-mapped files that might
+     * otherwise require a garbage collection to reclaim and close.
+     *
+     * @param glp the OpenGL Profile this texture data should be
+     *                  created for.
+     * @param internalFormat the OpenGL internal format for the
+     *                       resulting texture; must be specified, may
+     *                       not be 0
+     * @param width          the width in pixels of the topmost mipmap
+     *                       level of the texture
+     * @param height         the height in pixels of the topmost mipmap
+     *                       level of the texture
+     * @param border         the number of pixels of border this texture
+     *                       data has (0 or 1)
+     * @param pixelAttributes the OpenGL pixel format and type for the
+     *                       resulting texture; must be specified, may
+     *                       not be 0
+     * @param dataIsCompressed indicates whether the texture data is in
+     *                       compressed form
+     *                       (e.g. GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
+     * @param mustFlipVertically indicates whether the texture
+     *                           coordinates must be flipped vertically
+     *                           in order to properly display the
+     *                           texture
+     * @param mipmapData     the buffers containing all mipmap levels
+     *                       of the texture's data
+     * @param flusher        optional flusher to perform cleanup tasks
+     *                       upon call to flush()
+     *
+     * @throws IllegalArgumentException if any parameters of the texture
+     *   data were invalid, such as requesting mipmap generation for a
+     *   compressed texture
+     */
+    public TextureData(GLProfile glp,
+                       int internalFormat,
+                       int width,
+                       int height,
+                       int border,
+                       GLPixelAttributes pixelAttributes,
+                       boolean dataIsCompressed,
+                       boolean mustFlipVertically,
+                       Buffer[] mipmapData,
+                       Flusher flusher) throws IllegalArgumentException {
         this.glProfile = glp;
         this.width = width;
         this.height = height;
         this.border = border;
-        this.pixelFormat = pixelFormat;
-        this.pixelType = pixelType;
+        this.pixelAttributes = pixelAttributes;
         this.internalFormat = internalFormat;
         this.dataIsCompressed = dataIsCompressed;
         this.mustFlipVertically = mustFlipVertically;
@@ -216,9 +325,21 @@ public class TextureData {
             estimatedMemorySize += estimatedMemorySize(mipmapData[i]);
         }
     }
+    
+    /** 
+     * Returns the color space of the pixel data.
+     * @see #setColorSpace(ColorSpace) 
+     */
+    public ColorSpace getColorSpace() { return pixelCS; }
 
+    /** 
+     * Set the color space of the pixel data, which defaults to {@link ColorSpace#RGB}.
+     * @see #getColorSpace() 
+     */
+    public void setColorSpace(ColorSpace cs) { pixelCS = cs; }
+    
     /** Used only by subclasses */
-    protected TextureData(GLProfile glp) { this.glProfile = glp; }
+    protected TextureData(GLProfile glp) { this.glProfile = glp; this.pixelAttributes = GLPixelAttributes.UNDEF; }
 
     /** Returns the width in pixels of the texture data. */
     public int getWidth() { return width; }
@@ -228,13 +349,17 @@ public class TextureData {
     public int getBorder() { 
         return border; 
     }
+    /** Returns the intended OpenGL {@link GLPixelAttributes} of the texture data, i.e. format and type. */
+    public GLPixelAttributes getPixelAttributes() {
+        return pixelAttributes;
+    }
     /** Returns the intended OpenGL pixel format of the texture data. */
     public int getPixelFormat() {
-        return pixelFormat;
+        return pixelAttributes.format;
     }
     /** Returns the intended OpenGL pixel type of the texture data. */
     public int getPixelType() {
-        return pixelType;
+        return pixelAttributes.type;
     }
     /** Returns the intended OpenGL internal format of the texture data. */
     public int getInternalFormat() { 
@@ -280,9 +405,29 @@ public class TextureData {
     /** Sets the border in pixels of the texture data. */
     public void setBorder(int border) { this.border = border; }
     /** Sets the intended OpenGL pixel format of the texture data. */
-    public void setPixelFormat(int pixelFormat) { this.pixelFormat = pixelFormat; }
-    /** Sets the intended OpenGL pixel type of the texture data. */
-    public void setPixelType(int pixelType) { this.pixelType = pixelType; }
+    public void setPixelAttributes(GLPixelAttributes pixelAttributes) { this.pixelAttributes = pixelAttributes; }     
+    /** 
+     * Sets the intended OpenGL pixel format component of {@link GLPixelAttributes} of the texture data.
+     * <p>
+     * Use {@link #setPixelAttributes(GLPixelAttributes)}, if setting format and type. 
+     * </p> 
+     */
+    public void setPixelFormat(int pixelFormat) {
+        if( pixelAttributes.format != pixelFormat ) {
+            pixelAttributes = new GLPixelAttributes(pixelFormat, pixelAttributes.type);
+        }
+    }
+    /** 
+     * Sets the intended OpenGL pixel type component of {@link GLPixelAttributes} of the texture data.
+     * <p>
+     * Use {@link #setPixelAttributes(GLPixelAttributes)}, if setting format and type. 
+     * </p> 
+     */
+    public void setPixelType(int pixelType) { 
+        if( pixelAttributes.type != pixelType) {
+            pixelAttributes = new GLPixelAttributes(pixelAttributes.format, pixelType);
+        }
+    }
     /** Sets the intended OpenGL internal format of the texture data. */
     public void setInternalFormat(int internalFormat) { this.internalFormat = internalFormat; }
     /** Sets whether mipmaps should be generated for the texture data. */
@@ -355,7 +500,8 @@ public class TextureData {
     }
 
     public String toString() {
-        return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", internFormat 0x"+Integer.toHexString(internalFormat)+", pixelFormat 0x"+Integer.toHexString(pixelFormat)+", pixelType 0x"+Integer.toHexString(pixelType)+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength;
+        return "TextureData["+width+"x"+height+", y-flip "+mustFlipVertically+", internFormat 0x"+Integer.toHexString(internalFormat)+", "+
+                pixelAttributes+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength;
     }
 
     //----------------------------------------------------------------------
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
index b878c60..14ceb64 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
@@ -63,6 +63,7 @@ import jogamp.opengl.Debug;
 
 import com.jogamp.common.util.IOUtil;
 import com.jogamp.opengl.util.texture.spi.DDSImage;
+import com.jogamp.opengl.util.texture.spi.JPEGImage;
 import com.jogamp.opengl.util.texture.spi.NetPbmTextureWriter;
 import com.jogamp.opengl.util.texture.spi.PNGImage;
 import com.jogamp.opengl.util.texture.spi.SGIImage;
@@ -714,8 +715,12 @@ public class TextureIO {
     // SPI support
     //
 
-    /** Adds a TextureProvider to support reading of a new file
-        format. */
+    /** 
+     * Adds a TextureProvider to support reading of a new file format.
+     * <p>
+     * The last provider added, will be the first provider to be tested.
+     * </p>
+     */
     public static void addTextureProvider(TextureProvider provider) {
         // Must always add at the front so the ImageIO provider is last,
         // so we don't accidentally use it instead of a user's possibly
@@ -723,8 +728,12 @@ public class TextureIO {
         textureProviders.add(0, provider);
     }
 
-    /** Adds a TextureWriter to support writing of a new file
-        format. */
+    /** 
+     * Adds a TextureWriter to support writing of a new file format.
+     * <p>
+     * The last provider added, will be the first provider to be tested.
+     * </p>
+     */
     public static void addTextureWriter(TextureWriter writer) {
         // Must always add at the front so the ImageIO writer is last,
         // so we don't accidentally use it instead of a user's possibly
@@ -768,7 +777,7 @@ public class TextureIO {
     private static List<TextureProvider> textureProviders = new ArrayList<TextureProvider>();
     private static List<TextureWriter>   textureWriters   = new ArrayList<TextureWriter>();
 
-    static {
+    static {        
         // ImageIO provider, the fall-back, must be the first one added
         if(GLProfile.isAWTAvailable()) {
             try {
@@ -787,6 +796,7 @@ public class TextureIO {
         addTextureProvider(new DDSTextureProvider());
         addTextureProvider(new SGITextureProvider());
         addTextureProvider(new TGATextureProvider());
+        addTextureProvider(new JPGTextureProvider());
         addTextureProvider(new PNGTextureProvider());
 
         // ImageIO writer, the fall-back, must be the first one added
@@ -1174,6 +1184,43 @@ public class TextureIO {
     }
 
     //----------------------------------------------------------------------
+    // JPEG image provider
+    static class JPGTextureProvider extends StreamBasedTextureProvider {
+        public TextureData newTextureData(GLProfile glp, InputStream stream,
+                                          int internalFormat,
+                                          int pixelFormat,
+                                          boolean mipmap,
+                                          String fileSuffix) throws IOException {
+            if (JPG.equals(fileSuffix)) {
+                JPEGImage image = JPEGImage.read(/*glp, */ stream);
+                if (pixelFormat == 0) {
+                    pixelFormat = image.getGLFormat();
+                }
+                if (internalFormat == 0) {
+                    if(glp.isGL2GL3()) {
+                        internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA8:GL.GL_RGB8;
+                    } else {
+                        internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB;
+                    }
+                }
+                return new TextureData(glp, internalFormat,
+                                       image.getWidth(),
+                                       image.getHeight(),
+                                       0,
+                                       pixelFormat,
+                                       image.getGLType(),
+                                       mipmap,
+                                       false,
+                                       false,
+                                       image.getData(),
+                                       null);
+            }
+
+            return null;
+        }
+    }
+    
+    //----------------------------------------------------------------------
     // DDS texture writer
     //
     static class DDSTextureWriter implements TextureWriter {
@@ -1361,7 +1408,7 @@ public class TextureIO {
                     buf.rewind();
                     
                     PNGImage image = PNGImage.createFromData(data.getWidth(), data.getHeight(), -1f, -1f,
-                                                             bytesPerPixel, reversedChannels, buf);
+                                                             bytesPerPixel, reversedChannels, !data.getMustFlipVertically(), buf);
                     image.write(file, true);
                     return true;
                 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
index ad96a99..d7e825c 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 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
@@ -37,15 +38,36 @@
 package com.jogamp.opengl.util.texture.awt;
 
 import java.awt.AlphaComposite;
-import java.awt.Color;
 import java.awt.Graphics2D;
 import java.awt.Transparency;
-import java.awt.color.*;
-import java.awt.image.*;
-import java.nio.*;
+import java.awt.image.BufferedImage;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.ComponentSampleModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferDouble;
+import java.awt.image.DataBufferFloat;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DataBufferShort;
+import java.awt.image.DataBufferUShort;
+import java.awt.image.MultiPixelPackedSampleModel;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.awt.image.WritableRaster;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
 
-import javax.media.opengl.*;
-import com.jogamp.opengl.util.texture.*;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.texture.TextureData;
 
 public class AWTTextureData extends TextureData {
     // Mechanism for lazily converting input BufferedImages with custom
@@ -56,13 +78,13 @@ public class AWTTextureData extends TextureData {
     private boolean expectingEXTABGR;
     private boolean expectingGL12;
 
-    private static final ColorModel rgbaColorModel =
-        new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+    private static final java.awt.image.ColorModel rgbaColorModel =
+        new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB),
                                 new int[] {8, 8, 8, 8}, true, true, 
                                 Transparency.TRANSLUCENT,
                                 DataBuffer.TYPE_BYTE);
-    private static final ColorModel rgbColorModel =
-        new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+    private static final java.awt.image.ColorModel rgbColorModel =
+        new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB),
                                 new int[] {8, 8, 8, 0}, false, false,
                                 Transparency.OPAQUE,
                                 DataBuffer.TYPE_BYTE);
@@ -114,33 +136,38 @@ public class AWTTextureData extends TextureData {
         }
     }
 
-    /** Returns the intended OpenGL pixel format of the texture data. */
-    public int getPixelFormat() {
+    private void validatePixelAttributes() {
         if (imageForLazyCustomConversion != null) {
             if (!((expectingEXTABGR && haveEXTABGR) ||
                   (expectingGL12    && haveGL12))) {
-                revertPixelFormatAndType();
+                revertPixelAttributes();
             }
-        }
-        return pixelFormat;
+        }        
     }
-    /** Returns the intended OpenGL pixel type of the texture data. */
+    
+    @Override
+    public GLPixelAttributes getPixelAttributes() {
+        validatePixelAttributes();
+        return super.getPixelAttributes();
+    }
+    
+    @Override
+    public int getPixelFormat() {
+        validatePixelAttributes();
+        return super.getPixelFormat();
+    }
+    @Override
     public int getPixelType() {
-        if (imageForLazyCustomConversion != null) {
-            if (!((expectingEXTABGR && haveEXTABGR) ||
-                  (expectingGL12    && haveGL12))) {
-                revertPixelFormatAndType();
-            }
-        }
-        return pixelType;
+        validatePixelAttributes();
+        return super.getPixelType();
     }
 
-    /** Returns the texture data, or null if it is specified as a set of mipmaps. */
+    @Override
     public Buffer getBuffer() {
         if (imageForLazyCustomConversion != null) {
             if (!((expectingEXTABGR && haveEXTABGR) ||
                   (expectingGL12    && haveGL12))) {
-                revertPixelFormatAndType();
+                revertPixelAttributes();
                 // Must present the illusion to the end user that we are simply
                 // wrapping the input BufferedImage
                 createFromCustom(imageForLazyCustomConversion);
@@ -150,7 +177,7 @@ public class AWTTextureData extends TextureData {
     }
 
     private void createFromImage(GLProfile glp, BufferedImage image) {
-        pixelType = 0; // Determine from image
+        pixelAttributes = GLPixelAttributes.UNDEF; // Determine from image
         mustFlipVertically = true;
 
         width = image.getWidth();
@@ -180,24 +207,21 @@ public class AWTTextureData extends TextureData {
         if (glp.isGL2GL3()) {
             switch (image.getType()) {
                 case BufferedImage.TYPE_INT_RGB:
-                    pixelFormat = GL.GL_BGRA;
-                    pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
                     rowLength = scanlineStride;
                     alignment = 4;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_INT_ARGB_PRE:
-                    pixelFormat = GL.GL_BGRA;
-                    pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
                     rowLength = scanlineStride;
                     alignment = 4;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_INT_BGR:
-                    pixelFormat = GL.GL_RGBA;
-                    pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
                     rowLength = scanlineStride;
                     alignment = 4;
                     expectingGL12 = true;
@@ -208,8 +232,7 @@ public class AWTTextureData extends TextureData {
                         // we can pass the image data directly to OpenGL only if
                         // we have an integral number of pixels in each scanline
                         if ((scanlineStride % 3) == 0) {
-                            pixelFormat = GL2GL3.GL_BGR;
-                            pixelType = GL.GL_UNSIGNED_BYTE;
+                            pixelAttributes = new GLPixelAttributes(GL2GL3.GL_BGR, GL.GL_UNSIGNED_BYTE);
                             rowLength = scanlineStride / 3;
                             alignment = 1;
                         } else {
@@ -229,8 +252,7 @@ public class AWTTextureData extends TextureData {
                         // the necessary byte swapping (FIXME: needs more
                         // investigation)
                         if ((scanlineStride % 4) == 0 && glp.isGL2() && false) {
-                            pixelFormat = GL2.GL_ABGR_EXT;
-                            pixelType = GL.GL_UNSIGNED_BYTE;
+                            pixelAttributes = new GLPixelAttributes(GL2.GL_ABGR_EXT, GL.GL_UNSIGNED_BYTE);
                             rowLength = scanlineStride / 4;
                             alignment = 4;
     
@@ -246,30 +268,26 @@ public class AWTTextureData extends TextureData {
                         }
                     }
                 case BufferedImage.TYPE_USHORT_565_RGB:
-                    pixelFormat = GL.GL_RGB;
-                    pixelType = GL.GL_UNSIGNED_SHORT_5_6_5;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
                     rowLength = scanlineStride;
                     alignment = 2;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_USHORT_555_RGB:
-                    pixelFormat = GL.GL_BGRA;
-                    pixelType = GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV);
                     rowLength = scanlineStride;
                     alignment = 2;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_BYTE_GRAY:
-                    pixelFormat = GL.GL_LUMINANCE;
-                    pixelType = GL.GL_UNSIGNED_BYTE;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
                     rowLength = scanlineStride;
                     alignment = 1;
                     break;
                 case BufferedImage.TYPE_USHORT_GRAY:
-                    pixelFormat = GL.GL_LUMINANCE;
-                    pixelType = GL.GL_UNSIGNED_SHORT;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_SHORT);
                     rowLength = scanlineStride;
                     alignment = 2;
                     break;
@@ -282,15 +300,13 @@ public class AWTTextureData extends TextureData {
                 case BufferedImage.TYPE_BYTE_INDEXED:
                 case BufferedImage.TYPE_CUSTOM:
                 default:
-                    ColorModel cm = image.getColorModel();
+                    java.awt.image.ColorModel cm = image.getColorModel();
                     if (cm.equals(rgbColorModel)) {
-                        pixelFormat = GL.GL_RGB;
-                        pixelType = GL.GL_UNSIGNED_BYTE;
+                        pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
                         rowLength = scanlineStride / 3;
                         alignment = 1;
                     } else if (cm.equals(rgbaColorModel)) {
-                        pixelFormat = GL.GL_RGBA;
-                        pixelType = GL.GL_UNSIGNED_BYTE;
+                        pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
                         rowLength = scanlineStride / 4; // FIXME: correct?
                         alignment = 4;
                     } else {
@@ -302,8 +318,7 @@ public class AWTTextureData extends TextureData {
         } else {
             switch (image.getType()) {
                 case BufferedImage.TYPE_INT_RGB:
-                    pixelFormat = GL.GL_RGB;
-                    pixelType = GL.GL_UNSIGNED_BYTE;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
                     rowLength = scanlineStride;
                     alignment = 3;
                     expectingGL12 = true;
@@ -318,24 +333,21 @@ public class AWTTextureData extends TextureData {
                 case BufferedImage.TYPE_4BYTE_ABGR_PRE:
                     throw new GLException("INT_BGR n.a.");
                 case BufferedImage.TYPE_USHORT_565_RGB:
-                    pixelFormat = GL.GL_RGB;
-                    pixelType = GL.GL_UNSIGNED_SHORT_5_6_5;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
                     rowLength = scanlineStride;
                     alignment = 2;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_USHORT_555_RGB:
-                    pixelFormat = GL.GL_RGBA;
-                    pixelType = GL.GL_UNSIGNED_SHORT_5_5_5_1;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1);
                     rowLength = scanlineStride;
                     alignment = 2;
                     expectingGL12 = true;
                     setupLazyCustomConversion(image);
                     break;
                 case BufferedImage.TYPE_BYTE_GRAY:
-                    pixelFormat = GL.GL_LUMINANCE;
-                    pixelType = GL.GL_UNSIGNED_BYTE;
+                    pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
                     rowLength = scanlineStride;
                     alignment = 1;
                     break;
@@ -350,15 +362,13 @@ public class AWTTextureData extends TextureData {
                 case BufferedImage.TYPE_BYTE_INDEXED:
                 case BufferedImage.TYPE_CUSTOM:
                 default:
-                    ColorModel cm = image.getColorModel();
+                    java.awt.image.ColorModel cm = image.getColorModel();
                     if (cm.equals(rgbColorModel)) {
-                        pixelFormat = GL.GL_RGB;
-                        pixelType = GL.GL_UNSIGNED_BYTE;
+                        pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
                         rowLength = scanlineStride / 3;
                         alignment = 1;
                     } else if (cm.equals(rgbaColorModel)) {
-                        pixelFormat = GL.GL_RGBA;
-                        pixelType = GL.GL_UNSIGNED_BYTE;
+                        pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
                         rowLength = scanlineStride / 4; // FIXME: correct?
                         alignment = 4;
                     } else {
@@ -375,6 +385,8 @@ public class AWTTextureData extends TextureData {
     private void setupLazyCustomConversion(BufferedImage image) {
         imageForLazyCustomConversion = image;
         boolean hasAlpha = image.getColorModel().hasAlpha();
+        int pixelFormat = pixelAttributes.format;
+        int pixelType = pixelAttributes.type;
         if (pixelFormat == 0) {
             pixelFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB;
         }
@@ -401,6 +413,7 @@ public class AWTTextureData extends TextureData {
         } else {
             throw new RuntimeException("Unexpected DataBuffer type?");
         }
+        pixelAttributes = new GLPixelAttributes(pixelFormat, pixelType);
     }
 
     private void createFromCustom(BufferedImage image) {
@@ -409,7 +422,7 @@ public class AWTTextureData extends TextureData {
 
         // create a temporary image that is compatible with OpenGL
         boolean hasAlpha = image.getColorModel().hasAlpha();
-        ColorModel cm = null;
+        java.awt.image.ColorModel cm = null;
         int dataBufferType = image.getRaster().getDataBuffer().getDataType();
         // Don't use integer components for packed int images
         if (isPackedInt(image)) {
@@ -419,12 +432,12 @@ public class AWTTextureData extends TextureData {
             cm = hasAlpha ? rgbaColorModel : rgbColorModel;
         } else {
             if (hasAlpha) {
-                cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                cm = new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB),
                                              null, true, true,
                                              Transparency.TRANSLUCENT,
                                              dataBufferType);
             } else {
-                cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                cm = new ComponentColorModel(java.awt.color.ColorSpace.getInstance(java.awt.color.ColorSpace.CS_sRGB),
                                              null, false, false,
                                              Transparency.OPAQUE,
                                              dataBufferType);
@@ -454,13 +467,12 @@ public class AWTTextureData extends TextureData {
                 imgType == BufferedImage.TYPE_INT_ARGB_PRE);
     }
 
-    private void revertPixelFormatAndType() {
+    private void revertPixelAttributes() {
         // Knowing we don't have e.g. OpenGL 1.2 functionality available,
         // and knowing we're in the process of doing the fallback code
         // path, re-infer a vanilla pixel format and type compatible with
         // OpenGL 1.1
-        pixelFormat = 0;
-        pixelType = 0;
+        pixelAttributes = GLPixelAttributes.UNDEF;
         setupLazyCustomConversion(imageForLazyCustomConversion);
     }
 
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java
new file mode 100644
index 0000000..4d3d088
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/JPEGImage.java
@@ -0,0 +1,175 @@
+/**
+ * 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.util.texture.spi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+import javax.media.opengl.GL;
+
+import jogamp.opengl.Debug;
+import jogamp.opengl.util.jpeg.JPEGDecoder;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.texture.TextureData.ColorSpace;
+
+public class JPEGImage {
+    private static final boolean DEBUG = Debug.debug("JPEGImage");    
+    
+    
+    /**
+     * Reads a JPEG image from the specified InputStream, using the given color space for storage.
+     * 
+     * @param in
+     * @param cs Storage color space, either {@link ColorSpace#RGB} or {@link ColorSpace#YCbCr}. {@link ColorSpace#YCCK} and {@link ColorSpace#CMYK} will throw an exception!
+     * @return
+     * @throws IOException
+     */
+    public static JPEGImage read(InputStream in, ColorSpace cs) throws IOException {
+        return new JPEGImage(in, cs);
+    }
+    
+    /** Reads a JPEG image from the specified InputStream, using the {@link ColorSpace#RGB}. */
+    public static JPEGImage read(InputStream in) throws IOException {
+        return new JPEGImage(in, ColorSpace.RGB);
+    }
+    
+    private static class JPEGColorSink implements JPEGDecoder.ColorSink  {
+        int width=0, height=0;
+        int sourceComponents=0;
+        ColorSpace sourceCS = ColorSpace.YCbCr;
+        int storageComponents;
+        final ColorSpace storageCS;
+        ByteBuffer data = null;
+        
+        JPEGColorSink(ColorSpace storageCM) {
+            this.storageCS = storageCM;
+            switch(storageCS) {
+            case RGB:
+            case YCbCr:
+                storageComponents = 3;
+                break;
+            default:
+                throw new IllegalArgumentException("Unsupported storage color-space: "+storageCS);
+            }
+        }
+        
+        @Override
+        public final ColorSpace allocate(int width, int height, ColorSpace sourceCM, int sourceComponents) throws RuntimeException {
+            this.width = width;
+            this.height = height;
+            this.sourceComponents = sourceComponents;
+            this.sourceCS = sourceCM;
+            this.data = Buffers.newDirectByteBuffer(width * height * storageComponents);
+            return storageCS;
+        }
+
+        @Override
+        public final void storeRGB(int x, int y, byte r, byte g, byte b) {
+            int i = ( ( height - y - 1 ) * width + x ) * storageComponents;
+            data.put(i++, r);
+            data.put(i++, g);
+            data.put(i++, b);
+            // data.put(i++, (byte)0xff);            
+        }
+
+        @Override
+        public final void store2(int x, int y, byte c1, byte c2) {
+            throw new RuntimeException("not supported yet");
+        }
+
+        @Override
+        public final void storeYCbCr(int x, int y, byte Y, byte Cb, byte Cr) {
+            int i = ( ( height - y - 1 ) * width + x ) * storageComponents;
+            data.put(i++, Y);
+            data.put(i++, Cb);
+            data.put(i++, Cr);
+        }
+        
+        public String toString() {
+            return "JPEGPixels["+width+"x"+height+", sourceComp "+sourceComponents+", sourceCS "+sourceCS+", storageCS "+storageCS+", storageComp "+storageComponents+"]";
+        }
+    };
+    
+    private JPEGImage(InputStream in, ColorSpace cs) throws IOException {
+        pixelStorage = new JPEGColorSink(cs);
+        final JPEGDecoder decoder = new JPEGDecoder();
+        decoder.parse(in);
+        pixelWidth = decoder.getWidth();
+        pixelHeight = decoder.getHeight();
+        decoder.getPixel(pixelStorage, pixelWidth, pixelHeight);
+        data = pixelStorage.data;
+        final boolean hasAlpha = false;
+        
+        bytesPerPixel = 3;
+        glFormat = GL.GL_RGB;
+        reversedChannels = false; // RGB[A]
+        if(DEBUG) {
+            System.err.println("JPEGImage: alpha "+hasAlpha+", bytesPerPixel "+bytesPerPixel+
+                               ", pixels "+pixelWidth+"x"+pixelHeight+", glFormat 0x"+Integer.toHexString(glFormat));
+            System.err.println("JPEGImage: "+decoder);
+            System.err.println("JPEGImage: "+pixelStorage);
+        }
+        decoder.clear(null);
+    }
+    private JPEGColorSink pixelStorage;
+    private final int pixelWidth, pixelHeight, glFormat, bytesPerPixel;
+    private boolean reversedChannels;
+    private final ByteBuffer data;
+    
+    /** Returns the color space of the pixel data */
+    public ColorSpace getColorSpace() { return pixelStorage.storageCS; }
+
+    /** Returns the number of components of the pixel data */
+    public int getComponentCount() { return pixelStorage.storageComponents; }
+
+    /** Returns the width of the image. */
+    public int getWidth()    { return pixelWidth; }
+
+    /** Returns the height of the image. */
+    public int getHeight()   { return pixelHeight; }
+
+    /** Returns true if data has the channels reversed to BGR or BGRA, otherwise RGB or RGBA is expected. */
+    public boolean getHasReversedChannels() { return reversedChannels; }
+    
+    /** Returns the OpenGL format for this texture; e.g. GL.GL_LUMINANCE, GL.GL_RGB or GL.GL_RGBA. */
+    public int getGLFormat() { return glFormat; }
+    
+    /** Returns the OpenGL data type: GL.GL_UNSIGNED_BYTE. */
+    public int getGLType() { return GL.GL_UNSIGNED_BYTE; }
+
+    /** Returns the bytes per pixel */
+    public int getBytesPerPixel() { return bytesPerPixel; }
+
+    /** Returns the raw data for this texture in the correct
+        (bottom-to-top) order for calls to glTexImage2D. */
+    public ByteBuffer getData()  { return data; }
+    
+    public String toString() { return "JPEGImage["+pixelWidth+"x"+pixelHeight+", bytesPerPixel "+bytesPerPixel+", reversedChannels "+reversedChannels+", "+pixelStorage+", "+data+"]"; }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
index d8d6f7d..b4b00e7 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
@@ -1,3 +1,30 @@
+/**
+ * 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.util.texture.spi;
 
 import java.io.BufferedInputStream;
@@ -10,61 +37,86 @@ import java.nio.ByteBuffer;
 
 import javax.media.opengl.GL;
 
+import jogamp.opengl.Debug;
 import jogamp.opengl.util.pngj.ImageInfo;
 import jogamp.opengl.util.pngj.ImageLine;
+import jogamp.opengl.util.pngj.ImageLineHelper;
 import jogamp.opengl.util.pngj.PngReader;
 import jogamp.opengl.util.pngj.PngWriter;
+import jogamp.opengl.util.pngj.chunks.PngChunkPLTE;
+import jogamp.opengl.util.pngj.chunks.PngChunkTRNS;
 import jogamp.opengl.util.pngj.chunks.PngChunkTextVar;
 
 import com.jogamp.common.nio.Buffers;
 import com.jogamp.common.util.IOUtil;
 
-
-public class PNGImage {    
-    /** Creates a PNGImage from data supplied by the end user. Shares
-        data with the passed ByteBuffer. Assumes the data is already in
-        the correct byte order for writing to disk, i.e., LUMINANCE, RGB or RGBA bottom-to-top (OpenGL coord). */
+public class PNGImage {
+    private static final boolean DEBUG = Debug.debug("PNGImage");    
+    
+    /**
+     * Creates a PNGImage from data supplied by the end user. Shares
+     * data with the passed ByteBuffer. Assumes the data is already in
+     * the correct byte order for writing to disk, i.e., LUMINANCE, RGB or RGBA.
+     * Orientation is <i>bottom-to-top</i> (OpenGL coord. default)
+     * or <i>top-to-bottom</i> depending on <code>isGLOriented</code>.
+     * 
+     * @param width
+     * @param height
+     * @param dpiX
+     * @param dpiY
+     * @param bytesPerPixel
+     * @param reversedChannels
+     * @param isGLOriented see {@link #isGLOriented()}.
+     * @param data
+     * @return
+     */
     public static PNGImage createFromData(int width, int height, double dpiX, double dpiY,
-                                          int bytesPerPixel, boolean reversedChannels, ByteBuffer data) {
-        return new PNGImage(width, height, dpiX, dpiY, bytesPerPixel, reversedChannels, data);
+                                          int bytesPerPixel, boolean reversedChannels, boolean isGLOriented, ByteBuffer data) {
+        return new PNGImage(width, height, dpiX, dpiY, bytesPerPixel, reversedChannels, isGLOriented, data);
     }
     
-    /** Reads a PNG image from the specified InputStream. */
+    /** 
+     * Reads a PNG image from the specified InputStream.
+     * <p>
+     * Implicitly flip image to GL orientation, see {@link #isGLOriented()}.
+     * </p> 
+     */
     public static PNGImage read(InputStream in) throws IOException {
         return new PNGImage(in);
     }
     
-    /** Reverse read and store, implicitly flip image to GL coords. */
-    private static final int getPixelRGBA8(ByteBuffer d, int dOff, ImageLine line, int lineOff, boolean hasAlpha) {
-        if(hasAlpha) {
-            d.put(dOff--, (byte)line.scanline[lineOff + 3]); // A
+    /** Reverse read and store, implicitly flip image to GL orientation, see {@link #isGLOriented()}. */
+    private static final int getPixelRGBA8(ByteBuffer d, int dOff, int[] scanline, int lineOff, boolean hasAlpha) {
+    	if(hasAlpha) {
+            d.put(dOff--, (byte)scanline[lineOff + 3]); // A
         }
-        d.put(dOff--, (byte)line.scanline[lineOff + 2]); // B
-        d.put(dOff--, (byte)line.scanline[lineOff + 1]); // G        
-        d.put(dOff--, (byte)line.scanline[lineOff    ]); // R
+        d.put(dOff--, (byte)scanline[lineOff + 2]); // B
+        d.put(dOff--, (byte)scanline[lineOff + 1]); // G        
+        d.put(dOff--, (byte)scanline[lineOff    ]); // R
         return dOff;
-    }    
-    /** Reverse read and store, implicitly flip image from GL coords. Handle reversed channels (BGR[A])*/
-    private static int setPixelRGBA8(ImageLine line, int lineOff, ByteBuffer d, int dOff, boolean hasAlpha, boolean reversedChannels) {
-        if(reversedChannels) {
-            line.scanline[lineOff    ] = d.get(dOff--); // R, A
-            line.scanline[lineOff + 1] = d.get(dOff--); // G, B
-            line.scanline[lineOff + 2] = d.get(dOff--); // B, G
+    }
+    
+    /** Reverse write and store, implicitly flip image from current orientation, see {@link #isGLOriented()}. Handle reversed channels (BGR[A]). */
+    private int setPixelRGBA8(ImageLine line, int lineOff, ByteBuffer d, int dOff, boolean hasAlpha) {
+        if( reversedChannels ) {
             if(hasAlpha) {
-                line.scanline[lineOff + 3] = d.get(dOff--);// R
+                line.scanline[lineOff + 3] = d.get(dOff++); // A
             }
+            line.scanline[lineOff + 2] = d.get(dOff++); // R
+            line.scanline[lineOff + 1] = d.get(dOff++); // G
+            line.scanline[lineOff    ] = d.get(dOff++); // B
         } else {
+            line.scanline[lineOff    ] = d.get(dOff++); // R
+            line.scanline[lineOff + 1] = d.get(dOff++); // G
+            line.scanline[lineOff + 2] = d.get(dOff++); // B
             if(hasAlpha) {
-                line.scanline[lineOff + 3] = d.get(dOff--); // A
+                line.scanline[lineOff + 3] = d.get(dOff++); // A
             }
-            line.scanline[lineOff + 2] = d.get(dOff--); // B
-            line.scanline[lineOff + 1] = d.get(dOff--); // G
-            line.scanline[lineOff    ] = d.get(dOff--); // R
         }
-        return dOff;
+        return isGLOriented ? dOff - bytesPerPixel - bytesPerPixel : dOff;
     }
 
-    private PNGImage(int width, int height, double dpiX, double dpiY, int bytesPerPixel, boolean reversedChannels, ByteBuffer data) {
+    private PNGImage(int width, int height, double dpiX, double dpiY, int bytesPerPixel, boolean reversedChannels, boolean isGLOriented, ByteBuffer data) {
         pixelWidth=width;
         pixelHeight=height;
         dpi = new double[] { dpiX, dpiY };
@@ -77,50 +129,81 @@ public class PNGImage {
         }
         this.bytesPerPixel = bytesPerPixel;
         this.reversedChannels = reversedChannels;
+        this.isGLOriented = isGLOriented;
         this.data = data;        
     }
     
     private PNGImage(InputStream in) {
         final PngReader pngr = new PngReader(new BufferedInputStream(in), null);
-        final int channels = pngr.imgInfo.channels;
+        final ImageInfo imgInfo = pngr.imgInfo;
+        final PngChunkPLTE plte = pngr.getMetadata().getPLTE();
+        final PngChunkTRNS trns = pngr.getMetadata().getTRNS();
+        final boolean indexed = imgInfo.indexed;
+        final boolean hasAlpha = indexed ? ( trns != null ) : imgInfo.alpha ;
+        
+        final int channels = indexed ? ( hasAlpha ? 4 : 3 ) : imgInfo.channels ;
         if ( ! ( 1 == channels || 3 == channels || 4 == channels ) ) {
-            throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 channels] images for now. Channels "+channels);
+            throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 channels] images for now. Channels "+channels + " Paletted: " + indexed);
         }
-        bytesPerPixel=pngr.imgInfo.bytesPixel;
+        
+        bytesPerPixel = indexed ? channels : imgInfo.bytesPixel ;
         if ( ! ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel ) ) {
             throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 bpp] images for now. BytesPerPixel "+bytesPerPixel);
         }
-        if(channels != bytesPerPixel) {
+        if( channels != bytesPerPixel ) {
             throw new RuntimeException("PNGImage currently only handles Channels [1/3/4] == BytePerPixel [1/3/4], channels: "+channels+", bytesPerPixel "+bytesPerPixel);
         }
-        pixelWidth=pngr.imgInfo.cols;
-        pixelHeight=pngr.imgInfo.rows;
+        pixelWidth = imgInfo.cols;
+        pixelHeight = imgInfo.rows;
         dpi = new double[2];
         {
             final double[] dpi2 = pngr.getMetadata().getDpi();
             dpi[0]=dpi2[0];
             dpi[1]=dpi2[1];
         }
-        switch(channels) {
-            case 1: glFormat = GL.GL_LUMINANCE; break;
-            case 3: glFormat = GL.GL_RGB; break;
-            case 4: glFormat = GL.GL_RGBA; break;
-            default: throw new InternalError("XXX: channels: "+channels+", bytesPerPixel "+bytesPerPixel);
+        if ( indexed ) {
+        	if ( hasAlpha ) {
+        		glFormat = GL.GL_RGBA;
+        	} else {
+        		glFormat = GL.GL_RGB;
+        	}
+        } else {
+        	switch( channels ) {
+                case 1: glFormat = GL.GL_LUMINANCE; break;
+                case 3: glFormat = GL.GL_RGB; break;
+                case 4: glFormat = GL.GL_RGBA; break;
+                default: throw new InternalError("XXX: channels: "+channels+", bytesPerPixel "+bytesPerPixel);
+            }
+        }
+        if(DEBUG) {
+            System.err.println("PNGImage: "+imgInfo);
+            System.err.println("PNGImage: indexed "+indexed+", alpha "+hasAlpha+", channels "+channels+", bytesPerPixel "+bytesPerPixel+
+                               ", pixels "+pixelWidth+"x"+pixelHeight+", dpi "+dpi[0]+"x"+dpi[1]+", glFormat 0x"+Integer.toHexString(glFormat));
         }
+        
         data = Buffers.newDirectByteBuffer(bytesPerPixel * pixelWidth * pixelHeight);
         reversedChannels = false; // RGB[A]
-        final boolean hasAlpha = 4 == channels;
+        isGLOriented = true;
         int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse store
+
+        int[] rgbaScanline = indexed ? new int[imgInfo.cols * channels] : null;
+        
         for (int row = 0; row < pixelHeight; row++) {
             final ImageLine l1 = pngr.readRow(row);
-            int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ;      // start w/ last pixel in line, reverse read
-            if(1 == channels) {
+            int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse read (PNG top-left -> OpenGL bottom-left origin)
+            if( indexed ) {
+                for (int j = pixelWidth - 1; j >= 0; j--) {
+                    rgbaScanline = ImageLineHelper.palette2rgb(l1, plte, trns, rgbaScanline); // reuse rgbaScanline and update if resized
+                    dataOff = getPixelRGBA8(data, dataOff, rgbaScanline, lineOff, hasAlpha);
+                    lineOff -= bytesPerPixel;
+                }
+            } else if( 1 == channels ) {
                 for (int j = pixelWidth - 1; j >= 0; j--) {
                     data.put(dataOff--, (byte)l1.scanline[lineOff--]); // Luminance, 1 bytesPerPixel
                 }
             } else {
                 for (int j = pixelWidth - 1; j >= 0; j--) {
-                    dataOff = getPixelRGBA8(data, dataOff, l1, lineOff, hasAlpha);
+            		dataOff = getPixelRGBA8(data, dataOff, l1.scanline, lineOff, hasAlpha);
                     lineOff -= bytesPerPixel;
                 }
             }
@@ -128,7 +211,8 @@ public class PNGImage {
         pngr.end();
     }
     private final int pixelWidth, pixelHeight, glFormat, bytesPerPixel;
-    private boolean reversedChannels;
+    private final boolean reversedChannels;
+    private final boolean isGLOriented;
     private final double[] dpi;
     private final ByteBuffer data;
     
@@ -141,10 +225,20 @@ public class PNGImage {
     /** Returns true if data has the channels reversed to BGR or BGRA, otherwise RGB or RGBA is expected. */
     public boolean getHasReversedChannels() { return reversedChannels; }
     
+    /**
+     * Returns <code>true</code> if the drawable is rendered in 
+     * OpenGL's coordinate system, <i>origin at bottom left</i>.
+     * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
+     * <p>
+     * Default impl. is <code>true</code>, i.e. OpenGL coordinate system.
+     * </p> 
+     */
+    public boolean isGLOriented() { return isGLOriented; }
+    
     /** Returns the dpi of the image. */
     public double[] getDpi() { return dpi; }
     
-    /** Returns the OpenGL format for this texture; e.g. GL.GL_BGR or GL.GL_BGRA. */
+    /** Returns the OpenGL format for this texture; e.g. GL.GL_LUMINANCE, GL.GL_RGB or GL.GL_RGBA. */
     public int getGLFormat() { return glFormat; }
     
     /** Returns the OpenGL data type: GL.GL_UNSIGNED_BYTE. */
@@ -170,20 +264,40 @@ public class PNGImage {
             // png.getMetadata().setText("my key", "my text");
             final boolean hasAlpha = 4 == bytesPerPixel;
             final ImageLine l1 = new ImageLine(imi);
-            int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse read
-            for (int row = 0; row < pixelHeight; row++) {
-                int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ;      // start w/ last pixel in line, reverse store
-                if(1 == bytesPerPixel) {
-                    for (int j = pixelWidth - 1; j >= 0; j--) {
-                        l1.scanline[lineOff--] = data.get(dataOff--); // // Luminance, 1 bytesPerPixel
-                    }
-                } else {
-                    for (int j = pixelWidth - 1; j >= 0; j--) {
-                        dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha, reversedChannels);
-                        lineOff -= bytesPerPixel;
+            if( isGLOriented ) {
+                // start at last pixel at end-of-buffer, reverse read (OpenGL bottom-left -> PNG top-left origin)
+                int dataOff = ( pixelWidth * bytesPerPixel * ( pixelHeight - 1 ) ) + // full lines - 1 line 
+                              ( ( pixelWidth - 1 ) * bytesPerPixel );                // one line - 1 pixel
+                for (int row = 0; row < pixelHeight; row++) {
+                    int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse store (OpenGL bottom-left -> PNG top-left origin)
+                    if(1 == bytesPerPixel) {
+                        for (int j = pixelWidth - 1; j >= 0; j--) {
+                            l1.scanline[lineOff--] = data.get(dataOff--); // // Luminance, 1 bytesPerPixel
+                        }
+                    } else {
+                        for (int j = pixelWidth - 1; j >= 0; j--) {
+                            dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha);
+                            lineOff -= bytesPerPixel;
+                        }
                     }
+                    png.writeRow(l1, row);
                 }
-                png.writeRow(l1, row);
+            } else {
+                int dataOff = 0; // start at first pixel at start-of-buffer, normal read (same origin: top-left)
+                for (int row = 0; row < pixelHeight; row++) {
+                    int lineOff = 0; // start w/ first pixel in line, normal store (same origin: top-left)
+                    if(1 == bytesPerPixel) {
+                        for (int j = pixelWidth - 1; j >= 0; j--) {
+                            l1.scanline[lineOff++] = data.get(dataOff++); // // Luminance, 1 bytesPerPixel
+                        }
+                    } else {
+                        for (int j = pixelWidth - 1; j >= 0; j--) {
+                            dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha);
+                            lineOff += bytesPerPixel;
+                        }
+                    }
+                    png.writeRow(l1, row);
+                }                
             }
             png.end();
         } finally {
diff --git a/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java b/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
index 83e9e22..a72403e 100644
--- a/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
+++ b/src/jogl/classes/javax/media/opengl/GLAnimatorControl.java
@@ -35,18 +35,18 @@ package javax.media.opengl;
 public interface GLAnimatorControl extends FPSCounter {
 
     /**
-     * Indicates whether this animator is running, ie. has been started and not stopped.
+     * Indicates whether this animator has been {@link #start() started}.
      *
      * @see #start()
      * @see #stop()
+     * @see #isPaused()
      * @see #pause()
      * @see #resume()
      */
     boolean isStarted();
 
     /**
-     * Indicates whether this animator is running and animating,<br>
-     * the latter is true if it has {@link GLAutoDrawable}s to render and is not paused.
+     * Indicates whether this animator {@link #isStarted() is started} and {@link #isPaused() is not paused}.
      *
      * @see #start()
      * @see #stop()
@@ -56,7 +56,9 @@ public interface GLAnimatorControl extends FPSCounter {
     boolean isAnimating();
 
     /**
-     * Indicates whether this animator is running and paused.
+     * Indicates whether this animator {@link #isStarted() is started} 
+     * and either {@link #pause() manually paused} or paused 
+     * automatically due to no {@link #add(GLAutoDrawable) added} {@link GLAutoDrawable}s.
      *
      * @see #start()
      * @see #stop()
@@ -75,30 +77,38 @@ public interface GLAnimatorControl extends FPSCounter {
 
     /**
      * Starts this animator, if not running.
-     * <P>
+     * <p>
      * In most situations this method blocks until
      * completion, except when called from the animation thread itself
      * or in some cases from an implementation-internal thread like the
      * AWT event queue thread.
-     * <P>
+     * </p>
+     * <p>
+     * Note that an animator w/o {@link #add(GLAutoDrawable) added drawables}
+     * will be paused automatically.
+     * </p>
+     * <p>
      * If started, all counters (time, frames, ..) are reset to zero.
+     * </p>
      *
      * @return true is started due to this call,
      *         otherwise false, ie started already or unable to start.
      *
      * @see #stop()
      * @see #isAnimating()
+     * @see #isPaused()
      * @see #getThread()
      */
     boolean start();
 
     /**
      * Stops this animator.
-     * <P>
+     * <p>
      * In most situations this method blocks until
      * completion, except when called from the animation thread itself
      * or in some cases from an implementation-internal thread like the
      * AWT event queue thread.
+     * </p>
      *
      * @return true is stopped due to this call,
      *         otherwise false, ie not started or unable to stop.
@@ -111,13 +121,14 @@ public interface GLAnimatorControl extends FPSCounter {
 
     /**
      * Pauses this animator.
-     * <P>
+     * <p>
      * In most situations this method blocks until
      * completion, except when called from the animation thread itself
      * or in some cases from an implementation-internal thread like the
      * AWT event queue thread.
+     * </p>
      *
-     * @return  false if if not started or already paused, otherwise true
+     * @return  false if not started, already paused or failed to pause, otherwise true
      *
      * @see #resume()
      * @see #isAnimating()
@@ -126,15 +137,17 @@ public interface GLAnimatorControl extends FPSCounter {
 
     /**
      * Resumes animation if paused.
-     * <P>
+     * <p>
      * In most situations this method blocks until
      * completion, except when called from the animation thread itself
      * or in some cases from an implementation-internal thread like the
      * AWT event queue thread.
-     * <P>
+     * </p>
+     * <p>
      * If resumed, all counters (time, frames, ..) are reset to zero.
+     * </p>
      *
-     * @return false if if not started or not paused, otherwise true
+     * @return false if not started, not paused or unable to resume, otherwise true
      *
      * @see #pause()
      * @see #isAnimating()
@@ -142,13 +155,30 @@ public interface GLAnimatorControl extends FPSCounter {
     boolean resume();
 
     /**
-     * Removes a drawable from the animator's list of rendering drawables.<br>
+     * Adds a drawable to this animator's list of rendering drawables.
+     * <p>
+     * This allows the animator thread to become {@link #isAnimating() animating}, 
+     * in case the first drawable is added and the animator {@link #isStarted() is started}.
+     * </p>
+     * 
+     * @param drawable the drawable to be added
+     * @throws IllegalArgumentException if drawable was already added to this animator
+     */
+    void add(GLAutoDrawable drawable);
+    
+    /**
+     * Removes a drawable from the animator's list of rendering drawables.
+     * <p>
      * This method should get called in case a drawable becomes invalid,
-     * and will not be recovered.<br>
-     * This allows the animator thread to become idle in case the last drawable
-     * has reached it's end of life.<br>
+     * and will not be recovered.
+     * </p>
+     * <p>
+     * This allows the animator thread to become {@link #isAnimating() not animating}, 
+     * in case the last drawable has been removed.
+     * </p>
      * 
-     * @param drawable the to be removed drawable
+     * @param drawable the drawable to be removed
+     * @throws IllegalArgumentException if drawable was not added to this animator
      */
     void remove(GLAutoDrawable drawable);
 }
diff --git a/src/jogl/classes/javax/media/opengl/GLArrayData.java b/src/jogl/classes/javax/media/opengl/GLArrayData.java
index 5d17f68..8e13830 100644
--- a/src/jogl/classes/javax/media/opengl/GLArrayData.java
+++ b/src/jogl/classes/javax/media/opengl/GLArrayData.java
@@ -30,6 +30,8 @@ package javax.media.opengl;
 
 import java.nio.Buffer;
 
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+
 /**
  *
  * The total number of bytes hold by the referenced buffer is:
@@ -38,6 +40,19 @@ import java.nio.Buffer;
  */
 public interface GLArrayData {
     /**
+     * Implementation and type dependent object association.
+     * <p>
+     * One currently known use case is to associate a {@link com.jogamp.opengl.util.glsl.ShaderState ShaderState}
+     * to an GLSL aware vertex attribute object, allowing to use the ShaderState to handle it's 
+     * data persistence, location and state change.<br/>
+     * This is implicitly done via {@link com.jogamp.opengl.util.glsl.ShaderState#ownAttribute(GLArrayData, boolean) shaderState.ownAttribute(GLArrayData, boolean)}.
+     * </p>
+     * @param obj implementation and type dependent association
+     * @param enable pass true to enable the association and false to disable it.
+     */
+    public void associate(Object obj, boolean enable);
+    
+    /**
      * Returns true if this data set is intended for a GLSL vertex shader attribute,
      * otherwise false, ie intended for fixed function vertex pointer
      */
@@ -47,10 +62,10 @@ public interface GLArrayData {
      * The index of the predefined array index, see list below,
      * or -1 in case of a shader attribute array.
      *
-     * @see javax.media.opengl.GL2#GL_VERTEX_ARRAY
-     * @see javax.media.opengl.GL2#GL_NORMAL_ARRAY
-     * @see javax.media.opengl.GL2#GL_COLOR_ARRAY
-     * @see javax.media.opengl.GL2#GL_TEXTURE_COORD_ARRAY
+     * @see GLPointerFunc#GL_VERTEX_ARRAY
+     * @see GLPointerFunc#GL_NORMAL_ARRAY
+     * @see GLPointerFunc#GL_COLOR_ARRAY
+     * @see GLPointerFunc#GL_TEXTURE_COORD_ARRAY
      */
     public int getIndex();
 
@@ -61,6 +76,11 @@ public interface GLArrayData {
 
     /**
      * Set a new name for this array.
+     * <p>
+     * This clears the location, i.e. sets it to -1.
+     * </p>
+     * @see #setLocation(int)
+     * @see #setLocation(GL2ES2, int)
      */
     public void setName(String newName);
 
@@ -72,14 +92,37 @@ public interface GLArrayData {
     public int getLocation();
 
     /**
-     * Sets the determined location of the shader attribute
-     * This is usually done within ShaderState.
+     * Sets the given location of the shader attribute
      *
+     * @return the given location
      * @see com.jogamp.opengl.util.glsl.ShaderState#vertexAttribPointer(GL2ES2, GLArrayData)
      */
-    public void setLocation(int v);
+    public int setLocation(int v);
 
     /**
+     * Retrieves the location of the shader attribute from the linked shader program.
+     * <p>
+     * No validation is performed within the implementation.
+     * </p>
+     * @param gl
+     * @param program
+     * @return ≥0 denotes a valid attribute location as found and used in the given shader program.
+     *         <0 denotes an invalid location, i.e. not found or used in the given shader program.
+     */
+    public int setLocation(GL2ES2 gl, int program);
+    
+    /**
+     * Binds the location of the shader attribute to the given location for the unlinked shader program.
+     * <p>
+     * No validation is performed within the implementation.
+     * </p>
+     * @param gl
+     * @param program
+     * @return the given location
+     */
+    public int setLocation(GL2ES2 gl, int program, int location);
+    
+    /**
      * Determines whether the data is server side (VBO) and enabled,
      * or a client side array (false).
      */
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
index 38f1746..bdbbd96 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
@@ -40,6 +40,8 @@
 
 package javax.media.opengl;
 
+import java.util.List;
+
 import jogamp.opengl.Debug;
 
 /** A higher-level abstraction than {@link GLDrawable} which supplies
@@ -128,51 +130,53 @@ public interface GLAutoDrawable extends GLDrawable {
   public GLContext getContext();
 
   /**
-   * Associate a new context to this drawable and also propagates the context/drawable switch by 
-   * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
-   * <code>drawable</code> might be an inner GLDrawable instance if using a delegation pattern,
-   * or this GLAutoDrawable instance.
+   * Associate the new context, <code>newtCtx</code>, to this auto-drawable.
    * <p>
-   * If the old or new context was current on this thread, it is being released before switching the drawable.
-   * The new context will be made current afterwards, if it was current before. 
-   * However the user shall take extra care that no other thread
-   * attempts to make this context current.
+   * The current context will be destroyed if <code>destroyPrevCtx</code> is <code>true</code>,
+   * otherwise it will be dis-associated from this auto-drawable 
+   * via {@link GLContext#setGLDrawable(GLDrawable, boolean) setGLDrawable(null, true);} first.
    * </p>
    * <p>
-   * Be aware that the old context is still bound to the drawable, 
-   * and that one context can only be bound to one drawable at one time!
-   * </p>
+   * The new context will be associated with this auto-drawable 
+   * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
+   * </p> 
    * <p>
-   * In case you do not intend to use the old context anymore, i.e. 
-   * not assigning it to another drawable, it shall be 
-   * destroyed before setting the new context, i.e.:
-   * <pre>
-            GLContext oldCtx = glad.getContext();
-            if(null != oldCtx) {
-                oldCtx.destroy();
-            }
-            glad.setContext(newCtx);            
-   * </pre> 
-   * This is required, since a context must have a valid drawable at all times
-   * and this API shall not restrict the user in any way. 
+   * If the old or new context was current on this thread, it is being released before switching the association.
+   * The new context will be made current afterwards, if it was current before. 
+   * However the user shall take extra care that no other thread
+   * attempts to make this context current.
    * </p>
    * 
-   * @param newCtx the new context
-   * @return the replaced GLContext, maybe <code>null</code>
+   * @param newCtx the new context, maybe <code>null</code> for dis-association.
+   * @param destroyPrevCtx if <code>true</code>, destroy the previous context if exists  
+   * @return the previous GLContext, maybe <code>null</code>
    *  
    * @see GLContext#setGLDrawable(GLDrawable, boolean)
    * @see GLContext#setGLReadDrawable(GLDrawable)
-   * @see jogamp.opengl.GLDrawableHelper#switchContext(GLDrawable, GLContext, GLContext, int)
+   * @see jogamp.opengl.GLDrawableHelper#switchContext(GLDrawable, GLContext, boolean, GLContext, int)
    */
-  public GLContext setContext(GLContext newCtx);
+  public GLContext setContext(GLContext newCtx, boolean destroyPrevCtx);
   
-  /** Adds a {@link GLEventListener} to the end of this drawable queue.
-      The listeners are notified of events in the order of the queue. */
+  /**
+   * Adds the given {@link GLEventListener listener} to the end of this drawable queue.
+   * The {@link GLEventListener listeners} are notified of events in the order of the queue.
+   * <p>
+   * The newly added listener's {@link GLEventListener#init(GLAutoDrawable) init(..)} 
+   * method will be called once before any other of it's callback methods.
+   * See {@link #getGLEventListenerInitState(GLEventListener)} for details.
+   * </p> 
+   * @param listener The GLEventListener object to be inserted
+   */
   public void addGLEventListener(GLEventListener listener);
 
   /**
-   * Adds a {@link GLEventListener} at the given index of this drawable queue.
-   * The listeners are notified of events in the order of the queue.
+   * Adds the given {@link GLEventListener listener} at the given index of this drawable queue.
+   * The {@link GLEventListener listeners} are notified of events in the order of the queue.
+   * <p>
+   * The newly added listener's {@link GLEventListener#init(GLAutoDrawable) init(..)} 
+   * method will be called once before any other of it's callback methods.
+   * See {@link #getGLEventListenerInitState(GLEventListener)} for details.
+   * </p> 
    * @param index Position where the listener will be inserted.
    *              Should be within (0 <= index && index <= size()).
    *              An index value of -1 is interpreted as the end of the list, size().
@@ -181,38 +185,128 @@ public interface GLAutoDrawable extends GLDrawable {
    */
   public void addGLEventListener(int index, GLEventListener listener) throws IndexOutOfBoundsException;
 
-  /** 
-   * Removes a {@link GLEventListener} from this drawable. 
-   * Note that if this is done from within a particular drawable's 
-   * {@link GLEventListener} handler (reshape, display, etc.) that it is not
+  /**
+   * Returns the number of {@link GLEventListener} of this drawable queue.
+   * @return The number of GLEventListener objects of this drawable queue.
+   */
+  public int getGLEventListenerCount();
+  
+  /**
+   * Returns the {@link GLEventListener} at the given index of this drawable queue.
+   * @param index Position of the listener to be returned.
+   *              Should be within (0 <= index && index < size()).
+   *              An index value of -1 is interpreted as last listener, size()-1.
+   * @return The GLEventListener object at the given index.
+   * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index < size()), or -1
+   */
+  public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException;
+  
+  /**
+   * Retrieves whether the given {@link GLEventListener listener} is initialized or not.
+   * <p>
+   * After {@link #addGLEventListener(GLEventListener) adding} a {@link GLEventListener} it is 
+   * marked <i>uninitialized</i> and added to a list of to be initialized {@link GLEventListener}.
+   * If such <i>uninitialized</i> {@link GLEventListener}'s handler methods (reshape, display) 
+   * are about to be invoked, it's {@link GLEventListener#init(GLAutoDrawable) init(..)} method is invoked first.
+   * Afterwards the {@link GLEventListener} is marked <i>initialized</i>
+   * and removed from the list of to be initialized {@link GLEventListener}.
+   * </p>
+   * <p> 
+   * This methods returns the {@link GLEventListener} initialized state,
+   * i.e. returns <code>false</code> if it is included in the list of to be initialized {@link GLEventListener},
+   * otherwise <code>true</code>.
+   * </p>
+   * @param listener the GLEventListener object to query it's initialized state.
+   */
+  public boolean getGLEventListenerInitState(GLEventListener listener);
+  
+  /**
+   * Sets the given {@link GLEventListener listener's} initialized state.
+   * <p> 
+   * This methods allows manually setting the {@link GLEventListener} initialized state,
+   * i.e. adding it to, or removing it from the list of to be initialized {@link GLEventListener}.
+   * See {@link #getGLEventListenerInitState(GLEventListener)} for details.
+   * </p>
+   * <p>
+   * <b>Warning:</b> This method does not validate whether the given {@link GLEventListener listener's}
+   * is member of this drawable queue, i.e. {@link #addGLEventListener(GLEventListener) added}. 
+   * </p>
+   * <p>
+   * This method is only exposed to allow users full control over the {@link GLEventListener}'s state
+   * and is usually not recommended to change.
+   * </p>
+   * <p>
+   * One use case is moving a {@link GLContext} and their initialized {@link GLEventListener}
+   * from one {@link GLAutoDrawable} to another, 
+   * where a subsequent {@link GLEventListener#init(GLAutoDrawable) init(..)} call after adding it
+   * to the new owner is neither required nor desired. 
+   * See {@link com.jogamp.opengl.util.GLDrawableUtil#swapGLContextAndAllGLEventListener(GLAutoDrawable, GLAutoDrawable) swapGLContextAndAllGLEventListener(..)}.
+   * </p>
+   * @param listener the GLEventListener object to perform a state change.
+   * @param initialized if <code>true</code>, mark the listener initialized, otherwise uninitialized. 
+   */
+  public void setGLEventListenerInitState(GLEventListener listener, boolean initialized);
+  
+  /**
+   * Disposes the given {@link GLEventListener listener} via {@link GLEventListener#dispose(GLAutoDrawable) dispose(..)}
+   * if it has been initialized and added to this queue.
+   * <p>
+   * If <code>remove</code> is <code>true</code>, the {@link GLEventListener} is removed from this drawable queue before disposal,
+   * otherwise marked uninitialized.
+   * </p>
+   * <p>
+   * If an {@link GLAnimatorControl} is being attached and the current thread is different 
+   * than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+   * </p>
+   * <p>
+   * Note that this is an expensive operation, since {@link GLEventListener#dispose(GLAutoDrawable) dispose(..)}
+   * is decorated by {@link GLContext#makeCurrent()} and {@link GLContext#release()}.
+   * </p>
+   * <p>
+   * Use {@link #removeGLEventListener(GLEventListener) removeGLEventListener(listener)} instead
+   * if you just want to remove the {@link GLEventListener listener} and <i>don't care</i> about the disposal of the it's (OpenGL) resources.
+   * </p>
+   * <p> 
+   * Also note that this is done from within a particular drawable's 
+   * {@link GLEventListener} handler (reshape, display, etc.), that it is not
    * guaranteed that all other listeners will be evaluated properly
    * during this update cycle.
-   * @param listener The GLEventListener object to be removed
+   * </p>
+   * @param listener The GLEventListener object to be disposed and removed if <code>remove</code> is <code>true</code>
+   * @param remove pass <code>true</code> to have the <code>listener</code> removed from this drawable queue, otherwise pass <code>false</code>
+   * @return the disposed and/or removed GLEventListener, or null if no action was performed, i.e. listener was not added
    */  
-  public void removeGLEventListener(GLEventListener listener);
-
+  public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove);
+  
   /** 
-   * Removes a {@link GLEventListener} at the given index from this drawable. 
+   * Removes the given {@link GLEventListener listener} from this drawable queue.
+   * <p>
+   * This is an inexpensive operation, since the removed listener's 
+   * {@link GLEventListener#dispose(GLAutoDrawable) dispose(..)} method will <i>not</i> be called.
+   * </p>
+   * <p>
+   * Use {@link #disposeGLEventListener(GLEventListener, boolean) disposeGLEventListener(listener, true)} 
+   * instead to ensure disposal of the {@link GLEventListener listener}'s (OpenGL) resources.
+   * </p> 
+   * <p> 
    * Note that if this is done from within a particular drawable's 
-   * {@link GLEventListener} handler (reshape, display, etc.) that it is not
+   * {@link GLEventListener} handler (reshape, display, etc.), that it is not
    * guaranteed that all other listeners will be evaluated properly
    * during this update cycle.
-   * @param index Position of the listener to be removed.
-   *              Should be within (0 <= index && index < size()).
-   *              An index value of -1 is interpreted as last listener, size()-1.
-   * @return The removed GLEventListener object
-   * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index < size()), or -1
+   * </p>
+   * @param listener The GLEventListener object to be removed
+   * @return the removed GLEventListener, or null if listener was not added
    */  
-  public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException;
-
+  public GLEventListener removeGLEventListener(GLEventListener listener);
+  
   /**
-   * <p>
    * Registers the usage of an animator, an {@link javax.media.opengl.GLAnimatorControl} implementation.
-   * The animator will be queried whether it's animating, ie periodically issuing {@link #display()} calls or not.</p><br>
+   * The animator will be queried whether it's animating, ie periodically issuing {@link #display()} calls or not.
    * <p>
    * This method shall be called by an animator implementation only,<br>
    * e.g. {@link com.jogamp.opengl.util.Animator#add(javax.media.opengl.GLAutoDrawable)}, passing it's control implementation,<br>
-   * and {@link com.jogamp.opengl.util.Animator#remove(javax.media.opengl.GLAutoDrawable)}, passing <code>null</code>.</p><br>
+   * and {@link com.jogamp.opengl.util.Animator#remove(javax.media.opengl.GLAutoDrawable)}, passing <code>null</code>.
+   * </p>
    * <p>
    * Impacts {@link #display()} and {@link #invoke(boolean, GLRunnable)} semantics.</p><br>
    *
@@ -236,25 +330,64 @@ public interface GLAutoDrawable extends GLDrawable {
   public GLAnimatorControl getAnimator();
 
   /**
+   * Dedicates this instance's {@link GLContext} to the given thread.<br/>
+   * The thread will exclusively claim the {@link GLContext} via {@link #display()} and not release it
+   * until {@link #destroy()} or <code>setExclusiveContextThread(null)</code> has been called. 
    * <p>
+   * Default non-exclusive behavior is <i>requested</i> via <code>setExclusiveContextThread(null)</code>,
+   * which will cause the next call of {@link #display()} on the exclusive thread to 
+   * release the {@link GLContext}. Only after it's async release, {@link #getExclusiveContextThread()} 
+   * will return <code>null</code>.
+   * </p>
+   * <p>
+   * To release a previous made exclusive thread, a user issues <code>setExclusiveContextThread(null)</code>
+   * and may poll {@link #getExclusiveContextThread()} until it returns <code>null</code>, 
+   * <i>while</i> the exclusive thread is still running.  
+   * </p>
+   * <p>
+   * Note: Setting a new exclusive thread without properly releasing a previous one
+   * will throw an GLException.
+   * </p>
+   * <p>
+   * Note: Utilizing this feature w/ AWT could lead to an AWT-EDT deadlock, depending on the AWT implementation.
+   * Hence it is advised not to use it with native AWT GLAutoDrawable like GLCanvas.
+   * </p>
+   * <p>
+   * One scenario could be to dedicate the context to the {@link GLAnimatorControl#getThread() animator thread}
+   * and spare redundant context switches, see {@link com.jogamp.opengl.util.AnimatorBase#setExclusiveContext(boolean)}.
+   * </p>
+   * @param t the exclusive thread to claim the context, or <code>null</code> for default operation.
+   * @return previous exclusive context thread 
+   * @throws GLException If an exclusive thread is still active but a new one is attempted to be set
+   * @see com.jogamp.opengl.util.AnimatorBase#setExclusiveContext(boolean)
+   */
+  public Thread setExclusiveContextThread(Thread t) throws GLException;
+  
+  /**
+   * @see #setExclusiveContextThread(Thread) 
+   */
+  public Thread getExclusiveContextThread();
+  
+  /**
    * Enqueues a one-shot {@link GLRunnable},
    * which will be executed within the next {@link #display()} call
    * after all registered {@link GLEventListener}s
    * {@link GLEventListener#display(GLAutoDrawable) display(GLAutoDrawable)}
-   * methods has been called.
-   * </p>
+   * methods have been called.
    * <p>
    * If no {@link GLAnimatorControl} is animating (default),<br>
    * or if the current thread is the animator thread,<br>
-   * a {@link #display()} call is issued after enqueue the <code>GLRunnable</code>.<br>
-   * No extra synchronization is performed in case <code>wait</code> is true, since it is executed in the current thread.</p>
+   * a {@link #display()} call is issued after enqueue the <code>GLRunnable</code>,
+   * hence the {@link GLRunnable} will be executed right away.<br/>
+   * </p>
    * <p>
-   * If an {@link GLAnimatorControl} is animating,<br>
-   * no {@link #display()} call is issued, since the animator thread performs it.<br>
+   * If an {@link GLAnimatorControl animator} is running,<br>
+   * no explicit {@link #display()} call is issued, allowing the {@link GLAnimatorControl animator} to perform at due time.<br>
    * </p>
    * <p>
    * If <code>wait</code> is <code>true</code> the call blocks until the <code>glRunnable</code>
-   * has been executed.<p>
+   * has been executed by the {@link GLAnimatorControl animator}, otherwise the method returns immediately.
+   * </p>
    * <p>
    * If <code>wait</code> is <code>true</code> <b>and</b> 
    * {@link #isRealized()} returns <code>false</code> <i>or</i> {@link #getContext()} returns <code>null</code>,
@@ -266,15 +399,25 @@ public interface GLAutoDrawable extends GLDrawable {
    * where all blocked callers are being notified.
    * </p>
    *
-   * @param wait if <code>true</code> block until execution of <code>glRunnable</code> is finished, otherwise return immediatly w/o waiting
+   * @param wait if <code>true</code> block until execution of <code>glRunnable</code> is finished, otherwise return immediately w/o waiting
    * @param glRunnable the {@link GLRunnable} to execute within {@link #display()}
    * @return <code>true</code> if the {@link GLRunnable} has been processed or queued, otherwise <code>false</code>.
    * 
    * @see #setAnimator(GLAnimatorControl)
    * @see #display()
    * @see GLRunnable
+   * @see #enqueue(GLRunnable)
    */
   public boolean invoke(boolean wait, GLRunnable glRunnable);
+  
+  /**
+   * Extends {@link #invoke(boolean, GLRunnable)} functionality 
+   * allowing to inject a list of {@link GLRunnable}s.
+   * @param wait if <code>true</code> block until execution of the last <code>glRunnable</code> is finished, otherwise return immediately w/o waiting
+   * @param glRunnables the {@link GLRunnable}s to execute within {@link #display()}
+   * @return <code>true</code> if the {@link GLRunnable}s has been processed or queued, otherwise <code>false</code>.
+   */
+  public boolean invoke(boolean wait, List<GLRunnable> glRunnables);
 
   /** Destroys all resources associated with this GLAutoDrawable,
       inclusive the GLContext.
@@ -348,7 +491,7 @@ public interface GLAutoDrawable extends GLDrawable {
    * <p>
    * This GLAutoDrawable implementation holds it's own GLContext reference,
    * thus created a GLContext using this methods won't replace it implicitly.
-   * To replace or set this GLAutoDrawable's GLContext you need to call {@link #setContext(GLContext)}. 
+   * To replace or set this GLAutoDrawable's GLContext you need to call {@link #setContext(GLContext, boolean)}. 
    * </p>
    * <p>
    * The GLAutoDrawable implementation shall also set the 
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index 9bcee81..74c1b96 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -432,6 +432,19 @@ public interface GLBase {
     * </p> 
     */
    public int getDefaultReadFramebuffer();
-
+   
+   /** 
+    * Returns the default color buffer within the current bound 
+    * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER,
+    * which will be used as the source for pixel reading commands, 
+    * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc.
+    * <p>
+    * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
+    * otherwise this is {@link GL#GL_FRONT} for single buffer configurations 
+    * and {@link GL#GL_BACK} for double buffer configurations.
+    * </p> 
+    */
+   public int getDefaultReadBuffer();
+   
 }
 
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java
index 9b004a0..5b3eb91 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilities.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java
@@ -75,11 +75,6 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
   private boolean sampleBuffers = false;
   private int     numSamples    = 2;
 
-  // Bits for pbuffer creation
-  private boolean pbufferFloatingPointBuffers;
-  private boolean pbufferRenderToTexture;
-  private boolean pbufferRenderToTextureRectangle;
-
   /** Creates a GLCapabilities object. All attributes are in a default state.
     * @param glp GLProfile, or null for the default GLProfile
     * @throws GLException if no profile is given and no default profile is available for the default device.
@@ -122,9 +117,6 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
     accumBlueBits = source.getAccumBlueBits();
     accumAlphaBits = source.getAccumAlphaBits();
     sampleBuffers = source.getSampleBuffers();
-    pbufferFloatingPointBuffers = source.getPbufferFloatingPointBuffers();
-    pbufferRenderToTexture = source.getPbufferRenderToTexture();
-    pbufferRenderToTextureRectangle = source.getPbufferRenderToTextureRectangle();
     numSamples = source.getNumSamples();
     sampleExtension = source.getSampleExtension();
     return this;
@@ -148,9 +140,6 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
     hash = ((hash << 5) - hash) + this.accumGreenBits;
     hash = ((hash << 5) - hash) + this.accumBlueBits;
     hash = ((hash << 5) - hash) + this.accumAlphaBits;
-    hash = ((hash << 5) - hash) + ( this.pbufferFloatingPointBuffers ? 1 : 0 );
-    hash = ((hash << 5) - hash) + ( this.pbufferRenderToTexture ? 1 : 0 );
-    hash = ((hash << 5) - hash) + ( this.pbufferRenderToTextureRectangle ? 1 : 0 );
     return hash;
   }
 
@@ -174,10 +163,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
                   other.getAccumGreenBits()==accumGreenBits &&
                   other.getAccumBlueBits()==accumBlueBits &&
                   other.getAccumAlphaBits()==accumAlphaBits &&
-                  other.getSampleBuffers()==sampleBuffers &&
-                  other.getPbufferFloatingPointBuffers()==pbufferFloatingPointBuffers &&
-                  other.getPbufferRenderToTexture()==pbufferRenderToTexture &&
-                  other.getPbufferRenderToTextureRectangle()==pbufferRenderToTextureRectangle;
+                  other.getSampleBuffers()==sampleBuffers;
     if(res && sampleBuffers) {
         res = other.getNumSamples()==getNumSamples() &&
               other.getSampleExtension().equals(sampleExtension) ;
@@ -449,40 +435,6 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
     return sampleBuffers ? numSamples : 0;
   }
 
-  /** For pbuffers only, indicates whether floating-point buffers
-      should be used if available. Defaults to false. */
-  public void setPbufferFloatingPointBuffers(boolean enable) {
-    pbufferFloatingPointBuffers = enable;
-  }
-
-  @Override
-  public final boolean getPbufferFloatingPointBuffers() {
-    return pbufferFloatingPointBuffers;
-  }
-
-  /** For pbuffers only, indicates whether the render-to-texture
-      extension should be used if available.  Defaults to false. */
-  public void setPbufferRenderToTexture(boolean enable) {
-    pbufferRenderToTexture = enable;
-  }
-
-  @Override
-  public final boolean getPbufferRenderToTexture() {
-    return pbufferRenderToTexture;
-  }
-
-  /** For pbuffers only, indicates whether the
-      render-to-texture-rectangle extension should be used if
-      available. Defaults to false. */
-  public void setPbufferRenderToTextureRectangle(boolean enable) {
-    pbufferRenderToTextureRectangle = enable;
-  }
-
-  @Override
-  public final boolean getPbufferRenderToTextureRectangle() {
-    return pbufferRenderToTextureRectangle;
-  }
-
   @Override
   public StringBuilder toString(StringBuilder sink) {
     if(null == sink) {
@@ -493,8 +445,8 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
 
     super.toString(sink, false);
 
-    sink.append(", accum-rgba ").append(accumRedBits).append("/").append(accumGreenBits).append("/").append(accumBlueBits).append("/").append(accumAlphaBits);
-    sink.append(", dp/st/ms: ").append(depthBits).append("/").append(stencilBits).append("/").append(samples);
+    sink.append(", accum-rgba ").append(accumRedBits).append(ESEP).append(accumGreenBits).append(ESEP).append(accumBlueBits).append(ESEP).append(accumAlphaBits);
+    sink.append(", dp/st/ms ").append(depthBits).append(ESEP).append(stencilBits).append(ESEP).append(samples);
     if(samples>0) {
         sink.append(", sample-ext ").append(sampleExtension);
     }
@@ -525,15 +477,12 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
         ns = true;
     }
     if(isPBuffer()) {
-        if(ns) { sink.append(", "); }
-        sink.append("pbuffer [r2t ").append(pbufferRenderToTexture?1:0)
-            .append(", r2tr ").append(pbufferRenderToTextureRectangle?1:0)
-            .append(", float ").append(pbufferFloatingPointBuffers?1:0)
-            .append("]");                
+        if(ns) { sink.append(CSEP); }
+        sink.append("pbuffer");
         ns = true;
     }
     if(isBitmap()) {
-        if(ns) { sink.append(", "); }
+        if(ns) { sink.append(CSEP); }
         sink.append("bitmap");
         ns = true;
     }
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
index ee261ca..6af3502 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
@@ -130,33 +130,6 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable {
     int getNumSamples();
 
     /**
-     * For pbuffers only, returns whether floating-point buffers should
-     * be used if available. 
-     * <p>
-     * Default is false.
-     * </p>
-     */
-    boolean getPbufferFloatingPointBuffers();
-
-    /**
-     * For pbuffers only, returns whether the render-to-texture
-     * extension should be used if available.  
-     * <p>
-     * Default is false.
-     * </p>
-     */
-    boolean getPbufferRenderToTexture();
-
-    /**
-     * For pbuffers only, returns whether the render-to-texture
-     * extension should be used. 
-     * <p>
-     * Default is false.
-     * </p>
-     */
-    boolean getPbufferRenderToTextureRectangle();
-
-    /**
      * Returns the number of stencil buffer bits.
      * <p>
      * Default is 0.
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index de10a28..cc37da0 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -42,7 +42,7 @@ package javax.media.opengl;
 
 import java.nio.IntBuffer;
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.Set;
 
@@ -53,6 +53,7 @@ import jogamp.opengl.GLContextImpl;
 
 import com.jogamp.common.os.Platform;
 import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.VersionNumberString;
 import com.jogamp.common.util.locks.LockFactory;
 import com.jogamp.common.util.locks.RecursiveLock;
 import com.jogamp.opengl.GLExtensions;
@@ -103,6 +104,7 @@ public abstract class GLContext {
   
   public static final boolean DEBUG = Debug.debug("GLContext");
   public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
+  public static final boolean DEBUG_TRACE_SWITCH = DEBUG || TRACE_SWITCH;  
 
   /** Reflects property jogl.debug.DebugGL. If true, the debug pipeline is enabled at context creation. */
   public static final boolean DEBUG_GL = Debug.isPropertyDefined("jogl.debug.DebugGL", true);
@@ -116,6 +118,30 @@ public abstract class GLContext {
   /** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}. */
   public static final int CONTEXT_CURRENT_NEW = 2;
 
+  /* Version 1.00, i.e. GLSL 1.00 for ES 2.0. */
+  public static final VersionNumber Version100 = new VersionNumber(1,  0, 0);
+  /* Version 1.10, i.e. GLSL 1.10 for GL 2.0. */
+  public static final VersionNumber Version110 = new VersionNumber(1, 10, 0);
+  /* Version 1.20, i.e. GLSL 1.20 for GL 2.1. */
+  public static final VersionNumber Version120 = new VersionNumber(1, 20, 0);
+  /* Version 1.30, i.e. GLSL 1.30 for GL 3.0. */
+  public static final VersionNumber Version130 = new VersionNumber(1, 30, 0);
+  /* Version 1.40, i.e. GLSL 1.40 for GL 3.1. */
+  public static final VersionNumber Version140 = new VersionNumber(1, 40, 0);
+  /* Version 1.50, i.e. GLSL 1.50 for GL 3.2. */
+  public static final VersionNumber Version150 = new VersionNumber(1, 50, 0);
+  
+  /** Version 3.2. As an OpenGL version, it qualifies for geometry shader */
+  public static final VersionNumber Version32 = new VersionNumber(3, 2, 0);
+  
+  /** Version 3.1. As an OpenGL version, it qualifies for {@link #isGL3core()}, {@link #isGL3bc()} and {@link #isGL3()} */
+  public static final VersionNumber Version31 = new VersionNumber(3, 1, 0);
+  
+  /** Version 3.0. As an OpenGL version, it qualifies for {@link #isGL2()} only */
+  public static final VersionNumber Version30 = new VersionNumber(3, 0, 0);
+  
+  protected static final VersionNumber Version80 = new VersionNumber(8, 0, 0);
+
   /** <code>ARB_create_context</code> related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
   protected static final int CTX_IS_ARB_CREATED  = 1 <<  0;
   /** <code>ARB_create_context</code> related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
@@ -156,10 +182,10 @@ public abstract class GLContext {
       resetStates();
   }
 
-  protected int ctxMajorVersion;
-  protected int ctxMinorVersion;
+  protected VersionNumber ctxVersion;
   protected int ctxOptions;
   protected String ctxVersionString;
+  protected VersionNumberString ctxVendorVersion;
   protected VersionNumber ctxGLSLVersion;
   private int currentSwapInterval;
   protected GLRendererQuirks glRendererQuirks;
@@ -172,11 +198,11 @@ public abstract class GLContext {
         System.err.println(getThreadName() + ": GLContext.resetStates()");
         // Thread.dumpStack();
       }
-      ctxMajorVersion=-1;
-      ctxMinorVersion=-1;
+      ctxVersion = VersionNumberString.zeroVersion;
+      ctxVendorVersion = VersionNumberString.zeroVersion;
       ctxOptions=0;
       ctxVersionString=null;
-      ctxGLSLVersion=null;
+      ctxGLSLVersion = VersionNumber.zeroVersion;
       attachedObjects.clear();
       contextHandle=0;
       currentSwapInterval = -1;
@@ -209,15 +235,20 @@ public abstract class GLContext {
   /**
    * Sets the read/write drawable for framebuffer operations.
    * <p>
+   * If the arguments reflect the current state of this context
+   * this method is a no-operation and returns the old and current {@link GLDrawable}.
+   * </p>
+   * <p>
    * If the context was current on this thread, it is being released before switching the drawable
    * and made current afterwards. However the user shall take extra care that not other thread
    * attempts to make this context current. Otherwise a race condition may happen.
    * </p>
-   * @param readWrite the read/write drawable for framebuffer operations.
-   * @param setWriteOnly if <code>true</code> and if the current read-drawable differs 
-   *        from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}), 
-   *        only change the write-drawable. Otherwise set both drawables.
-   * @return the replaced read/write drawable
+   * @param readWrite The read/write drawable for framebuffer operations, maybe <code>null</code> to remove association.
+   * @param setWriteOnly Only change the write-drawable, if <code>setWriteOnly</code> is <code>true</code> and 
+   *                     if the {@link #getGLReadDrawable() read-drawable} differs 
+   *                     from the {@link #getGLDrawable() write-drawable}. 
+   *                     Otherwise set both drawables, read and write.
+   * @return The previous read/write drawable
    *
    * @throws GLException in case <code>null</code> is being passed or 
    *                     this context is made current on another thread.
@@ -231,6 +262,12 @@ public abstract class GLContext {
   
   /**
    * Returns the write-drawable this context uses for framebuffer operations.
+   * <p>
+   * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)},
+   * it equals to the write-drawable (default).
+   * </p> 
+   * @see #setGLDrawable(GLDrawable, boolean)
+   * @see #setGLReadDrawable(GLDrawable)
    */
   public abstract GLDrawable getGLDrawable();
 
@@ -251,7 +288,7 @@ public abstract class GLContext {
    *
    * @param read the read-drawable for read framebuffer operations.
    *             If null is passed, the default write drawable will be set.
-   * @return the replaced read-drawable
+   * @return the previous read-drawable
    *
    * @throws GLException in case a read drawable is not supported or
    *                     this context is made current on another thread.
@@ -276,6 +313,9 @@ public abstract class GLContext {
   /**
    * Makes this GLContext current on the calling thread.
    * <p>
+   * Recursive call to {@link #makeCurrent()} and hence {@link #release()} are supported.
+   * </p>
+   * <p>
    * There are two return values that indicate success and one that
    * indicates failure.
    * </p>
@@ -288,7 +328,7 @@ public abstract class GLContext {
    * </p>
    * <p>
    * A return value of {@link #CONTEXT_CURRENT} indicates that the context has
-   * been made currrent, with its previous state restored.
+   * been made current, with its previous state restored.
    * </p>
    * <p>
    * If the context could not be made current (for example, because
@@ -320,6 +360,9 @@ public abstract class GLContext {
   /**
    * Releases control of this GLContext from the current thread.
    * <p>
+   * Recursive call to {@link #release()} and hence {@link #makeCurrent()} are supported.
+   * </p>
+   * <p>
    * The drawable's surface is being unlocked at exit,
    * assumed to be locked by {@link #makeCurrent()}.
    * </p>
@@ -401,13 +444,23 @@ public abstract class GLContext {
     }
   }
 
+  /** Returns a String representation of the {@link #makeCurrent()} result. */
+  public static final String makeCurrentResultToString(int res) {
+      switch(res) {
+          case CONTEXT_NOT_CURRENT:   return "CONTEXT_NOT_CURRENT";
+          case CONTEXT_CURRENT:       return "CONTEXT_CURRENT";
+          case CONTEXT_CURRENT_NEW:   return "CONTEXT_NOT_CURRENT";
+          default: return "INVALID_VALUE";
+      }
+  }
+
   /**
    * Sets the thread-local variable returned by {@link #getCurrent}
    * and has no other side-effects. For use by third parties adding
    * new GLContext implementations; not for use by end users.
    */
   protected static void setCurrent(GLContext cur) {
-    if(TRACE_SWITCH) {
+    if( TRACE_SWITCH ) {
        if(null == cur) {
            System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - NULL");
        } else {
@@ -442,12 +495,12 @@ public abstract class GLContext {
   public abstract GL setGL(GL gl);
 
   /**
-   * Returns the native GL context handle
+   * Returns the underlying native OpenGL context handle
    */
   public final long getHandle() { return contextHandle; }
 
   /**
-   * Indicates whether the underlying OpenGL context has been created.
+   * Indicates whether the underlying native OpenGL context has been created.
    */
   public final boolean isCreated() {
     return 0 != contextHandle;
@@ -486,14 +539,9 @@ public abstract class GLContext {
   }
 
   public final StringBuilder append(StringBuilder sb) {
-    sb.append("OpenGL ");
-    sb.append(getGLVersionMajor());
-    sb.append(".");
-    sb.append(getGLVersionMinor());
-    sb.append(", options 0x");
+    sb.append("Version ").append(getGLVersion()).append(" [GL ").append(getGLVersionNumber()).append(", vendor ").append(getGLVendorVersionNumber());
+    sb.append("], options 0x");
     sb.append(Integer.toHexString(ctxOptions));
-    sb.append(", ");
-    sb.append(getGLVersion());
     sb.append(", this ");
     sb.append(toHexString(hashCode()));
     sb.append(", handle ");
@@ -623,8 +671,26 @@ public abstract class GLContext {
     return ctxVersionString;
   }
 
-  public final int getGLVersionMajor() { return ctxMajorVersion; }
-  public final int getGLVersionMinor() { return ctxMinorVersion; }
+  /** @deprecated Use {@link #getGLVersionNumber()} */
+  public final int getGLVersionMajor() { return ctxVersion.getMajor(); }
+  /** @deprecated Use {@link #getGLVersionNumber()} */
+  public final int getGLVersionMinor() { return ctxVersion.getMinor(); }
+  /**
+   * Returns this context OpenGL version. 
+   * @see #getGLSLVersionNumber() 
+   **/
+  public final VersionNumber getGLVersionNumber() { return ctxVersion; }
+  /** 
+   * Returns the vendor's version, i.e. version number at the end of <code>GL_VERSION</code> not being the GL version.
+   * <p>
+   * In case no such version exists within <code>GL_VERSION</code>, 
+   * the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+   * </p> 
+   * <p>
+   * The vendor's version is usually the vendor's OpenGL driver version.
+   * </p>
+   */
+  public final VersionNumberString getGLVendorVersionNumber() { return ctxVendorVersion; }
   public final boolean isGLCompatibilityProfile() { return ( 0 != ( CTX_PROFILE_COMPAT & ctxOptions ) ); }
   public final boolean isGLCoreProfile()          { return ( 0 != ( CTX_PROFILE_CORE   & ctxOptions ) ); }
   public final boolean isGLForwardCompatible()    { return ( 0 != ( CTX_OPTION_FORWARD & ctxOptions ) ); }
@@ -636,13 +702,14 @@ public abstract class GLContext {
    * via {@link GL2ES2#GL_SHADING_LANGUAGE_VERSION} if ≥ ES2.0 or GL2.0,
    * otherwise a static match is being utilized.
    * <p>
-   * The context must have been current once, otherwise <code>null</code> is returned. 
+   * The context must have been current once, 
+   * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned. 
    * </p>
    * <p>
    * Examples w/ <code>major.minor</code>: 
    * <pre>
-   *    1.00 (ES2.0), 1.10 (GL2.0), 1.20 (GL2.1), 1.50 GL(3.2), 
-   *    3.30 (GL3.3), 4.40 (GL4.0)
+   *    1.00 (ES 2.0), 1.10 (GL 2.0), 1.20 (GL 2.1), 1.50 (GL 3.2), 
+   *    3.30 (GL 3.3), 4.00 (GL 4.0), 4.10 (GL 4.1), 4.20 (GL 4.2)
    * </pre >
    * </p>
    * <p>
@@ -651,10 +718,10 @@ public abstract class GLContext {
    * The latter is not true on OSX w/ a GL3 context. 
    * </p>
    * 
-   * @param GLSL version number if context has been made current at least once, otherwise <code>null</code>.
+   * @return GLSL version number if context has been made current at least once, 
+   *         otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
    *            
-   * @see #getGLVersionMajor()
-   * @see #getGLVersionMinor()
+   * @see #getGLVersionNumber()
    */
   public final VersionNumber getGLSLVersionNumber() {
       return ctxGLSLVersion;
@@ -662,45 +729,55 @@ public abstract class GLContext {
   
   /**
    * Returns the GLSL version string as to be used in a shader program, including a terminating newline '\n',
-   * i.e.:
+   * i.e. for desktop
    * <pre>
    *    #version 110
+   *    ..
+   *    #version 150
+   *    #version 330
+   *    ...
+   * </pre>
+   * And for ES:
+   * <pre>
+   *    #version 100
+   *    #version 300 es
+   *    ..
    * </pre>
    * <p>
-   * If context has not been made current, <code>null</code> is returned.
+   * If context has not been made current yet, a string of zero length is returned.
    * </p>
    * @see #getGLSLVersionNumber()
    */
   public final String getGLSLVersionString() {
-      if(null == ctxGLSLVersion) {
-          return null;
+      if( ctxGLSLVersion.isZero() ) {
+          return "";
       }
       final int minor = ctxGLSLVersion.getMinor();
-      return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + "\n" ;
+      final String esSuffix = isGLES() && ctxGLSLVersion.compareTo(Version30) >= 0 ? " es" : ""; 
+      return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + esSuffix + "\n" ;
   }
   
-  protected static final void getStaticGLSLVersionNumber(int glMajorVersion, int glMinorVersion, int ctxOptions, int[] res) {
+  protected static final VersionNumber getStaticGLSLVersionNumber(int glMajorVersion, int glMinorVersion, int ctxOptions) {
       if( 0 != ( CTX_PROFILE_ES & ctxOptions ) ) {
-          res[0] = 1; res[1] =  0;      // ES 2.0  ->  GLSL 1.00
+          if( 3 > glMajorVersion ) {
+              return Version100;           // ES 2.0  ->  GLSL 1.00
+          }
       } else if( 1 == glMajorVersion ) {
-          res[0] = 1; res[0] = 10;      // GL 1.x  ->  GLSL 1.10
+          return Version110;               // GL 1.x  ->  GLSL 1.10
       } else if( 2 == glMajorVersion ) {
-          res[0] = 1;
           switch ( glMinorVersion ) {
-          case 0:  res[1] = 10; break;  // GL 2.0  ->  GLSL 1.10
-          default: res[1] = 20; break;  // GL 2.1  ->  GLSL 1.20
+              case 0:  return Version110;  // GL 2.0  ->  GLSL 1.10
+              default: return Version120;  // GL 2.1  ->  GLSL 1.20
           }
-      } else if( 3 == glMajorVersion && 2 >= glMajorVersion ) {
-          res[0] = 1;
+      } else if( 3 == glMajorVersion && 2 >= glMinorVersion ) {
           switch ( glMinorVersion ) {
-          case 0:  res[1] = 30; break;  // GL 3.0  ->  GLSL 1.30
-          case 1:  res[1] = 40; break;  // GL 3.1  ->  GLSL 1.40
-          default: res[1] = 50; break;  // GL 3.2  ->  GLSL 1.50 
+              case 0:  return Version130;  // GL 3.0  ->  GLSL 1.30
+              case 1:  return Version140;  // GL 3.1  ->  GLSL 1.40
+              default: return Version150;  // GL 3.2  ->  GLSL 1.50 
           }
-      } else { // >= 3.3
-          res[0] = glMajorVersion;     // GL M.N  ->  GLSL M.N
-          res[1] = glMinorVersion * 10;
       }
+      // The new default: GL >= 3.3, ES >= 3.0
+      return new VersionNumber(glMajorVersion, glMinorVersion * 10, 0); // GL M.N  ->  GLSL M.N
   }
   
   /**
@@ -727,7 +804,7 @@ public abstract class GLContext {
   public final boolean hasGLSL() {
       return isGLES2() ||
              isGL3() ||
-             isGL2() && ctxMajorVersion>1 ;
+             isGL2() && ctxVersion.getMajor()>1 ;
   }
 
   /** 
@@ -759,15 +836,15 @@ public abstract class GLContext {
    * </p>
    */
   public final boolean hasFullFBOSupport() {        
-      return !FORCE_MIN_FBO_SUPPORT && hasBasicFBOSupport() &&
-              ( isGL3() ||                                                         // GL >= 3.0                
-                isExtensionAvailable(GLExtensions.ARB_framebuffer_object) ||       // ARB_framebuffer_object
-                ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) &&     // All EXT_framebuffer_object*
-                  isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
-                  isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
-                  isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil)
-                )
-              ) ;               
+      return hasBasicFBOSupport() && !hasRendererQuirk(GLRendererQuirks.NoFullFBOSupport) &&
+             ( isGL3() ||                                                         // GL >= 3.0                
+               isExtensionAvailable(GLExtensions.ARB_framebuffer_object) ||       // ARB_framebuffer_object
+               ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) &&     // All EXT_framebuffer_object*
+                 isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
+                 isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
+                 isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil)
+               )
+             ) ;
   }
   
   /**
@@ -804,46 +881,46 @@ public abstract class GLContext {
 
   /** @see GLProfile#isGL4bc() */
   public final boolean isGL4bc() {
-      return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
-                                && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
+      return ctxVersion.getMajor() >= 4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
+                                        && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
   }
 
   /** @see GLProfile#isGL4() */
   public final boolean isGL4() {
-      return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
-                                && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
+      return ctxVersion.getMajor() >= 4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
+                                        && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
   }
 
   /** Indicates whether this profile is capable of GL4 (core only). <p>Includes [ GL4 ].</p> */
   public final boolean isGL4core() {
-      return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
-                                && 0 != (ctxOptions & CTX_PROFILE_CORE);
+      return ctxVersion.getMajor() >= 4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
+                                        && 0 != (ctxOptions & CTX_PROFILE_CORE);
   }
   
   /** @see GLProfile#isGL3bc() */
   public final boolean isGL3bc() {
-      return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
+      return ctxVersion.compareTo(Version31) >= 0
              && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
              && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
   }
 
   /** @see GLProfile#isGL3() */
   public final boolean isGL3() {
-      return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
+      return ctxVersion.compareTo(Version31) >= 0
              && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
              && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
   }
   
-  /** Indicates whether this profile is capable of GL3 (core only). <p>Includes [ GL4, GL3 ].</p> */
+  /** Indicates whether this profile is capable of GL3 (core only). GL3 starts w/ OpenGL 3.1 <p>Includes [ GL4, GL3 ].</p> */
   public final boolean isGL3core() {
-      return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
+      return ctxVersion.compareTo(Version31) >= 0
              && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
              && 0 != (ctxOptions & CTX_PROFILE_CORE);
   }
   
   /** @see GLProfile#isGL2() */
   public final boolean isGL2() {
-      return ctxMajorVersion>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT);
+      return ctxVersion.getMajor()>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT);
   }
 
   /** @see GLProfile#isGL2GL3() */  
@@ -853,12 +930,12 @@ public abstract class GLContext {
 
   /** @see GLProfile#isGLES1() */
   public final boolean isGLES1() {
-      return ctxMajorVersion==1 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
+      return ctxVersion.getMajor() == 1 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
   }
 
   /** @see GLProfile#isGLES2() */
   public final boolean isGLES2() {
-      return ctxMajorVersion==2 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
+      return ctxVersion.getMajor() == 2 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
   }
 
   /** @see GLProfile#isGLES() */
@@ -970,6 +1047,25 @@ public abstract class GLContext {
    */
   public abstract int getDefaultReadFramebuffer();
   
+  /** 
+   * Returns the default color buffer within the current bound 
+   * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​,  
+   * which will be used as the source for pixel reading commands, 
+   * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc.
+   * <p>
+   * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
+   * otherwise this is {@link GL#GL_FRONT} for single buffer configurations 
+   * and {@link GL#GL_BACK} for double buffer configurations.
+   * </p> 
+   */
+  public abstract int getDefaultReadBuffer();
+  
+  /** Get the default pixel data type, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}. */
+  public abstract int getDefaultPixelDataType();
+  
+  /** Get the default pixel data format, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}. */
+  public abstract int getDefaultPixelDataFormat();
+  
   /**
    * @return The extension implementing the GLDebugOutput feature,
    *         either <i>GL_ARB_debug_output</i> or <i>GL_AMD_debug_output</i>.
@@ -1126,12 +1222,12 @@ public abstract class GLContext {
   /**
    * @see #getDeviceVersionAvailableKey(javax.media.nativewindow.AbstractGraphicsDevice, int, int)
    */
-  protected static /*final*/ HashMap<String, Integer> deviceVersionAvailable = new HashMap<String, Integer>();
+  protected static final IdentityHashMap<String, Integer> deviceVersionAvailable = new IdentityHashMap<String, Integer>();
 
   /**
    * @see #getUniqueDeviceString(javax.media.nativewindow.AbstractGraphicsDevice)
    */
-  private static /*final*/ HashSet<String> deviceVersionsAvailableSet = new HashSet<String>();
+  private static final IdentityHashMap<String, String> deviceVersionsAvailableSet = new IdentityHashMap<String, String>();
 
   /** clears the device/context mappings as well as the GL/GLX proc address tables. */
   protected static void shutdown() {
@@ -1142,17 +1238,16 @@ public abstract class GLContext {
 
   protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) {
       synchronized ( deviceVersionsAvailableSet ) {
-        return deviceVersionsAvailableSet.contains(device.getUniqueID());
+        return deviceVersionsAvailableSet.containsKey(device.getUniqueID());
       }
   }
 
   protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) {
       synchronized ( deviceVersionsAvailableSet ) {
-          String devKey = device.getUniqueID();
-          if ( deviceVersionsAvailableSet.contains(devKey) ) {
+          final String devKey = device.getUniqueID();
+          if( null != deviceVersionsAvailableSet.put(devKey, devKey) ) {
               throw new InternalError("Already set: "+devKey);
           }
-          deviceVersionsAvailableSet.add(devKey);
           if (DEBUG) {
             System.err.println(getThreadName() + ": createContextARB: SET mappedVersionsAvailableSet "+devKey);
             System.err.println(GLContext.dumpAvailableGLVersions(null).toString());            
@@ -1160,8 +1255,13 @@ public abstract class GLContext {
       }
   }
 
+  /** 
+   * Returns a unique String object using {@link String#intern()} for the given arguments, 
+   * which object reference itself can be used as a key.
+   */
   protected static String getDeviceVersionAvailableKey(AbstractGraphicsDevice device, int major, int profile) {
-      return device.getUniqueID() + "-" + toHexString(composeBits(major, profile, 0));
+      final String r = device.getUniqueID() + "-" + toHexString(composeBits(major, profile, 0));
+      return r.intern();
   }
 
   /**
@@ -1189,10 +1289,10 @@ public abstract class GLContext {
         System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null));
         // Thread.dumpStack();
     }
-    final String key = getDeviceVersionAvailableKey(device, reqMajor, profile);
+    final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, profile);
     final Integer val = new Integer(composeBits(resMajor, resMinor, resCtp));
     synchronized(deviceVersionAvailable) {
-        return deviceVersionAvailable.put( key, val );
+        return deviceVersionAvailable.put( objectKey, val );
     }
   }
 
@@ -1232,10 +1332,10 @@ public abstract class GLContext {
    * @return the available GL version as encoded with {@link #composeBits(int, int, int), otherwise <code>null</code>
    */
   protected static Integer getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int reqProfile)  {
-    String key = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
+    final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
     Integer val;
     synchronized(deviceVersionAvailable) {
-        val = deviceVersionAvailable.get( key );
+        val = deviceVersionAvailable.get( objectKey );
     }
     return val;
   }
@@ -1492,9 +1592,7 @@ public abstract class GLContext {
     return needColon;
   }
 
-  protected static String getThreadName() {
-    return Thread.currentThread().getName();
-  }
+  protected static String getThreadName() { return Thread.currentThread().getName(); }
   
 }
 
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawable.java b/src/jogl/classes/javax/media/opengl/GLDrawable.java
index c0910eb..369ea6d 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawable.java
@@ -65,29 +65,31 @@ public interface GLDrawable {
   public GLContext createContext(GLContext shareWith);
 
   /**
-   * Indicates to on-screen GLDrawable implementations whether the
-   * underlying window has been created and can be drawn into. End
-   * users do not need to call this method; it is not necessary to
-   * call <code>setRealized</code> on a GLCanvas, a GLJPanel, or a
-   * GLPbuffer, as these perform the appropriate calls on their
-   * underlying GLDrawables internally.
-   *
-   * <P>
-   *
+   * Indicates to GLDrawable implementations whether the
+   * underlying {@link NativeSurface surface} has been created and can be drawn into.
+   * <p>
+   * If realized, the {@link #getHandle() drawable handle} may become
+   * valid while it's {@link NativeSurface surface} is being {@link NativeSurface#lockSurface() locked}.
+   * </p>
+   * <p>
+   * End users do not need to call this method; it is not necessary to
+   * call <code>setRealized</code> on a {@link GLAutoDrawable} 
+   * as these perform the appropriate calls on their underlying GLDrawables internally.
+   * </p>
+   * <p>
    * Developers implementing new OpenGL components for various window
    * toolkits need to call this method against GLDrawables obtained
-   * from the GLDrawableFactory via the {@link
-   * GLDrawableFactory#getGLDrawable
-   * GLDrawableFactory.getGLDrawable()} method. It must typically be
+   * from the GLDrawableFactory via the 
+   * {@link GLDrawableFactory#createGLDrawable(NativeSurface)} method.
+   * It must typically be
    * called with an argument of <code>true</code> when the component
    * associated with the GLDrawable is realized and with an argument
    * of <code>false</code> just before the component is unrealized.
    * For the AWT, this means calling <code>setRealized(true)</code> in
    * the <code>addNotify</code> method and with an argument of
    * <code>false</code> in the <code>removeNotify</code> method.
-   *
-   * <P>
-   *
+   * </p>
+   * <p>   
    * <code>GLDrawable</code> implementations should handle multiple
    * cycles of <code>setRealized(true)</code> /
    * <code>setRealized(false)</code> calls. Most, if not all, Java
@@ -101,12 +103,11 @@ public interface GLDrawable {
    * <code>GLDrawable</code> to re-initialize and destroy any
    * associated resources as the component becomes realized and
    * unrealized, respectively.
-   *
-   * <P>
-   *
+   * </p>
+   * <p>   
    * With an argument of <code>true</code>,
    * the minimum implementation shall call
-   * {@link NativeSurface#lockSurface() NativeSurface's lockSurface()} and if successfull:
+   * {@link NativeSurface#lockSurface() NativeSurface's lockSurface()} and if successful:
    * <ul>
    *    <li> Update the {@link GLCapabilities}, which are associated with
    *         the attached {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.</li>
@@ -115,18 +116,27 @@ public interface GLDrawable {
    * This is important since {@link NativeSurface#lockSurface() NativeSurface's lockSurface()}
    * ensures resolving the window/surface handles, and the drawable's {@link GLCapabilities}
    * might have changed.
-   *
-   * <P>
-   *
+   * </p>
+   * <p>   
    * Calling this method has no other effects. For example, if
    * <code>removeNotify</code> is called on a Canvas implementation
    * for which a GLDrawable has been created, it is also necessary to
    * destroy all OpenGL contexts associated with that GLDrawable. This
    * is not done automatically by the implementation.
+   * </p>
+   * @see #isRealized()
+   * @see #getHandle()
+   * @see NativeSurface#lockSurface()
    */
   public void setRealized(boolean realized);
 
-  /** @return true if this drawable is realized, otherwise false */
+  /** 
+   * Returns <code>true</code> if this drawable is realized, otherwise <code>true</code>.
+   * <p>
+   * A drawable can be realized and unrealized via {@link #setRealized(boolean)}.
+   * </p>
+   * @see #setRealized(boolean)
+   */
   public boolean isRealized();
 
   /** Returns the current width of this GLDrawable. */
@@ -135,6 +145,20 @@ public interface GLDrawable {
   /** Returns the current height of this GLDrawable. */
   public int getHeight();
 
+  /**
+   * Returns <code>true</code> if the drawable is rendered in 
+   * OpenGL's coordinate system, <i>origin at bottom left</i>.
+   * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
+   * <p>
+   * Default impl. is <code>true</code>, i.e. OpenGL coordinate system.
+   * </p> 
+   * <p>
+   * Currently only MS-Windows bitmap offscreen drawable uses a non OpenGL orientation and hence returns <code>false</code>.<br/>
+   * This removes the need of a vertical flip when used in AWT or Windows applications.
+   * </p>
+   */
+  public boolean isGLOriented();
+  
   /** Swaps the front and back buffers of this drawable. For {@link
       GLAutoDrawable} implementations, when automatic buffer swapping
       is enabled (as is the default), this method is called
@@ -167,11 +191,22 @@ public interface GLDrawable {
   public NativeSurface getNativeSurface();
 
   /**
-   * This is the GL/Windowing drawable handle.<br>
-   * It is usually the {@link javax.media.nativewindow.NativeSurface#getSurfaceHandle()},
-   * ie the native surface handle of the underlying windowing toolkit.<br>
-   * However, on X11/GLX this reflects a GLXDrawable, which represents a GLXWindow, GLXPixmap, or GLXPbuffer.<br>
-   * On EGL, this represents the EGLSurface.<br>
+   * Returns the GL drawable handle, 
+   * guaranteed to be valid after {@link #setRealized(boolean) realization}
+   * <i>and</i> while it's {@link NativeSurface surface} is being {@link NativeSurface#lockSurface() locked}.
+   * <p>
+   * It is usually identical to the underlying windowing toolkit {@link NativeSurface surface}'s 
+   * {@link javax.media.nativewindow.NativeSurface#getSurfaceHandle() handle}
+   * or an intermediate layer to suite GL, e.g. an EGL surface.
+   * </p>
+   * <p>
+   * On EGL it is represented by the EGLSurface.<br>
+   * On X11/GLX it is represented by either the Window XID, GLXPixmap, or GLXPbuffer.<br>
+   * On Windows it is represented by the HDC, which may change with each {@link #lockSurface()}.<br>
+   * </p>
+   * @see #setRealized(boolean)
+   * @see NativeSurface#lockSurface()
+   * @see NativeSurface#unlockSurface()
    */
   public long getHandle();
 
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index 70480e7..f1d8ff9 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -40,13 +40,9 @@
 
 package javax.media.opengl;
 
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.jogamp.common.JogampRuntimeException;
-
 import com.jogamp.common.util.ReflectionUtil;
 import com.jogamp.opengl.GLAutoDrawableDelegate;
 import com.jogamp.opengl.GLRendererQuirks;
@@ -116,20 +112,12 @@ public abstract class GLDrawableFactory {
    */
   protected static final boolean disableOpenGLES = Debug.isPropertyDefined("jogl.disable.opengles", true);
 
-  static final String macosxFactoryClassNameCGL = "jogamp.opengl.macosx.cgl.MacOSXCGLDrawableFactory";
-  static final String macosxFactoryClassNameAWTCGL = "jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLDrawableFactory";
-
   private static volatile boolean isInit = false;
   private static GLDrawableFactory eglFactory;
   private static GLDrawableFactory nativeOSFactory;
 
-  protected static ArrayList<GLDrawableFactory> glDrawableFactories = new ArrayList<GLDrawableFactory>();
-
-  // Shutdown hook mechanism for the factory
-  private static boolean factoryShutdownHookRegistered = false;
-  private static Thread factoryShutdownHook = null;
-  private static volatile boolean isJVMShuttingDown = false;
-
+  private static ArrayList<GLDrawableFactory> glDrawableFactories = new ArrayList<GLDrawableFactory>();
+  
   /**
    * Instantiate singleton factories if available, EGLES1, EGLES2 and the OS native ones.
    */
@@ -144,7 +132,12 @@ public abstract class GLDrawableFactory {
       }
   }  
   private static final void initSingletonImpl() {
-    registerFactoryShutdownHook();
+    NativeWindowFactory.initSingleton();
+    NativeWindowFactory.addCustomShutdownHook(false /* head */, new Runnable() {
+       public void run() {
+           shutdown0();
+       }
+    });
     
     final String nwt = NativeWindowFactory.getNativeWindowType(true);
     GLDrawableFactory tmp = null;
@@ -156,11 +149,7 @@ public abstract class GLDrawableFactory {
         } else if ( nwt == NativeWindowFactory.TYPE_WINDOWS ) {
           factoryClassName = "jogamp.opengl.windows.wgl.WindowsWGLDrawableFactory";
         } else if ( nwt == NativeWindowFactory.TYPE_MACOSX ) {
-            if(ReflectionUtil.isClassAvailable(macosxFactoryClassNameAWTCGL, cl)) {
-                factoryClassName = macosxFactoryClassNameAWTCGL;
-            } else {
-                factoryClassName = macosxFactoryClassNameCGL;
-            }
+          factoryClassName = "jogamp.opengl.macosx.cgl.MacOSXCGLDrawableFactory";
         } else {
           // may use egl*Factory ..
           if (DEBUG || GLProfile.DEBUG) {
@@ -174,7 +163,7 @@ public abstract class GLDrawableFactory {
       }
       try {
           tmp = (GLDrawableFactory) ReflectionUtil.createInstance(factoryClassName, cl);
-      } catch (JogampRuntimeException jre) { 
+      } catch (Exception jre) { 
           if (DEBUG || GLProfile.DEBUG) {
               System.err.println("Info: GLDrawableFactory.static - Native Platform: "+nwt+" - not available: "+factoryClassName);
               jre.printStackTrace();
@@ -189,7 +178,7 @@ public abstract class GLDrawableFactory {
     if(!disableOpenGLES) {
         try {
             tmp = (GLDrawableFactory) ReflectionUtil.createInstance("jogamp.opengl.egl.EGLDrawableFactory", cl);
-        } catch (JogampRuntimeException jre) {
+        } catch (Exception jre) {
             if (DEBUG || GLProfile.DEBUG) {
                 System.err.println("Info: GLDrawableFactory.static - EGLDrawableFactory - not available");
                 jre.printStackTrace();
@@ -208,19 +197,35 @@ public abstract class GLDrawableFactory {
       synchronized (GLDrawableFactory.class) {
           if (isInit) {
               isInit=false;
-              shutdownImpl();
+              shutdown0();
           }
       }
     }
   }
   
-  private static void shutdownImpl() {
+  private static void shutdown0() {
     // Following code will _always_ remain in shutdown hook
     // due to special semantics of native utils, i.e. X11Utils.
     // The latter requires shutdown at JVM-Shutdown only.
     synchronized(glDrawableFactories) {
-        for(int i=0; i<glDrawableFactories.size(); i++) {
-            glDrawableFactories.get(i).destroy();
+        final int gldfCount = glDrawableFactories.size();
+        if( DEBUG ) {
+            System.err.println("GLDrawableFactory.shutdownAll "+gldfCount+" instances, on thread "+getThreadName());
+        }
+        for(int i=0; i<gldfCount; i++) {
+            final GLDrawableFactory gldf = glDrawableFactories.get(i);
+            if( DEBUG ) {
+                System.err.println("GLDrawableFactory.shutdownAll["+(i+1)+"/"+gldfCount+"]:  "+gldf.getClass().getName());
+            }
+            try {
+                gldf.resetDisplayGamma();
+                gldf.destroy();
+            } catch (Throwable t) {
+                System.err.println("GLDrawableFactory.shutdownImpl: Catched "+t.getClass().getName()+" during factory shutdown #"+(i+1)+"/"+gldfCount+" "+gldf.getClass().getName());
+                if( DEBUG ) {
+                    t.printStackTrace();
+                }
+            }
         }
         glDrawableFactories.clear();
         
@@ -229,34 +234,16 @@ public abstract class GLDrawableFactory {
         eglFactory = null;
     }
     GLContext.shutdown();
-    NativeWindowFactory.shutdown(isJVMShuttingDown);
   }
   
-  private static synchronized void registerFactoryShutdownHook() {
-    if (factoryShutdownHookRegistered) {
-        return;
-    }
-    factoryShutdownHook = new Thread(new Runnable() {
-        public void run() {
-            isJVMShuttingDown = true;
-            GLDrawableFactory.shutdownImpl();
-        }
-    });
-    AccessController.doPrivileged(new PrivilegedAction<Object>() {
-        public Object run() {
-            Runtime.getRuntime().addShutdownHook(factoryShutdownHook);
-            return null;
-        }
-    });
-    factoryShutdownHookRegistered = true;
-  }
-
   protected GLDrawableFactory() {
     synchronized(glDrawableFactories) {
         glDrawableFactories.add(this);
     }
   }
   
+  protected static String getThreadName() { return Thread.currentThread().getName(); }
+  
   /** Returns true if this factory is complete, i.e. ready to be used. Otherwise return false. */
   protected abstract boolean isComplete();
 
@@ -265,6 +252,8 @@ public abstract class GLDrawableFactory {
 
   protected abstract void destroy();
 
+  public abstract void resetDisplayGamma();
+  
   /**
    * Retrieve the default <code>device</code> {@link AbstractGraphicsDevice#getConnection() connection},
    * {@link AbstractGraphicsDevice#getUnitID() unit ID} and {@link AbstractGraphicsDevice#getUniqueID() unique ID name}. for this factory<br>
@@ -292,7 +281,7 @@ public abstract class GLDrawableFactory {
       if(null==device) {
           device = getDefaultDevice();
           if(null==device) {
-              throw new InternalError("no default device");
+              throw new InternalError("no default device available");
           }
           if (GLProfile.DEBUG) {
               System.err.println("Info: "+getClass().getSimpleName()+".validateDevice: using default device : "+device);
@@ -329,7 +318,10 @@ public abstract class GLDrawableFactory {
    * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
    * @return true if a shared resource could been created, otherwise false. 
    */
-  protected abstract boolean createSharedResource(AbstractGraphicsDevice device);
+  protected final boolean createSharedResource(AbstractGraphicsDevice device) {
+      return createSharedResourceImpl(device);
+  }  
+  protected abstract boolean createSharedResourceImpl(AbstractGraphicsDevice device);
   
   /**
    * Returns true if the <code>quirk</code> exist in the shared resource's context {@link GLRendererQuirks}.
@@ -426,7 +418,7 @@ public abstract class GLDrawableFactory {
   public final List<GLCapabilitiesImmutable> getAvailableCapabilities(AbstractGraphicsDevice device) {
       device = validateDevice(device);
       if(null!=device) {
-        return getAvailableCapabilitiesImpl(device);
+          return getAvailableCapabilitiesImpl(device);
       }
       return null;
   }
@@ -436,7 +428,7 @@ public abstract class GLDrawableFactory {
   // Methods to create high-level objects
 
   /**
-   * Returns a GLDrawable according to it's chosen {@link GLCapabilitiesImmutable},<br>
+   * Returns an {@link GLDrawable#isRealized() unrealized} GLDrawable according to it's chosen {@link GLCapabilitiesImmutable},<br>
    * which determines pixel format, on- and offscreen incl. PBuffer type.
    * <p>
    * The chosen {@link GLCapabilitiesImmutable} are referenced within the target
@@ -473,9 +465,11 @@ public abstract class GLDrawableFactory {
     throws IllegalArgumentException, GLException;
   
   /**
-   * Creates an {@link GLOffscreenAutoDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
+   * Creates a {@link GLDrawable#isRealized() realized} {@link GLOffscreenAutoDrawable} 
+   * incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
    * <p>
-   * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is realized and it's {@link GLContext} assigned but not yet made current.
+   * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is {@link GLDrawable#isRealized() realized} 
+   * and it's {@link GLContext} assigned but not yet made current.
    * </p>
    * <p>
    * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
@@ -513,7 +507,8 @@ public abstract class GLDrawableFactory {
                                                                       int width, int height,
                                                                       GLContext shareWith) throws GLException;
   /**
-   * Creates a offscreen {@link GLDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
+   * Creates an {@link GLDrawable#isRealized() unrealized} offscreen {@link GLDrawable} 
+   * incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
    * <p>
    * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
    * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} <code> == true</code>,
@@ -557,7 +552,8 @@ public abstract class GLDrawableFactory {
    * <code>windowHandle</code>'s native visualID if set or the given {@link GLCapabilitiesImmutable}.
    * </p>
    * <p>
-   * Lifecycle (destruction) of the given surface handle shall be handled by the caller.
+   * Lifecycle (creation and destruction) of the given surface handle shall be handled by the caller
+   * via {@link ProxySurface#createNotify()} and {@link ProxySurface#destroyNotify()}.  
    * </p>
    * <p>
    * Such surface can be used to instantiate a GLDrawable. With the help of {@link GLAutoDrawableDelegate}
diff --git a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
index 079d9af..4d6c7c2 100644
--- a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
@@ -101,7 +101,8 @@ public interface GLFBODrawable extends GLDrawable {
     void setTextureUnit(int unit);
     
     /**
-     * Set a new sample size
+     * Set the number of sample buffers if using MSAA
+     * 
      * @param gl GL context object bound to this drawable, will be made current during operation. 
      *           A prev. current context will be make current after operation. 
      * @param newSamples new sample size
@@ -113,6 +114,25 @@ public interface GLFBODrawable extends GLDrawable {
      * @return the number of sample buffers if using MSAA, otherwise 0
      */
     int getNumSamples();
+        
+    /**
+     * Sets the number of buffers (FBO) being used if using {@link GLCapabilities#getDoubleBuffered() double buffering}.
+     * <p>
+     * If {@link GLCapabilities#getDoubleBuffered() double buffering} is not chosen, this is a NOP.
+     * </p>
+     * <p>
+     * Must be called before {@link #isInitialized() initialization}, otherwise an exception is thrown.
+     * </p>
+     * @return the new number of buffers (FBO) used, maybe different than the requested <code>bufferCount</code> (see above) 
+     * @throws GLException if already initialized, see {@link #isInitialized()}.
+     */
+    int setNumBuffers(int bufferCount) throws GLException;
+    
+    /** 
+     * @return the number of buffers (FBO) being used. 1 if not using {@link GLCapabilities#getDoubleBuffered() double buffering},
+     * otherwise ≥ 2, depending on {@link #setNumBuffers(int)}. 
+     */
+    int getNumBuffers();
     
     /**
      * @return the used {@link DoubleBufferMode} 
diff --git a/src/jogl/classes/javax/media/opengl/GLPbuffer.java b/src/jogl/classes/javax/media/opengl/GLPbuffer.java
index de7731a..12f57fc 100644
--- a/src/jogl/classes/javax/media/opengl/GLPbuffer.java
+++ b/src/jogl/classes/javax/media/opengl/GLPbuffer.java
@@ -50,32 +50,7 @@ package javax.media.opengl;
     @deprecated Use {@link GLOffscreenAutoDrawable} w/ {@link GLCapabilities#setFBO(boolean)} 
                 via {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) GLDrawableFactory.createOffscreenAutoDrawable(..)}.
   */
-
 public interface GLPbuffer extends GLAutoDrawable {
-  /** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */
-  public static final int APPLE_FLOAT = 1;
-
-  /** Indicates the GL_ATI_texture_float extension is being used for this pbuffer. */
-  public static final int ATI_FLOAT = 2;
-
-  /** Indicates the GL_NV_float_buffer extension is being used for this pbuffer. */
-  public static final int NV_FLOAT = 3;
-
-  /** Binds this pbuffer to its internal texture target. Only valid to
-      call if offscreen render-to-texture has been specified in the
-      NWCapabilities for this GLPbuffer. If the
-      render-to-texture-rectangle capability has also been specified,
-      this will use e.g. wglBindTexImageARB as its implementation and
-      cause the texture to be bound to e.g. the
-      GL_TEXTURE_RECTANGLE_NV state; otherwise, during the display()
-      phase the pixels will have been copied into an internal texture
-      target and this will cause that to be bound to the GL_TEXTURE_2D
-      state. */
-  public void bindTexture();
-
-  /** Unbinds the pbuffer from its internal texture target. */
-  public void releaseTexture();
-
   /** Destroys the native resources associated with this pbuffer. It
       is not valid to call display() or any other routines on this
       pbuffer after it has been destroyed. Before destroying the
@@ -84,13 +59,4 @@ public interface GLPbuffer extends GLAutoDrawable {
       #createContext}. */
   @Override
   public void destroy();
-
-  /** Indicates which vendor's extension is being used to support
-      floating point channels in this pbuffer if that capability was
-      requested in the NWCapabilities during pbuffer creation. Returns
-      one of NV_FLOAT, ATI_FLOAT or APPLE_FLOAT, or throws GLException
-      if floating-point channels were not requested for this pbuffer.
-      This function may only be called once the init method for this
-      pbuffer's GLEventListener has been called. */
-  public int getFloatingPointMode();
 }
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index f916ab8..1b6af22 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -543,8 +543,20 @@ public class GLProfile {
      * </ul>
      *
      */
-    public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER   = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GLES2 };
+    public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER = new String[] { GL4bc, GL4, GL3bc, GL3, GL2, GLES2 };
 
+    /**
+     * Order of maximum programmable shader <i>core only</i> profiles
+     *
+     * <ul>
+     *  <li> GL4
+     *  <li> GL3
+     *  <li> GLES2
+     * </ul>
+     *
+     */
+    public static final String[] GL_PROFILE_LIST_MAX_PROGSHADER_CORE = new String[] { GL4, GL3, GLES2 };
+    
     /** Returns a default GLProfile object, reflecting the best for the running platform.
      * It selects the first of the set {@link GLProfile#GL_PROFILE_LIST_ALL}
      * and favors hardware acceleration.
@@ -659,6 +671,29 @@ public class GLProfile {
         return get(GL_PROFILE_LIST_MAX_PROGSHADER, favorHardwareRasterizer);
     }
 
+    /**
+     * Returns the highest profile, implementing the programmable shader <i>core</i> pipeline <i>only</i>.
+     * It selects the first of the set: {@link GLProfile#GL_PROFILE_LIST_MAX_PROGSHADER_CORE}
+     *
+     * @throws GLException if no programmable core profile is available for the device.
+     * @see #GL_PROFILE_LIST_MAX_PROGSHADER_CORE
+     */
+    public static GLProfile getMaxProgrammableCore(AbstractGraphicsDevice device, boolean favorHardwareRasterizer)
+        throws GLException
+    {            
+        return get(device, GL_PROFILE_LIST_MAX_PROGSHADER_CORE, favorHardwareRasterizer);
+    }
+
+    /** Uses the default device 
+     * @throws GLException if no programmable core profile is available for the default device.
+     * @see #GL_PROFILE_LIST_MAX_PROGSHADER_CORE
+     */
+    public static GLProfile getMaxProgrammableCore(boolean favorHardwareRasterizer)
+        throws GLException
+    {
+        return get(GL_PROFILE_LIST_MAX_PROGSHADER_CORE, favorHardwareRasterizer);
+    }
+    
     /** 
      * Returns the GL2ES1 profile implementation, hence compatible w/ GL2ES1.<br/>
      * It returns:
@@ -1489,7 +1524,7 @@ public class GLProfile {
         final boolean addedEGLProfile     = null != defaultEGLDevice     ? initProfilesForDevice(defaultEGLDevice)     : false;
         final boolean addedDesktopProfile = null != defaultDesktopDevice ? initProfilesForDevice(defaultDesktopDevice) : false;        
         final boolean addedAnyProfile     = addedEGLProfile || addedDesktopProfile ;
-            
+    
         if(DEBUG) {
             System.err.println("GLProfile.init addedAnyProfile       "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
             System.err.println("GLProfile.init isAWTAvailable        "+isAWTAvailable);
diff --git a/src/jogl/classes/javax/media/opengl/GLUniformData.java b/src/jogl/classes/javax/media/opengl/GLUniformData.java
index 9638ba8..60d0c58 100644
--- a/src/jogl/classes/javax/media/opengl/GLUniformData.java
+++ b/src/jogl/classes/javax/media/opengl/GLUniformData.java
@@ -4,7 +4,7 @@ package javax.media.opengl;
 import java.nio.*;
 
 import com.jogamp.common.nio.Buffers;
-import com.jogamp.opengl.FloatUtil;
+import com.jogamp.opengl.math.FloatUtil;
 
 public class GLUniformData {
 
@@ -147,10 +147,26 @@ public class GLUniformData {
     public int getLocation() { return location; }
 
     /**
-     * Sets the determined location of the shader uniform.
+     * Sets the given location of the shader uniform.
+     * @return the given location
      */
-    public GLUniformData setLocation(int location) { this.location=location; return this; }
+    public int setLocation(int location) { this.location=location; return location; }
 
+    /**
+     * Retrieves the location of the shader uniform from the linked shader program.
+     * <p>
+     * No validation is performed within the implementation.
+     * </p>
+     * @param gl
+     * @param program
+     * @return ≥0 denotes a valid uniform location as found and used in the given shader program.
+     *         <0 denotes an invalid location, i.e. not found or used in the given shader program.
+     */
+    public int setLocation(GL2ES2 gl, int program) {
+        location = gl.glGetUniformLocation(program, name);
+        return location;
+    }
+    
     public Object getObject() {
         return data;
     }
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 1e9fcc9..b7a24a7 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -57,6 +57,7 @@ import java.awt.geom.Rectangle2D;
 import java.awt.EventQueue;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.List;
 
 import javax.media.nativewindow.AbstractGraphicsConfiguration;
 import javax.media.nativewindow.OffscreenLayerOption;
@@ -85,6 +86,7 @@ import javax.media.opengl.Threading;
 
 import com.jogamp.common.GlueGenVersion;
 import com.jogamp.common.util.VersionUtil;
+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.AWTGraphicsConfiguration;
@@ -94,7 +96,6 @@ import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
 import com.jogamp.nativewindow.awt.JAWTWindow;
 import com.jogamp.opengl.JoglVersion;
 
-import jogamp.common.awt.AWTEDTExecutor;
 import jogamp.opengl.Debug;
 import jogamp.opengl.GLContextImpl;
 import jogamp.opengl.GLDrawableHelper;
@@ -173,9 +174,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
           new AWTWindowClosingProtocol(this, new Runnable() {
                 @Override
                 public void run() {
-                    GLCanvas.this.destroy();
+                    GLCanvas.this.destroyImpl( true );
                 }
-            });
+            }, null);
 
   /** Creates a new GLCanvas component with a default set of OpenGL
       capabilities, using the default OpenGL capabilities selection
@@ -311,6 +312,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
      *     all platforms since the peer hasn't been created.
      */
     final GraphicsConfiguration gc = super.getGraphicsConfiguration();
+    
+    if( Beans.isDesignTime() ) {
+        return gc;
+    }
+    
     /*
      * chosen is only non-null on platforms where the GLDrawableFactory
      * returns a non-null GraphicsConfiguration (in the GLCanvas
@@ -369,10 +375,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
            */
           chosen = compatible;
 
-          awtConfig = config;
-
           if( !equalCaps && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) {
-              dispose(true);
+              // complete destruction!
+              destroyImpl( true );
+              // recreation!
+              awtConfig = config;
+              createDrawableAndContext( true );
+              validateGLDrawable();
+          } else {
+              awtConfig = config;
           }
         }
       }
@@ -418,8 +429,30 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
     }
   }
     
+  private final void setRealizedImpl(boolean realized) {
+      final RecursiveLock _lock = lock;
+      _lock.lock();
+      try {            
+          final GLDrawable _drawable = drawable;
+          if( null == _drawable || realized == _drawable.isRealized() ||
+              realized && ( 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) ) {
+              return;
+          }
+         _drawable.setRealized(realized);
+          if( realized && _drawable.isRealized() ) {
+              sendReshape=true; // ensure a reshape is being send ..
+          }
+      } finally {
+          _lock.unlock();
+      }
+  }  
+  private final Runnable realizeOnEDTAction = new Runnable() { public void run() { setRealizedImpl(true); } };
+  private final Runnable unrealizeOnEDTAction = new Runnable() { public void run() { setRealizedImpl(false); } };
+  
   @Override
-  public void setRealized(boolean realized) {
+  public final void setRealized(boolean realized) {
+      // Make sure drawable realization happens on AWT-EDT and only there. Consider the AWTTree lock!
+      AWTEDTExecutor.singleton.invoke(getTreeLock(), false /* allowOnNonEDT */, true /* wait */, realized ? realizeOnEDTAction : unrealizeOnEDTAction);
   }
 
   @Override
@@ -446,26 +479,33 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
         }
         return; // not yet available ..
     }
-    Threading.invoke(true, displayOnEDTAction, getTreeLock());
-    awtWindowClosingProtocol.addClosingListenerOneShot();
-  }
-
-  private void dispose(boolean regenerate) {
-    disposeRegenerate=regenerate;
-    Threading.invoke(true, disposeOnEDTAction, getTreeLock());
+    if( isVisible() ) {
+        Threading.invoke(true, displayOnEDTAction, getTreeLock());
+    }
   }
 
   /**
    * {@inheritDoc}
    *
    * <p>
-   * This impl. calls this class's {@link #removeNotify()} AWT override,
-   * where the actual implementation resides.
+   * This impl. only destroys all GL related resources.
+   * </p>
+   * <p>
+   * This impl. does not remove the GLCanvas from it's parent AWT container
+   * so this class's {@link #removeNotify()} AWT override won't get called.
+   * To do so, remove this component from it's parent AWT container.
    * </p>
    */
   @Override
   public void destroy() {
-    removeNotify();
+    destroyImpl( false );
+  }
+  
+  protected void destroyImpl(boolean destroyJAWTWindowAndAWTDevice) {
+    Threading.invoke(true, destroyOnEDTAction, getTreeLock());
+    if( destroyJAWTWindowAndAWTDevice ) {
+        AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, disposeJAWTWindowAndAWTDeviceOnEDT);
+    }
   }
 
   /** Overridden to cause OpenGL rendering to be performed during
@@ -475,7 +515,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
     */
   @Override
   public void paint(Graphics g) {
-    if (Beans.isDesignTime()) {
+    if( Beans.isDesignTime() ) {
       // Make GLCanvas behave better in NetBeans GUI builder
       g.setColor(Color.BLACK);
       g.fillRect(0, 0, getWidth(), getHeight());
@@ -493,9 +533,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
       g.drawString(name,
                    (int) ((getWidth()  - bounds.getWidth())  / 2),
                    (int) ((getHeight() + bounds.getHeight()) / 2));
-      return;
-    }
-    if( ! this.helper.isExternalAnimatorAnimating() ) {
+    } else if( !this.helper.isAnimatorAnimatingOnOtherThread() ) {
         display();
     }
   }
@@ -512,42 +550,47 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   public void addNotify() {
     final RecursiveLock _lock = lock;
     _lock.lock();
-    try {    
+    try {   
+        final boolean isBeansDesignTime = Beans.isDesignTime();
+        
         if(DEBUG) {
-            System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds());
+            System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds()+", isBeansDesignTime "+isBeansDesignTime);
             Thread.dumpStack();
         }
     
-        /**
-         * 'super.addNotify()' determines the GraphicsConfiguration,
-         * while calling this class's overriden 'getGraphicsConfiguration()' method
-         * after which it creates the native peer.
-         * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
-         * is being used in getGraphicsConfiguration().
-         * This code order also allows recreation, ie re-adding the GLCanvas.
-         */
-        awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device);
-        if(null==awtConfig) {
-            throw new GLException("Error: NULL AWTGraphicsConfiguration");
-        }
-    
-        // before native peer is valid: X11
-        disableBackgroundErase();
-    
-        // issues getGraphicsConfiguration() and creates the native peer
-        super.addNotify();
-    
-        // after native peer is valid: Windows
-        disableBackgroundErase();
-    
-        if (!Beans.isDesignTime()) {
-            createDrawableAndContext();
+        if( isBeansDesignTime ) {
+            super.addNotify();
+        } else {
+            /**
+             * 'super.addNotify()' determines the GraphicsConfiguration,
+             * while calling this class's overriden 'getGraphicsConfiguration()' method
+             * after which it creates the native peer.
+             * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
+             * is being used in getGraphicsConfiguration().
+             * This code order also allows recreation, ie re-adding the GLCanvas.
+             */
+            awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device);
+            if(null==awtConfig) {
+                throw new GLException("Error: NULL AWTGraphicsConfiguration");
+            }
+        
+            // before native peer is valid: X11
+            disableBackgroundErase();
+        
+            // issues getGraphicsConfiguration() and creates the native peer
+            super.addNotify();
+        
+            // after native peer is valid: Windows
+            disableBackgroundErase();
+        
+            createDrawableAndContext( true );
+        
+            // init drawable by paint/display makes the init sequence more equal
+            // for all launch flavors (applet/javaws/..)
+            // validateGLDrawable();            
         }
-    
-        // init drawable by paint/display makes the init sequence more equal
-        // for all launch flavors (applet/javaws/..)
-        // validateGLDrawable();
-    
+        awtWindowClosingProtocol.addClosingListener();
+
         if(DEBUG) {
             System.err.println(getThreadName()+": Info: addNotify - end: peer: "+getPeer());
         }
@@ -556,58 +599,46 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
     }
   }
 
-  private void createDrawableAndContext() {
-    // no lock required, since this resource ain't available yet
-    jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
-    jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
-    jawtWindow.lockSurface();
-    try {
-        drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
-        context = (GLContextImpl) drawable.createContext(shareWith);
-        context.setContextCreationFlags(additionalCtxCreationFlags);
-    } finally {
-        jawtWindow.unlockSurface();
-    }
-  }
-
-  private boolean validateGLDrawable() {
-    final GLDrawable _drawable = drawable;
-    if ( null != _drawable ) {
-        if( _drawable.isRealized() ) {
-            return true;
-        }
-        if( Beans.isDesignTime() || !isDisplayable() || 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) {
-            return false; // early out!
+  private void createDrawableAndContext(boolean createJAWTWindow) {
+    if ( !Beans.isDesignTime() ) {
+        if( createJAWTWindow ) {
+            jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
+            jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);            
         }
-        // make sure drawable realization happens on AWT EDT, due to AWTTree lock
-        AWTEDTExecutor.singleton.invoke(getTreeLock(), true, setRealizedOnEDTAction);
-        final boolean res = _drawable.isRealized();
-        if(DEBUG) {
-            System.err.println(getThreadName()+": Realized Drawable: "+res+", "+_drawable.toString());
-            Thread.dumpStack();
+        jawtWindow.lockSurface();
+        try {
+            drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
+            context = (GLContextImpl) drawable.createContext(shareWith);
+            context.setContextCreationFlags(additionalCtxCreationFlags);
+        } finally {
+            jawtWindow.unlockSurface();
         }
-        return res;
     }
-    return false;
-  }
-  private Runnable setRealizedOnEDTAction = new Runnable() { 
-      public void run() { 
-          final RecursiveLock _lock = lock;
-          _lock.lock();
-          try {            
-              final GLDrawable _drawable = drawable;
-              if( null == _drawable || 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) {
-                  return; 
-              }
-              _drawable.setRealized(true);
-              if( _drawable.isRealized() ) {
-                  sendReshape=true; // ensure a reshape is being send ..
-              }
-          } finally {
-              _lock.unlock();
-          }
-      } };
+  }  
 
+  private boolean validateGLDrawable() {
+      if( Beans.isDesignTime() || !isDisplayable() ) {
+          return false; // early out!
+      }
+      final GLDrawable _drawable = drawable;
+      if ( null != _drawable ) {
+          if( _drawable.isRealized() ) {
+              return true;
+          }
+          if( 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) {
+              return false; // early out!
+          }
+          setRealized(true);
+          final boolean res = _drawable.isRealized();
+          if(DEBUG) {
+              System.err.println(getThreadName()+": Realized Drawable: isRealized "+res+", "+_drawable.toString());
+              Thread.dumpStack();
+          }
+          return res;
+      }
+      return false;
+  }
+  
   /** <p>Overridden to track when this component is removed from a
       container. Subclasses which override this method must call
       super.removeNotify() in their removeNotify() method in order to
@@ -626,11 +657,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
 
     awtWindowClosingProtocol.removeClosingListener();
 
-    if (Beans.isDesignTime()) {
+    if( Beans.isDesignTime() ) {
       super.removeNotify();
     } else {
       try {
-        dispose(false);
+        destroyImpl( true );
       } finally {
         super.removeNotify();
       }
@@ -656,7 +687,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
         if(DEBUG) {
             final NativeSurface ns = getNativeSurface();
             final long nsH = null != ns ? ns.getSurfaceHandle() : 0;
-            System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(nsH));
+            System.err.println("GLCanvas.sizeChanged: ("+getThreadName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(nsH));
             // Thread.dumpStack();
         }            
         if( validateGLDrawable() ) {
@@ -699,16 +730,38 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   }
 
   @Override
-  public void removeGLEventListener(GLEventListener listener) {
-    helper.removeGLEventListener(listener);
+  public int getGLEventListenerCount() {
+      return helper.getGLEventListenerCount();
+  }
+
+  @Override
+  public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException {
+      return helper.getGLEventListener(index);
+  }
+
+  @Override
+  public boolean getGLEventListenerInitState(GLEventListener listener) {
+      return helper.getGLEventListenerInitState(listener);
   }
 
   @Override
-  public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
-    return helper.removeGLEventListener(index);
+  public void setGLEventListenerInitState(GLEventListener listener, boolean initialized) {
+      helper.setGLEventListenerInitState(listener, initialized);
+  }
+  
+  @Override
+  public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove) {
+    final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
+    Threading.invoke(true, r, getTreeLock());
+    return r.listener;
   }
   
   @Override
+  public GLEventListener removeGLEventListener(GLEventListener listener) {
+    return helper.removeGLEventListener(listener);
+  }
+
+  @Override
   public void setAnimator(GLAnimatorControl animatorControl) {
     helper.setAnimator(animatorControl);
   }
@@ -719,21 +772,33 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   }
 
   @Override
+  public final Thread setExclusiveContextThread(Thread t) throws GLException {
+      return helper.setExclusiveContextThread(t, context);
+  }
+
+  @Override
+  public final Thread getExclusiveContextThread() {
+      return helper.getExclusiveContextThread();
+  }
+
+  @Override
   public boolean invoke(boolean wait, GLRunnable glRunnable) {
     return helper.invoke(this, wait, glRunnable);
   }
 
   @Override
-  public GLContext setContext(GLContext newCtx) {
+  public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) {
+    return helper.invoke(this, wait, glRunnables);
+  }
+  
+  @Override
+  public GLContext setContext(GLContext newCtx, boolean destroyPrevCtx) {
       final RecursiveLock _lock = lock;
       _lock.lock();
       try {
           final GLContext oldCtx = context;
-          final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+          GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
           context=(GLContextImpl)newCtx;
-          if(newCtxCurrent) {
-              context.makeCurrent();
-          }
           return oldCtx;
       } finally {
           _lock.unlock();
@@ -752,7 +817,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
 
   @Override
   public GL getGL() {
-    if (Beans.isDesignTime()) {
+    if( Beans.isDesignTime() ) {
       return null;
     }
     final GLContext _context = context;
@@ -806,22 +871,28 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
 
   @Override
   public GLCapabilitiesImmutable getChosenGLCapabilities() {
-    if (awtConfig == null) {
+    if( Beans.isDesignTime() ) {
+        return capsReqUser;
+    } else if( null == awtConfig ) {
         throw new GLException("No AWTGraphicsConfiguration: "+this);
     }
-
     return (GLCapabilitiesImmutable)awtConfig.getChosenCapabilities();
   }
 
   public GLCapabilitiesImmutable getRequestedGLCapabilities() {
-    if (awtConfig == null) {
+    if( null == awtConfig ) {
         return capsReqUser;
     }
-
     return (GLCapabilitiesImmutable)awtConfig.getRequestedCapabilities();
   }
 
   @Override
+  public boolean isGLOriented() {
+    final GLDrawable _drawable = drawable;
+    return null != _drawable ? _drawable.isGLOriented() : true;
+  }
+  
+  @Override
   public NativeSurface getNativeSurface() {
     final GLDrawable _drawable = drawable;
     return (null != _drawable) ? _drawable.getNativeSurface() : null;
@@ -851,7 +922,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
                           ",\n\thandle    0x"+Long.toHexString(getHandle())+
                           ",\n\tDrawable size "+dw+"x"+dh+
                           ",\n\tAWT pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
-                          ",\n\tvisible "+isVisible()+
+                          ",\n\tvisible "+isVisible()+", displayable "+isDisplayable()+
                           ",\n\t"+awtConfig+"]";
   }
 
@@ -859,35 +930,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   // Internals only below this point
   //
 
-  private boolean disposeRegenerate;
-  private final Runnable postDisposeOnEDTAction = new Runnable() {
-    @Override
-    public void run() {
-      context=null;
-      if(null!=drawable) {
-          drawable.setRealized(false);
-          drawable=null;
-          if(null!=jawtWindow) {
-            jawtWindow.destroy();
-            jawtWindow=null;
-          }
-      }
-
-      if(disposeRegenerate) {
-          // Similar process as in addNotify()!
-
-          // Recreate GLDrawable/GLContext to reflect it's new graphics configuration
-          createDrawableAndContext();
-
-          if(DEBUG) {
-            System.err.println(getThreadName()+": GLCanvas.dispose(true): new drawable: "+drawable);
-          }
-          validateGLDrawable(); // immediate attempt to recreate the drawable
-      }
-    }
-  };
-
-  private final Runnable disposeOnEDTAction = new Runnable() {
+  private final Runnable destroyOnEDTAction = new Runnable() {
     @Override
     public void run() {
         final RecursiveLock _lock = lock;
@@ -896,36 +939,49 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
             final GLAnimatorControl animator =  getAnimator();
 
             if(DEBUG) {
-                System.err.println(getThreadName()+": Info: dispose("+disposeRegenerate+") - START, hasContext " +
+                System.err.println(getThreadName()+": Info: destroyOnEDTAction() - START, hasContext " +
                         (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator);
                 Thread.dumpStack();
             }
-        
-            if(null!=drawable && null!=context) {
-                boolean animatorPaused = false;
-                if(null!=animator) {
-                    // can't remove us from animator for recreational addNotify()
-                    animatorPaused = animator.pause();
-                }
-        
-                if(context.isCreated()) {
-                    helper.disposeGL(GLCanvas.this, drawable, context, postDisposeOnEDTAction);
-                }
-        
-                if(animatorPaused) {
-                    animator.resume();
+                    
+            final boolean animatorPaused;
+            if(null!=animator) {
+                // can't remove us from animator for recreational addNotify()
+                animatorPaused = animator.pause();
+            } else {
+                animatorPaused = false;
+            }
+            
+            // OLS will be detached by disposeGL's context destruction below
+            if( null != context ) {
+                if( context.isCreated() ) {
+                    // Catch dispose GLExceptions by GLEventListener, just 'print' them
+                    // so we can continue with the destruction.
+                    try {
+                        helper.disposeGL(GLCanvas.this, context, true);
+                        if(DEBUG) {
+                            System.err.println(getThreadName()+": destroyOnEDTAction() - post ctx: "+context);
+                        }
+                    } catch (GLException gle) {
+                        gle.printStackTrace();
+                    }
                 }
+                context = null;
             }
-        
-            if(!disposeRegenerate) {
-                if(null != awtConfig) {
-                    AWTEDTExecutor.singleton.invoke(getTreeLock(), true, disposeAbstractGraphicsDeviceActionOnEDT);
+            if( null != drawable ) {
+                drawable.setRealized(false);
+                if(DEBUG) {
+                    System.err.println(getThreadName()+": destroyOnEDTAction() - post drawable: "+drawable);
                 }
-                awtConfig=null;
+                drawable = null;
             }
-        
+
+            if(animatorPaused) {
+                animator.resume();
+            }
+            
             if(DEBUG) {
-                System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - END, "+animator);
+                System.err.println(getThreadName()+": dispose() - END, animator "+animator);
             }
             
         } finally {
@@ -935,28 +991,43 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   };
 
   /**
-   * Disposes the AbstractGraphicsDevice within EDT,
+   * Disposes the JAWTWindow and AbstractGraphicsDevice within EDT,
    * since resources created (X11: Display), must be destroyed in the same thread, where they have been created.
+   * <p>
+   * The drawable and context handle are null'ed as well, assuming {@link #destroy()} has been called already.
+   * </p>
    *
    * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice)
    */
-  private final Runnable disposeAbstractGraphicsDeviceActionOnEDT = new Runnable() {
+  private final Runnable disposeJAWTWindowAndAWTDeviceOnEDT = new Runnable() {
     @Override
     public void run() {
-      if(null != awtConfig) {
-          final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration();
-          final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
-          final String adeviceMsg;
-          if(DEBUG) {
-            adeviceMsg = adevice.toString();
-          } else {
-            adeviceMsg = null;
-          }
-          boolean closed = adevice.close();
-          if(DEBUG) {
-            System.err.println(getThreadName()+": GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed);
-          }
-      }
+        context=null;
+        drawable=null;
+
+        if( null != jawtWindow ) {
+            jawtWindow.destroy();
+            if(DEBUG) {
+                System.err.println(getThreadName()+": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post JAWTWindow: "+jawtWindow);
+            }
+            jawtWindow=null;
+        }
+        
+        if(null != awtConfig) {
+            final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration();
+            final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
+            final String adeviceMsg;
+            if(DEBUG) {
+                adeviceMsg = adevice.toString();
+            } else {
+                adeviceMsg = null;
+            }
+            boolean closed = adevice.close();
+            if(DEBUG) {
+                System.err.println(getThreadName()+": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post GraphicsDevice: "+adeviceMsg+", result: "+closed);
+            }
+        }
+        awtConfig=null;
     }
   };
   
@@ -984,16 +1055,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
     }
   };
 
-  // Workaround for ATI driver bugs related to multithreading issues
-  // like simultaneous rendering via Animators to canvases that are
-  // being resized on the AWT event dispatch thread
   private final Runnable displayOnEDTAction = new Runnable() {
     @Override
     public void run() {
         final RecursiveLock _lock = lock;
         _lock.lock();
-        try {            
-            helper.invokeGL(drawable, context, displayAction, initAction);
+        try {
+            if( null != drawable && drawable.isRealized() ) {
+                helper.invokeGL(drawable, context, displayAction, initAction);
+            }
         } finally {
             _lock.unlock();
         }
@@ -1006,7 +1076,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
         final RecursiveLock _lock = lock;
         _lock.lock();
         try {
-            if(null != drawable) {
+            if( null != drawable && drawable.isRealized() ) {
                 drawable.swapBuffers();
             }
         } finally {
@@ -1015,6 +1085,26 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
     }
   };
 
+  private class DisposeGLEventListenerAction implements Runnable {
+    GLEventListener listener;
+    private boolean remove;
+    private DisposeGLEventListenerAction(GLEventListener listener, boolean remove) {
+        this.listener = listener;
+        this.remove = remove;
+    }
+    
+    @Override
+    public void run() {
+        final RecursiveLock _lock = lock;
+        _lock.lock();
+        try {
+            listener = helper.disposeGLEventListener(GLCanvas.this, drawable, context, listener, remove);
+        } finally {
+            _lock.unlock();
+        }
+    }
+  };
+  
   // Disables the AWT's erasing of this Canvas's background on Windows
   // in Java SE 6. This internal API is not available in previous
   // releases, but the system property
@@ -1076,14 +1166,14 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
    * @param device
    * @return the chosen AWTGraphicsConfiguration
    *
-   * @see #disposeAbstractGraphicsDeviceActionOnEDT
+   * @see #disposeJAWTWindowAndAWTDeviceOnEDT
    */
   private AWTGraphicsConfiguration chooseGraphicsConfiguration(final GLCapabilitiesImmutable capsChosen,
                                                                final GLCapabilitiesImmutable capsRequested,
                                                                final GLCapabilitiesChooser chooser,
                                                                final GraphicsDevice device) {
     // Make GLCanvas behave better in NetBeans GUI builder
-    if (Beans.isDesignTime()) {
+    if( Beans.isDesignTime() ) {
       return null;
     }
 
@@ -1125,9 +1215,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
     return config;
   }
 
-  protected static String getThreadName() {
-    return Thread.currentThread().getName();
-  }
+  protected static String getThreadName() { return Thread.currentThread().getName(); }
 
   /**
    * A most simple JOGL AWT test entry
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index d0b9fb9..b11f359 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -49,11 +49,10 @@ import java.awt.GraphicsEnvironment;
 import java.awt.Rectangle;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferByte;
 import java.awt.image.DataBufferInt;
 import java.beans.Beans;
-import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
+import java.util.List;
 
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.NativeSurface;
@@ -72,7 +71,7 @@ import javax.media.opengl.GLDrawable;
 import javax.media.opengl.GLDrawableFactory;
 import javax.media.opengl.GLEventListener;
 import javax.media.opengl.GLException;
-import javax.media.opengl.GLPbuffer;
+import javax.media.opengl.GLFBODrawable;
 import javax.media.opengl.GLProfile;
 import javax.media.opengl.GLRunnable;
 import javax.media.opengl.Threading;
@@ -84,15 +83,15 @@ import jogamp.opengl.GLDrawableFactoryImpl;
 import jogamp.opengl.GLDrawableHelper;
 import jogamp.opengl.GLDrawableImpl;
 import jogamp.opengl.awt.Java2D;
-import jogamp.opengl.awt.Java2DGLContext;
-
+import jogamp.opengl.util.glsl.GLSLTextureRaster;
 import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
 import com.jogamp.opengl.FBObject;
-import com.jogamp.opengl.util.GLBuffers;
-
-// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
-// context whenever the displayChanged() function is called on their
-// GLEventListeners
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.GLPixelBuffer.SingletonGLPixelBufferProvider;
+import com.jogamp.opengl.util.GLPixelStorageModes;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider;
 
 /** A lightweight Swing component which provides OpenGL rendering
     support. Provided for compatibility with Swing user interfaces
@@ -104,31 +103,91 @@ import com.jogamp.opengl.util.GLBuffers;
     #setOpaque}(false). Pixels with resulting OpenGL alpha values less
     than 1.0 will be overlaid on any underlying Swing rendering. </P>
     <P>
-    Notes specific to the Reference Implementation: This component
-    attempts to use hardware-accelerated rendering via pbuffers and
-    falls back on to software rendering if problems occur.
-    Note that because this component attempts to use pbuffers for
-    rendering, and because pbuffers can not be resized, somewhat
-    surprising behavior may occur during resize operations; the {@link
-    GLEventListener#init} method may be called multiple times as the
-    pbuffer is resized to be able to cover the size of the GLJPanel.
-    This behavior is correct, as the textures and display lists for
-    the GLJPanel will have been lost during the resize operation. The
-    application should attempt to make its GLEventListener.init()
-    methods as side-effect-free as possible. </P>
+    This component attempts to use hardware-accelerated rendering via FBO or pbuffers and
+    falls back on to software rendering if none of the former are available
+    using {@link GLDrawableFactory#createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int) GLDrawableFactory.createOffscreenDrawable(..)}.<br/>
+    </P>
+    <P>
+    In case FBO is used and GLSL is available, a fragment shader is utilized
+    to flip the FBO texture vertically. This hardware-accelerated step can be disabled via system property <code>jogl.gljpanel.noglsl</code>.
+    </P>
+    <P>
+    The OpenGL path is concluded by copying the rendered pixels an {@link BufferedImage} via {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
+    for later Java2D composition.
+    </p>
+    <p>
+    In case the above mentioned GLSL vertical-flipping is not performed,
+    {@link System#arraycopy(Object, int, Object, int, int) System.arraycopy(..)} is used line by line. 
+    This step causes more CPU load per frame and is not hardware-accelerated.
+    </p>
+    <p>
+    Finally the Java2D compositioning takes place via via {@link Graphics#drawImage(java.awt.Image, int, int, int, int, java.awt.image.ImageObserver) Graphics.drawImage(...)}
+    on the prepared {@link BufferedImage} as described above.
+    </p>
     <P>
  *  Please read <A HREF="GLCanvas.html#java2dgl">Java2D OpenGL Remarks</A>.
  *  </P>
 */
 
- at SuppressWarnings({ "serial", "deprecation" })
+ at SuppressWarnings("serial")
 public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol {
   private static final boolean DEBUG = Debug.debug("GLJPanel");
+  private static final boolean DEBUG_VIEWPORT = Debug.isPropertyDefined("jogl.debug.GLJPanel.Viewport", true);
+  private static final boolean USE_GLSL_TEXTURE_RASTERIZER = !Debug.isPropertyDefined("jogl.gljpanel.noglsl", true);    
 
+  /** Indicates whether the Java 2D OpenGL pipeline is requested by user. */
+  private static final boolean java2dOGLEnabledByProp;
+  
+  /** Indicates whether the Java 2D OpenGL pipeline is enabled, resource-compatible and requested by user. */
+  private static final boolean useJava2DGLPipeline;
+  
+  /** Indicates whether the Java 2D OpenGL pipeline's usage is error free. */
+  private static boolean java2DGLPipelineOK;
+  
+  static {
+      boolean enabled = false;
+      final String sVal = System.getProperty("sun.java2d.opengl");
+      if( null != sVal ) {
+          enabled = Boolean.valueOf(sVal);
+      }
+      java2dOGLEnabledByProp = enabled && !Debug.isPropertyDefined("jogl.gljpanel.noogl", true);
+
+      enabled = false;
+      if( java2dOGLEnabledByProp ) {
+          // Force eager initialization of part of the Java2D class since
+          // otherwise it's likely it will try to be initialized while on
+          // the Queue Flusher Thread, which is not allowed
+          if (Java2D.isOGLPipelineResourceCompatible() && Java2D.isFBOEnabled()) {
+              if( null != Java2D.getShareContext(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()) ) {
+                  enabled = true;
+              }
+          }
+      }
+      useJava2DGLPipeline = enabled;
+      java2DGLPipelineOK = enabled;
+      if( DEBUG ) {
+          System.err.println("GLJPanel: java2dOGLEnabledByProp "+java2dOGLEnabledByProp);
+          System.err.println("GLJPanel: useJava2DGLPipeline "+useJava2DGLPipeline);
+          System.err.println("GLJPanel: java2DGLPipelineOK "+java2DGLPipelineOK);
+      }
+  }
+  
+  private static SingleAWTGLPixelBufferProvider singleAWTGLPixelBufferProvider = null;
+  private static synchronized SingleAWTGLPixelBufferProvider getSingleAWTGLPixelBufferProvider() {
+      if( null == singleAWTGLPixelBufferProvider ) {
+          singleAWTGLPixelBufferProvider = new SingleAWTGLPixelBufferProvider( true /* allowRowStride */ );
+      }
+      return singleAWTGLPixelBufferProvider;
+  }
+    
   private GLDrawableHelper helper = new GLDrawableHelper();
   private volatile boolean isInitialized;
 
+  //
   // Data used for either pbuffers or pixmap-based offscreen surfaces
+  //
+  private AWTGLPixelBufferProvider customPixelBufferProvider = null;
+  /** Single buffered offscreen caps */
   private GLCapabilitiesImmutable offscreenCaps;
   private GLProfile             glProfile;
   private GLDrawableFactoryImpl factory;
@@ -136,63 +195,40 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   private GLContext             shareWith;
   private int additionalCtxCreationFlags = 0;
 
-  // Width of the actual GLJPanel
-  private int panelWidth   = 0;
-  private int panelHeight  = 0;
-  // Lazy reshape notification
+  // Lazy reshape notification: reshapeWidth -> panelWidth -> backend.width
   private boolean handleReshape = false;
   private boolean sendReshape = true;
 
-  // The backend in use
-  private Backend backend;
-
-  // Used by all backends either directly or indirectly to hook up callbacks
-  private Updater updater = new Updater();
-
-  // Turns off the pbuffer-based backend (used by default, unless the
-  // Java 2D / OpenGL pipeline is in use)
-  private static boolean hardwareAccelerationDisabled =
-    Debug.isPropertyDefined("jogl.gljpanel.nohw", true);
-
-  // Turns off the fallback to software-based rendering from
-  // pbuffer-based rendering
-  private static boolean softwareRenderingDisabled =
-    Debug.isPropertyDefined("jogl.gljpanel.nosw", true);
-
-  // Indicates whether the Java 2D OpenGL pipeline is enabled
-  private boolean oglPipelineEnabled =
-    Java2D.isOGLPipelineActive() &&
-    !Debug.isPropertyDefined("jogl.gljpanel.noogl", true);
-
-  // For handling reshape events lazily
-  // private int reshapeX;
-  // private int reshapeY;
+  // For handling reshape events lazily: reshapeWidth -> panelWidth -> backend.width
   private int reshapeWidth;
   private int reshapeHeight;
 
+  // Width of the actual GLJPanel: reshapeWidth -> panelWidth -> backend.width
+  private int panelWidth   = 0;
+  private int panelHeight  = 0;
+  
   // These are always set to (0, 0) except when the Java2D / OpenGL
   // pipeline is active
   private int viewportX;
   private int viewportY;
 
+  // The backend in use
+  private volatile Backend backend;
+
+  // Used by all backends either directly or indirectly to hook up callbacks
+  private Updater updater = new Updater();
+
+  private boolean oglPipelineUsable() {
+      return null == customPixelBufferProvider &&  useJava2DGLPipeline && java2DGLPipelineOK;
+  }
+
   private AWTWindowClosingProtocol awtWindowClosingProtocol =
           new AWTWindowClosingProtocol(this, new Runnable() {
                 @Override
                 public void run() {
                     GLJPanel.this.destroy();
                 }
-            });
-
-  static {
-    // Force eager initialization of part of the Java2D class since
-    // otherwise it's likely it will try to be initialized while on
-    // the Queue Flusher Thread, which is not allowed
-    if (Java2D.isOGLPipelineActive() && Java2D.isFBOEnabled()) {
-      Java2D.getShareContext(GraphicsEnvironment.
-                             getLocalGraphicsEnvironment().
-                             getDefaultScreenDevice());
-    }
-  }
+            }, null);
 
   /** Creates a new GLJPanel component with a default set of OpenGL
       capabilities and using the default OpenGL capabilities selection
@@ -248,8 +284,27 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     this.factory = GLDrawableFactoryImpl.getFactoryImpl(glProfile);
     this.chooser = ((chooser != null) ? chooser : new DefaultGLCapabilitiesChooser());
     this.shareWith = shareWith;
+    
+    this.setFocusable(true); // allow keyboard input!
   }
 
+  public AWTGLPixelBufferProvider getCustomPixelBufferProvider() { return customPixelBufferProvider; }
+
+  /**
+   * @param custom custom {@link AWTGLPixelBufferProvider}
+   * @throws IllegalArgumentException if <code>custom</code> is <code>null</code>
+   * @throws IllegalStateException if backend is already realized, i.e. this instanced already painted once.
+   */
+  public void setPixelBufferProvider(AWTGLPixelBufferProvider custom) throws IllegalArgumentException, IllegalStateException {
+      if( null == custom ) {
+          throw new IllegalArgumentException("Null PixelBufferProvider");
+      }
+      if( null != backend ) {
+          throw new IllegalStateException("Backend already realized.");
+      }
+      customPixelBufferProvider = custom;
+  }
+  
   @Override
   public final Object getUpstreamWidget() {
     return this;
@@ -257,17 +312,19 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   
   @Override
   public void display() {
-    if (EventQueue.isDispatchThread()) {
-      // Want display() to be synchronous, so call paintImmediately()
-      paintImmediately(0, 0, getWidth(), getHeight());
-    } else {
-      // Multithreaded redrawing of Swing components is not allowed,
-      // so do everything on the event dispatch thread
-      try {
-        EventQueue.invokeAndWait(paintImmediatelyAction);
-      } catch (Exception e) {
-        throw new GLException(e);
-      }
+    if( isVisible() ) {
+        if (EventQueue.isDispatchThread()) {
+          // Want display() to be synchronous, so call paintImmediately()
+          paintImmediately(0, 0, getWidth(), getHeight());
+        } else {
+          // Multithreaded redrawing of Swing components is not allowed,
+          // so do everything on the event dispatch thread
+          try {
+            EventQueue.invokeAndWait(paintImmediatelyAction);
+          } catch (Exception e) {
+            throw new GLException(e);
+          }
+        }
     }
   }
 
@@ -353,12 +410,15 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     // re-creating it -- tricky to do properly while the context is
     // current
     if (handleReshape) {
-      handleReshape();
+      handleReshape = false;
+      sendReshape = handleReshape();
     }
 
-    updater.setGraphics(g);
-
-    backend.doPaintComponent(g);
+    if( isVisible() ) {
+        updater.setGraphics(g);
+    
+        backend.doPaintComponent(g);
+    }
   }
 
 
@@ -371,6 +431,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   @Override
   public void addNotify() {
     super.addNotify();
+    awtWindowClosingProtocol.addClosingListener();
     if (DEBUG) {
       System.err.println(getThreadName()+": GLJPanel.addNotify()");
     }
@@ -394,12 +455,17 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
       called on all registered {@link GLEventListener}s. Subclasses
       which override this method must call super.reshape() in
       their reshape() method in order to function properly. <P>
-
-      <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
+   *
+   * {@inheritDoc} 
+   */
+  @SuppressWarnings("deprecation")
   @Override
   public void reshape(int x, int y, int width, int height) {
     super.reshape(x, y, width, height);
 
+    if (DEBUG) {
+        System.err.println(getThreadName()+": GLJPanel.reshape: " +reshapeWidth+"x"+reshapeHeight + " -> " + width+"x"+height);
+    }    
     // reshapeX = x;
     // reshapeY = y;
     reshapeWidth = width;
@@ -426,16 +492,48 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   }
 
   @Override
-  public void removeGLEventListener(GLEventListener listener) {
-    helper.removeGLEventListener(listener);
+  public int getGLEventListenerCount() {
+      return helper.getGLEventListenerCount();
   }
 
   @Override
-  public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
-    return helper.removeGLEventListener(index);
-  }       
+  public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException {
+      return helper.getGLEventListener(index);
+  }
+
+  @Override
+  public boolean getGLEventListenerInitState(GLEventListener listener) {
+      return helper.getGLEventListenerInitState(listener);
+  }
+
+  @Override
+  public void setGLEventListenerInitState(GLEventListener listener, boolean initialized) {
+      helper.setGLEventListenerInitState(listener, initialized);
+  }
+   
+  @Override
+  public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove) {
+    final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
+    if (EventQueue.isDispatchThread()) {
+      r.run();
+    } else {
+      // Multithreaded redrawing of Swing components is not allowed,
+      // so do everything on the event dispatch thread
+      try {
+        EventQueue.invokeAndWait(r);
+      } catch (Exception e) {
+        throw new GLException(e);
+      }
+    }
+    return r.listener;
+  }
   
   @Override
+  public GLEventListener removeGLEventListener(GLEventListener listener) {
+    return helper.removeGLEventListener(listener);
+  }
+
+  @Override
   public void setAnimator(GLAnimatorControl animatorControl) {
     helper.setAnimator(animatorControl);
   }
@@ -446,13 +544,32 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   }
 
   @Override
+  public final Thread setExclusiveContextThread(Thread t) throws GLException {
+      return helper.setExclusiveContextThread(t, getContext());
+  }
+
+  @Override
+  public final Thread getExclusiveContextThread() {
+      return helper.getExclusiveContextThread();
+  }
+
+  @Override
   public boolean invoke(boolean wait, GLRunnable glRunnable) {
     return helper.invoke(this, wait, glRunnable);
   }
 
   @Override
+  public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) {
+    return helper.invoke(this, wait, glRunnables);
+  }
+  
+  @Override
   public GLContext createContext(GLContext shareWith) {
-    return (null != backend) ? backend.createContext(shareWith) : null;
+    final Backend b = backend;
+    if ( null == b ) {
+        return null;
+    }
+    return b.createContext(shareWith);
   }
 
   @Override
@@ -465,34 +582,34 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   }
 
   @Override
-  public GLContext setContext(GLContext newCtx) {
-      if (backend == null) {
-          return null;
-      }
-      final GLContext oldCtx = backend.getContext();
-      final boolean newCtxCurrent = GLDrawableHelper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags);
-      backend.setContext(newCtx);
-      if(newCtxCurrent) {
-          newCtx.makeCurrent();
-      }
-      return oldCtx;
+  public GLContext setContext(GLContext newCtx, boolean destroyPrevCtx) {
+    final Backend b = backend;
+    if ( null == b ) {
+        return null;
+    }
+    final GLContext oldCtx = b.getContext();
+    GLDrawableHelper.switchContext(b.getDrawable(), oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
+    b.setContext(newCtx);
+    return oldCtx;
   }
 
 
   @Override
   public final GLDrawable getDelegatedDrawable() {
-    if (backend == null) {
-      return null;
+    final Backend b = backend;
+    if ( null == b ) {
+        return null;
     }
-    return backend.getDrawable();
+    return b.getDrawable();
   }
   
   @Override
   public GLContext getContext() {
-    if (backend == null) {
-      return null;
+    final Backend b = backend;
+    if ( null == b ) {
+        return null;
     }
-    return backend.getContext();
+    return b.getContext();
   }
 
   @Override
@@ -565,12 +682,25 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
       to perform OpenGL rendering using the GLJPanel into the same
       OpenGL drawable as the Swing implementation uses. */
   public boolean shouldPreserveColorBufferIfTranslucent() {
-    return oglPipelineEnabled;
+    return oglPipelineUsable();
   }
 
   @Override
+  public boolean isGLOriented() {
+    final Backend b = backend;
+    if ( null == b ) {
+        return true;
+    }
+    return b.getDrawable().isGLOriented();
+  }
+  
+  @Override
   public GLCapabilitiesImmutable getChosenGLCapabilities() {
-    return backend.getChosenGLCapabilities();
+    final Backend b = backend;
+    if ( null == b ) {
+        return null;
+    }
+    return b.getChosenGLCapabilities();
   }
 
   @Override
@@ -580,12 +710,20 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
 
   @Override
   public NativeSurface getNativeSurface() {
-    throw new GLException("FIXME");
+    final Backend b = backend;
+    if ( null == b ) {
+        return null;
+    }
+    return b.getDrawable().getNativeSurface();
   }
 
   @Override
   public long getHandle() {
-    throw new GLException("FIXME");
+    final Backend b = backend;
+    if ( null == b ) {
+        return 0;
+    }
+    return b.getDrawable().getNativeSurface().getSurfaceHandle();
   }
 
   @Override
@@ -598,15 +736,16 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   //
 
   private void createAndInitializeBackend() {
-    if (panelWidth == 0 ||
-        panelHeight == 0) {
+    if ( 0 >= panelWidth || 0 >= panelHeight ) {
       // See whether we have a non-zero size yet and can go ahead with
       // initialization
-      if (reshapeWidth == 0 ||
-          reshapeHeight == 0) {
-        return;
+      if (0 >= reshapeWidth || 0 >= reshapeHeight ) {
+          return;
       }
 
+      if (DEBUG) {
+          System.err.println(getThreadName()+": GLJPanel.createAndInitializeBackend: " +panelWidth+"x"+panelHeight + " -> " + reshapeWidth+"x"+reshapeHeight);
+      }      
       // Pull down reshapeWidth and reshapeHeight into panelWidth and
       // panelHeight eagerly in order to complete initialization, and
       // force a reshape later
@@ -614,31 +753,18 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
       panelHeight = reshapeHeight;
     }
 
-    do {
-      if (backend == null) {
-        if (oglPipelineEnabled) {
-          backend = new J2DOGLBackend();
+    if ( null == backend ) {
+        if ( oglPipelineUsable() ) {
+            backend = new J2DOGLBackend();
         } else {
-          if (!hardwareAccelerationDisabled &&
-              factory.canCreateGLPbuffer(null)) {
-            backend = new PbufferBackend();
-          } else {
-            if (softwareRenderingDisabled) {
-              throw new GLException("Fallback to software rendering disabled by user");
-            }
-            backend = new SoftwareBackend();
-          }
+            backend = new OffscreenBackend(glProfile, customPixelBufferProvider);
         }
-      }
+        isInitialized = false;
+    }
 
-      if (!isInitialized) {
+    if (!isInitialized) {
         backend.initialize();
-      }
-      // The backend might set itself to null, indicating it punted to
-      // a different implementation -- try again
-    } while (backend == null);
-
-    awtWindowClosingProtocol.addClosingListenerOneShot();
+    }
   }
 
   @Override
@@ -651,18 +777,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
       return awtWindowClosingProtocol.setDefaultCloseOperation(op);
   }
 
-  private void handleReshape() {
+  private boolean handleReshape() {
+    if (DEBUG) {
+      System.err.println(getThreadName()+": GLJPanel.handleReshape: " +panelWidth+"x"+panelHeight + " -> " + reshapeWidth+"x"+reshapeHeight);
+    }    
     panelWidth  = reshapeWidth;
     panelHeight = reshapeHeight;
 
-    if (DEBUG) {
-      System.err.println(getThreadName()+": GLJPanel.handleReshape: (w,h) = (" +
-                         panelWidth + "," + panelHeight + ")");
-    }
-
-    sendReshape = true;
-    backend.handleReshape();
-    handleReshape = false;
+    return backend.handleReshape();
   }
 
   // This is used as the GLEventListener for the pbuffer-based backend
@@ -685,7 +807,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
 
     @Override
     public void dispose(GLAutoDrawable drawable) {
-      helper.dispose(GLJPanel.this);
+      helper.disposeAllGLEventListener(GLJPanel.this, false);
     }
 
     @Override
@@ -716,24 +838,33 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
 
   @Override
   public String toString() {
-    return "AWT-GLJPanel[ "+((null!=backend)?backend.getDrawable().getClass().getName():"null-drawable")+"]";
+    final GLDrawable d = ( null != backend ) ? backend.getDrawable() : null;
+    return "AWT-GLJPanel[ drawableType "+ ( ( null != d ) ? d.getClass().getName() : "null" ) +
+           ", chosenCaps " + getChosenGLCapabilities() +
+           "]";
   }
 
-  private final Runnable postDisposeAction = new Runnable() {
-      @Override
-      public void run() {
-          if (backend != null && !backend.isUsingOwnThreadManagment()) {
-              backend.destroy();
-              backend = null;
-              isInitialized = false;
-          }
-      }
-  };
-
   private final Runnable disposeAction = new Runnable() {
     @Override
     public void run() {
-      helper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction);
+        if ( null != backend ) {
+            final GLContext _context = backend.getContext();
+            final boolean backendDestroy = !backend.isUsingOwnLifecycle();
+            if( null != _context && _context.isCreated() ) {
+                // Catch dispose GLExceptions by GLEventListener, just 'print' them
+                // so we can continue with the destruction.
+                try {
+                    helper.disposeGL(GLJPanel.this, _context, !backendDestroy);
+                } catch (GLException gle) {
+                    gle.printStackTrace();
+                }
+            }
+            if ( backendDestroy ) {
+                backend.destroy();
+                backend = null;
+                isInitialized = false;
+            }
+        }
     }
   };
 
@@ -758,24 +889,30 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     }
   };
 
-  private int getNextPowerOf2(int number) {
-    // Workaround for problems where 0 width or height are transiently
-    // seen during layout
-    if (number == 0) {
-      return 2;
-    }
-    return GLBuffers.getNextPowerOf2(number);
-  }
+  private class DisposeGLEventListenerAction implements Runnable {
+      GLEventListener listener;
+      private boolean remove;
+      private DisposeGLEventListenerAction(GLEventListener listener, boolean remove) {
+          this.listener = listener;
+          this.remove = remove;
+      }
 
+      @Override
+      public void run() {
+          final Backend b = backend;
+          if ( null != b ) {
+              listener = helper.disposeGLEventListener(GLJPanel.this, b.getDrawable(), b.getContext(), listener, remove);
+          }
+      }
+  };
+  
   private int getGLInteger(GL gl, int which) {
     int[] tmp = new int[1];
     gl.glGetIntegerv(which, tmp, 0);
     return tmp[0];
   }
 
-  protected static String getThreadName() {
-    return Thread.currentThread().getName();
-  }
+  protected static String getThreadName() { return Thread.currentThread().getName(); }
 
   //----------------------------------------------------------------------
   // Implementations of the various backends
@@ -786,7 +923,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   // / JOGL bridge
   static interface Backend {
     // Create, Destroy, ..
-    public boolean isUsingOwnThreadManagment();
+    public boolean isUsingOwnLifecycle();
 
     // Called each time the backend needs to initialize itself
     public void initialize();
@@ -819,7 +956,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     // Called to handle a reshape event. When this is called, the
     // OpenGL context associated with the backend is not current, to
     // make it easier to destroy and re-create pbuffers if necessary.
-    public void handleReshape();
+    public boolean handleReshape();
 
     // Called before the OpenGL work is done in init() and display().
     // If false is returned, this render is aborted.
@@ -837,219 +974,134 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   // Base class used by both the software (pixmap) and pbuffer
   // backends, both of which rely on reading back the OpenGL frame
   // buffer and drawing it with a BufferedImage
-  abstract class AbstractReadbackBackend implements Backend {
-    // This image is exactly the correct size to render into the panel
-    protected BufferedImage         offscreenImage;
+  class OffscreenBackend implements Backend {
+    private final AWTGLPixelBufferProvider pixelBufferProvider;
+    private final boolean useSingletonBuffer;
+    private AWTGLPixelBuffer pixelBuffer;
+    
     // One of these is used to store the read back pixels before storing
     // in the BufferedImage
-    protected ByteBuffer            readBackBytes;
-    protected IntBuffer             readBackInts;
-    protected int                   readBackWidthInPixels;
-    protected int                   readBackHeightInPixels;
-
-    private int glFormat;
-    private int glType;
+    protected IntBuffer readBackIntsForCPUVFlip;
 
+    // Implementation using software rendering
+    private GLDrawableImpl offscreenDrawable;
+    private FBObject fboFlipped;
+    private GLSLTextureRaster glslTextureRaster;
+    private final int fboTextureUnit = 0;
+    
+    private GLContextImpl offscreenContext;
+    private boolean flipVertical;          
+    
     // For saving/restoring of OpenGL state during ReadPixels
-    private int[] swapbytes    = new int[1];
-    private int[] rowlength    = new int[1];
-    private int[] skiprows     = new int[1];
-    private int[] skippixels   = new int[1];
-    private int[] alignment    = new int[1];
-
-    @Override
-    public void setOpaque(boolean opaque) {
-      if (opaque != isOpaque()) {
-        if (offscreenImage != null) {
-          offscreenImage.flush();
-          offscreenImage = null;
-        }
-      }
-    }
-
-    @Override
-    public boolean preGL(Graphics g) {
-      // Empty in this implementation
-      return true;
-    }
-
-    @Override
-    public void postGL(Graphics g, boolean isDisplay) {
-      if (isDisplay) {
-        // Must now copy pixels from offscreen context into surface
-        if (offscreenImage == null) {
-          if (panelWidth > 0 && panelHeight > 0) {
-            // It looks like NVidia's drivers (at least the ones on my
-            // notebook) are buggy and don't allow a sub-rectangle to be
-            // read from a pbuffer...this doesn't really matter because
-            // it's the Graphics.drawImage() calls that are the
-            // bottleneck
-
-            int awtFormat = 0;
-
-            // Should be more flexible in these BufferedImage formats;
-            // perhaps see what the preferred image types are on the
-            // given platform
-            if (isOpaque()) {
-              awtFormat = BufferedImage.TYPE_INT_RGB;
-            } else {
-              awtFormat = BufferedImage.TYPE_INT_ARGB;
-            }
+    private final GLPixelStorageModes psm =  new GLPixelStorageModes();
 
-            offscreenImage = new BufferedImage(panelWidth,
-                                               panelHeight,
-                                               awtFormat);
-            switch (awtFormat) {
-            case BufferedImage.TYPE_3BYTE_BGR:
-              glFormat = GL2.GL_BGR;
-              glType   = GL.GL_UNSIGNED_BYTE;
-              readBackBytes = ByteBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels * 3);
-              break;
-
-            case BufferedImage.TYPE_INT_RGB:
-            case BufferedImage.TYPE_INT_ARGB:
-              glFormat = GL.GL_BGRA;
-              glType   = getGLPixelType();
-              readBackInts = IntBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels);
-              break;
-
-            default:
-              // FIXME: Support more off-screen image types (current
-              // offscreen context implementations don't use others, and
-              // some of the OpenGL formats aren't supported in the 1.1
-              // headers, which we're currently using)
-              throw new GLException("Unsupported offscreen image type " + awtFormat);
-            }
-          }
+    OffscreenBackend(GLProfile glp, AWTGLPixelBufferProvider custom) {
+        if(null == custom) {
+            pixelBufferProvider = glp.isGL2GL3() ? getSingleAWTGLPixelBufferProvider() :
+                                                   new AWTGLPixelBufferProvider( false /* allowRowStride */ ) ;
+        } else {
+            pixelBufferProvider = custom;
         }
-
-        if (offscreenImage != null) {
-          GL2 gl = getGL().getGL2();
-          // Save current modes
-          gl.glGetIntegerv(GL2.GL_PACK_SWAP_BYTES,    swapbytes, 0);
-          gl.glGetIntegerv(GL2.GL_PACK_ROW_LENGTH,    rowlength, 0);
-          gl.glGetIntegerv(GL2.GL_PACK_SKIP_ROWS,     skiprows, 0);
-          gl.glGetIntegerv(GL2.GL_PACK_SKIP_PIXELS,   skippixels, 0);
-          gl.glGetIntegerv(GL2.GL_PACK_ALIGNMENT,     alignment, 0);
-
-          gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES,    GL.GL_FALSE);
-          gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH,    readBackWidthInPixels);
-          gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS,     0);
-          gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS,   0);
-          gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT,     1);
-
-          // Actually read the pixels.
-          gl.glReadBuffer(GL2.GL_FRONT);
-          if (readBackBytes != null) {
-            gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackBytes);
-          } else if (readBackInts != null) {
-            gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackInts);
-          }
-
-          // Restore saved modes.
-          gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES,  swapbytes[0]);
-          gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH,  rowlength[0]);
-          gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS,   skiprows[0]);
-          gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, skippixels[0]);
-          gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT,   alignment[0]);
-
-          if (readBackBytes != null || readBackInts != null) {
-            // Copy temporary data into raster of BufferedImage for faster
-            // blitting Note that we could avoid this copy in the cases
-            // where !offscreenContext.offscreenImageNeedsVerticalFlip(),
-            // but that's the software rendering path which is very slow
-            // anyway
-            Object src  = null;
-            Object dest = null;
-            int    srcIncr  = 0;
-            int    destIncr = 0;
-
-            if (readBackBytes != null) {
-              src = readBackBytes.array();
-              dest = ((DataBufferByte) offscreenImage.getRaster().getDataBuffer()).getData();
-              srcIncr = readBackWidthInPixels * 3;
-              destIncr = offscreenImage.getWidth() * 3;
-            } else {
-              src = readBackInts.array();
-              dest = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData();
-              srcIncr = readBackWidthInPixels;
-              destIncr = offscreenImage.getWidth();
-            }
-
-            if (flipVertically()) {
-              int srcPos = 0;
-              int destPos = (offscreenImage.getHeight() - 1) * destIncr;
-              for (; destPos >= 0; srcPos += srcIncr, destPos -= destIncr) {
-                System.arraycopy(src, srcPos, dest, destPos, destIncr);
-              }
-            } else {
-              int srcPos = 0;
-              int destEnd = destIncr * offscreenImage.getHeight();
-              for (int destPos = 0; destPos < destEnd; srcPos += srcIncr, destPos += destIncr) {
-                System.arraycopy(src, srcPos, dest, destPos, destIncr);
-              }
-            }
-
-            // Note: image will be drawn back in paintComponent() for
-            // correctness on all platforms
-          }
+        if( pixelBufferProvider instanceof SingletonGLPixelBufferProvider ) {
+            useSingletonBuffer = true;
+        } else {
+            useSingletonBuffer = false;
         }
-      }
     }
-
+    
     @Override
-    public void doPaintComponent(Graphics g) {
-      doPaintComponentImpl();
-      if (offscreenImage != null) {
-        // Draw resulting image in one shot
-        g.drawImage(offscreenImage, 0, 0,
-                    offscreenImage.getWidth(),
-                    offscreenImage.getHeight(),
-                    GLJPanel.this);
-      }
-    }
-
-    protected abstract void    doPaintComponentImpl();
-    protected abstract int     getGLPixelType();
-    protected abstract boolean flipVertically();
-  }
-
-  class SoftwareBackend extends AbstractReadbackBackend {
-    // Implementation using software rendering
-    private GLDrawableImpl offscreenDrawable;
-    private GLContextImpl offscreenContext;
-
-    @Override
-    public boolean isUsingOwnThreadManagment() { return false; }
+    public boolean isUsingOwnLifecycle() { return false; }
 
     @Override
     public void initialize() {
       if(DEBUG) {
-          System.err.println(getThreadName()+": SoftwareBackend: initialize()");
+          System.err.println(getThreadName()+": OffscreenBackend: initialize()");
+      }
+      try {
+          offscreenDrawable = (GLDrawableImpl) factory.createOffscreenDrawable(
+                                                    null /* default platform device */,
+                                                    offscreenCaps,
+                                                    chooser,
+                                                    panelWidth, panelHeight);
+          offscreenDrawable.setRealized(true);
+          offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith);
+          offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
+          if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
+              isInitialized = true;
+              final GL gl = offscreenContext.getGL();
+              flipVertical = offscreenDrawable.isGLOriented();
+              final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities();
+              if( USE_GLSL_TEXTURE_RASTERIZER && chosenCaps.isFBO() && flipVertical && gl.isGL2ES2() ) {
+                  final boolean _autoSwapBufferMode = helper.getAutoSwapBufferMode();
+                  helper.setAutoSwapBufferMode(false);
+                  final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable;
+                  try {
+                      fboFlipped = new FBObject();
+                      fboFlipped.reset(gl, fboDrawable.getWidth(), fboDrawable.getHeight(), 0, false);
+                      fboFlipped.attachTexture2D(gl, 0, chosenCaps.getAlphaBits()>0);
+                      // fboFlipped.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+                      glslTextureRaster = new GLSLTextureRaster(fboTextureUnit, true);
+                      glslTextureRaster.init(gl.getGL2ES2());
+                      glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, fboDrawable.getWidth(), fboDrawable.getHeight());
+                  } catch (Exception ex) {
+                      ex.printStackTrace();
+                      if(null != glslTextureRaster) {
+                        glslTextureRaster.dispose(gl.getGL2ES2());
+                        glslTextureRaster = null;
+                      }
+                      if(null != fboFlipped) {
+                        fboFlipped.destroy(gl);
+                        fboFlipped = null;
+                      }
+                      helper.setAutoSwapBufferMode(_autoSwapBufferMode);
+                  }
+              } else {
+                  fboFlipped = null;
+                  glslTextureRaster = null;
+              }          
+              offscreenContext.release();
+          } else {
+              isInitialized = false;
+          }          
+      } finally {
+          if( !isInitialized ) {
+              if(null != offscreenContext) {
+                  offscreenContext.destroy();
+                  offscreenContext = null;
+              }
+              if(null != offscreenDrawable) {
+                  offscreenDrawable.setRealized(false);
+                  offscreenDrawable = null;
+              }
+          }
       }
-      // Fall-through path: create an offscreen context instead
-      offscreenDrawable = (GLDrawableImpl) factory.createOffscreenDrawable(
-                                                null /* default platform device */,
-                                                offscreenCaps,
-                                                chooser,
-                                                Math.max(1, panelWidth),
-                                                Math.max(1, panelHeight));
-      offscreenDrawable.setRealized(true);
-      offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith);
-      offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
-
-      isInitialized = true;
     }
 
     @Override
     public void destroy() {
       if(DEBUG) {
-          System.err.println(getThreadName()+": SoftwareBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable));
+          System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable));
       }
-      if (offscreenContext != null) {
-        offscreenContext.destroy();
-        offscreenContext = null;
+      if ( null != offscreenContext && offscreenContext.isCreated() ) {
+        if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {            
+            try {
+                final GL gl = offscreenContext.getGL();
+                if(null != glslTextureRaster) {
+                    glslTextureRaster.dispose(gl.getGL2ES2());
+                }
+                if(null != fboFlipped) {
+                    fboFlipped.destroy(gl);
+                }
+            } finally {
+                offscreenContext.destroy();
+            }
+        }
       }
+      offscreenContext = null;
+      glslTextureRaster = null;
+      fboFlipped = null;
+      offscreenContext = null;
+      
       if (offscreenDrawable != null) {
         final AbstractGraphicsDevice adevice = offscreenDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
         offscreenDrawable.setRealized(false);
@@ -1058,237 +1110,228 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
             adevice.close();
         }
       }
+      
+      if( null != readBackIntsForCPUVFlip ) { 
+          readBackIntsForCPUVFlip.clear();
+          readBackIntsForCPUVFlip = null;
+      }
+      if( null != pixelBuffer ) {
+          if( !useSingletonBuffer ) {
+              pixelBuffer.dispose();
+          }
+          pixelBuffer = null;
+      }
     }
 
     @Override
-    public GLContext createContext(GLContext shareWith) {
-      return (null != offscreenDrawable) ? offscreenDrawable.createContext(shareWith) : null;
+    public void setOpaque(boolean opaque) {
+      if ( opaque != isOpaque() && !useSingletonBuffer ) {
+          pixelBuffer.dispose();
+          pixelBuffer = null;
+      }
     }
 
     @Override
-    public void setContext(GLContext ctx) {
-      offscreenContext=(GLContextImpl)ctx;
+    public boolean preGL(Graphics g) {
+      // Empty in this implementation
+      return true;
     }
 
     @Override
-    public GLContext getContext() {
-      return offscreenContext;
-    }
+    public void postGL(Graphics g, boolean isDisplay) {
+      if (isDisplay) {
+        final GL gl = offscreenContext.getGL();
+
+        final int componentCount;
+        final int alignment;
+        if( isOpaque() ) {
+            // w/o alpha
+            componentCount = 3;
+            alignment = 1;
+        } else {
+            // with alpha
+            componentCount = 4;
+            alignment = 4;
+        }
+        
+        final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);        
+        
+        if( useSingletonBuffer ) { // attempt to fetch the latest AWTGLPixelBuffer             
+            pixelBuffer = (AWTGLPixelBuffer) ((SingletonGLPixelBufferProvider)pixelBufferProvider).getSingleBuffer(pixelAttribs);
+        }
+        if( null != pixelBuffer && pixelBuffer.requiresNewBuffer(gl, panelWidth, panelHeight, 0) ) {
+            pixelBuffer.dispose();
+            pixelBuffer = null;
+        }
+        if ( null == pixelBuffer ) {
+          if (0 >= panelWidth || 0 >= panelHeight ) {
+              return;
+          }          
+          pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, panelWidth, panelHeight, 1, true, 0);
+          if(DEBUG) {
+              System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: pixelBufferProvider isSingletonBufferProvider "+useSingletonBuffer+", 0x"+Integer.toHexString(pixelBufferProvider.hashCode())+", "+pixelBufferProvider.getClass().getSimpleName());
+              System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: pixelBuffer 0x"+Integer.toHexString(pixelBuffer.hashCode())+", "+pixelBuffer+", alignment "+alignment);
+              System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: flippedVertical "+flipVertical+", glslTextureRaster "+(null!=glslTextureRaster));
+              System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: panelSize "+panelWidth+"x"+panelHeight);
+          }
+        }
+        final IntBuffer readBackInts;
+        
+        if( !flipVertical || null != glslTextureRaster ) {
+           readBackInts = (IntBuffer) pixelBuffer.buffer;
+        } else {
+           if( null == readBackIntsForCPUVFlip || pixelBuffer.width * pixelBuffer.height > readBackIntsForCPUVFlip.remaining() ) {
+               readBackIntsForCPUVFlip = IntBuffer.allocate(pixelBuffer.width * pixelBuffer.height);
+           }
+           readBackInts = readBackIntsForCPUVFlip;
+        }
 
-    @Override
-    public GLDrawable getDrawable() {
-        return offscreenDrawable;
-    }
+        if( DEBUG_VIEWPORT ) {
+            int[] vp = new int[] { 0, 0, 0, 0 };
+            gl.glGetIntegerv(GL.GL_VIEWPORT, vp, 0);
+            System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL: Viewport: "+vp[0]+"/"+vp[1]+" "+vp[2]+"x"+vp[3]);
+        }
+        
+        // Must now copy pixels from offscreen context into surface
+        
+        // Save current modes
+        psm.setAlignment(gl, alignment, alignment);
+        if(gl.isGL2GL3()) {
+            final GL2GL3 gl2gl3 = gl.getGL2GL3();
+            gl2gl3.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, pixelBuffer.width);
+            gl2gl3.glReadBuffer(gl2gl3.getDefaultReadBuffer());
+        }
 
-    @Override
-    public GLCapabilitiesImmutable getChosenGLCapabilities() {
-      if (offscreenDrawable == null) {
-        return null;
-      }
-      return offscreenDrawable.getChosenGLCapabilities();
-    }
+        if(null != glslTextureRaster) { // implies flippedVertical
+            // perform vert-flipping via OpenGL/FBO        
+            final GLFBODrawable fboDrawable = (GLFBODrawable)offscreenDrawable;
+            final FBObject.TextureAttachment fboTex = fboDrawable.getTextureBuffer(GL.GL_FRONT);
+            
+            fboDrawable.swapBuffers();
+            fboFlipped.bind(gl);
+            
+            // gl.glActiveTexture(fboDrawable.getTextureUnit()); // implicit!
+            gl.glBindTexture(GL.GL_TEXTURE_2D, fboTex.getName());
+            // gl.glClear(GL.GL_DEPTH_BUFFER_BIT); // fboFlipped runs w/o DEPTH!
+            glslTextureRaster.display(gl.getGL2ES2());
+            gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
+
+            fboFlipped.unbind(gl);
+        } else {
+            gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
+            
+            if ( flipVertical ) {
+                // Copy temporary data into raster of BufferedImage for faster
+                // blitting Note that we could avoid this copy in the cases
+                // where !offscreenDrawable.isGLOriented(),
+                // but that's the software rendering path which is very slow anyway.
+                final BufferedImage image = pixelBuffer.image;
+                final int[] src = readBackInts.array();
+                final int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+                final int incr = pixelBuffer.width;
+                int srcPos = 0;
+                int destPos = (panelHeight - 1) * pixelBuffer.width;
+                for (; destPos >= 0; srcPos += incr, destPos -= incr) {
+                  System.arraycopy(src, srcPos, dest, destPos, incr);
+                }
+            }
+        }
 
-    @Override
-    public GLProfile getGLProfile() {
-      if (offscreenDrawable == null) {
-        return null;
-      }
-      return offscreenDrawable.getGLProfile();
-    }
+        // Restore saved modes.
+        psm.restore(gl);
 
-    @Override
-    public void handleReshape() {
-      destroy();
-      initialize();
-      readBackWidthInPixels  = Math.max(1, panelWidth);
-      readBackHeightInPixels = Math.max(1, panelHeight);
-
-      if (offscreenImage != null) {
-        offscreenImage.flush();
-        offscreenImage = null;
+        // Note: image will be drawn back in paintComponent() for
+        // correctness on all platforms
       }
     }
 
     @Override
-    protected void doPaintComponentImpl() {
+    public void doPaintComponent(Graphics g) {
       helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
+      
+      if ( null != pixelBuffer ) {
+        final BufferedImage image = pixelBuffer.image;
+        // Draw resulting image in one shot
+        g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null); // Null ImageObserver since image data is ready.
+      }
     }
 
     @Override
-    protected int getGLPixelType() {
-      return offscreenContext.getOffscreenContextPixelDataType();
-    }
-
-    @Override
-    protected boolean flipVertically() {
-      return offscreenContext.offscreenImageNeedsVerticalFlip();
-    }
-  }
-
-  class PbufferBackend extends AbstractReadbackBackend {
-    private GLPbuffer pbuffer;
-    private int       pbufferWidth  = 256;
-    private int       pbufferHeight = 256;
-
-    @Override
-    public boolean isUsingOwnThreadManagment() { return false; }
-
-    @Override
-    public void initialize() {
-      if (pbuffer != null) {
-        throw new InternalError("Creating pbuffer twice without destroying it (memory leak / correctness bug)");
-      }
-      if(DEBUG) {
-          System.err.println(getThreadName()+": PbufferBackend: initialize()");
-      }
-      try {
-        pbuffer = factory.createGLPbuffer(null /* default platform device */,
-                                          offscreenCaps,
-                                          null,
-                                          pbufferWidth,
-                                          pbufferHeight,
-                                          shareWith);
-        pbuffer.setContextCreationFlags(additionalCtxCreationFlags);
-        pbuffer.addGLEventListener(updater);
-        isInitialized = true;
-      } catch (GLException e) {
+    public boolean handleReshape() {
+        /** FIXME: Shall we utilize such resize optimization (snippet kept alive from removed pbuffer backend) ?
+        // Use factor larger than 2 during shrinks for some hysteresis
+        float shrinkFactor = 2.5f;
+        if ( (panelWidth > readBackWidthInPixels)                  || (panelHeight > readBackHeightInPixels) ||
+             (panelWidth < (readBackWidthInPixels / shrinkFactor)) || (panelHeight < (readBackHeightInPixels / shrinkFactor))) {
+            if (DEBUG) {
+                System.err.println(getThreadName()+": Resizing offscreen from (" + readBackWidthInPixels + ", " + readBackHeightInPixels + ") " +
+                        " to fit (" + panelWidth + ", " + panelHeight + ")");
+            }
+        } */
+        
+        GLDrawableImpl _drawable = offscreenDrawable;
+        {
+            final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, offscreenContext, panelWidth, panelHeight);
+            if(_drawable != _drawableNew) {
+                // write back 
+                _drawable = _drawableNew;
+                offscreenDrawable = _drawableNew;
+            }
+        }
         if (DEBUG) {
-          e.printStackTrace();
-          System.err.println(getThreadName()+": GLJPanel: Falling back on software rendering because of problems creating pbuffer");
+            System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.handleReshape: " +panelWidth+"x"+panelHeight + " -> " + _drawable.getWidth()+"x"+_drawable.getHeight());
         }
-        hardwareAccelerationDisabled = true;
-        backend = null;
-        isInitialized = false;
-        createAndInitializeBackend();
-      }
-    }
-
-    @Override
-    public void destroy() {
-      if(DEBUG) {
-          System.err.println(getThreadName()+": PbufferBackend: destroy() - pbuffer: "+(null!=pbuffer));
-      }
-      if (pbuffer != null) {
-        pbuffer.destroy();
-        pbuffer = null;
-      }
+        panelWidth = _drawable.getWidth();
+        panelHeight = _drawable.getHeight();
+        
+        if( null != glslTextureRaster ) {
+            if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {            
+                try {
+                    final GL gl = offscreenContext.getGL();
+                    fboFlipped.reset(gl, _drawable.getWidth(), _drawable.getHeight(), 0, false);
+                    glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, _drawable.getWidth(), _drawable.getHeight());
+                } finally {
+                    offscreenContext.release();
+                }
+            }
+        }
+        return _drawable.isRealized();
     }
-
+    
     @Override
     public GLContext createContext(GLContext shareWith) {
-      return (null != pbuffer) ? pbuffer.createContext(shareWith) : null;
+      return (null != offscreenDrawable) ? offscreenDrawable.createContext(shareWith) : null;
     }
 
     @Override
     public void setContext(GLContext ctx) {
-      if (pbuffer == null || Beans.isDesignTime()) {
-        return;
-      }
-      pbuffer.setContext(ctx);
+      offscreenContext=(GLContextImpl)ctx;
     }
 
     @Override
     public GLContext getContext() {
-      // Workaround for crashes in NetBeans GUI builder
-      if (null == pbuffer || Beans.isDesignTime()) {
-        return null;
-      }
-      return pbuffer.getContext();
+      return offscreenContext;
     }
 
     @Override
     public GLDrawable getDrawable() {
-        return pbuffer;
+        return offscreenDrawable;
     }
 
     @Override
     public GLCapabilitiesImmutable getChosenGLCapabilities() {
-      if (pbuffer == null) {
+      if (offscreenDrawable == null) {
         return null;
       }
-      return pbuffer.getChosenGLCapabilities();
+      return offscreenDrawable.getChosenGLCapabilities();
     }
 
     @Override
     public GLProfile getGLProfile() {
-      if (pbuffer == null) {
+      if (offscreenDrawable == null) {
         return null;
       }
-      return pbuffer.getGLProfile();
-    }
-
-    @Override
-    public void handleReshape() {
-      // Use factor larger than 2 during shrinks for some hysteresis
-      float shrinkFactor = 2.5f;
-      if ((panelWidth > pbufferWidth)                  || (panelHeight > pbufferHeight) ||
-          (panelWidth < (pbufferWidth / shrinkFactor)) || (panelHeight < (pbufferHeight / shrinkFactor))) {
-        if (DEBUG) {
-          System.err.println(getThreadName()+": Resizing pbuffer from (" + pbufferWidth + ", " + pbufferHeight + ") " +
-                             " to fit (" + panelWidth + ", " + panelHeight + ")");
-        }
-        // Must destroy and recreate pbuffer to fit
-        if (pbuffer != null) {
-          // Watch for errors during pbuffer destruction (due to
-          // buggy / bad OpenGL drivers, in particular SiS) and fall
-          // back to software rendering
-          try {
-            pbuffer.destroy();
-          } catch (GLException e) {
-            hardwareAccelerationDisabled = true;
-            backend = null;
-            isInitialized = false;
-            // Just disabled hardware acceleration during this resize operation; do a fixup
-            readBackWidthInPixels  = Math.max(1, panelWidth);
-            readBackHeightInPixels = Math.max(1, panelHeight);
-            if (DEBUG) {
-              System.err.println(getThreadName()+": Warning: falling back to software rendering due to bugs in OpenGL drivers");
-              e.printStackTrace();
-            }
-            createAndInitializeBackend();
-            return;
-          }
-        }
-        pbuffer = null;
-        isInitialized = false;
-        pbufferWidth = getNextPowerOf2(panelWidth);
-        pbufferHeight = getNextPowerOf2(panelHeight);
-        if (DEBUG && !hardwareAccelerationDisabled) {
-          System.err.println(getThreadName()+": New pbuffer size is (" + pbufferWidth + ", " + pbufferHeight + ")");
-        }
-        initialize();
-      }
-
-      // It looks like NVidia's drivers (at least the ones on my
-      // notebook) are buggy and don't allow a rectangle of less than
-      // the pbuffer's width to be read...this doesn't really matter
-      // because it's the Graphics.drawImage() calls that are the
-      // bottleneck. Should probably make the size of the offscreen
-      // image be the exact size of the pbuffer to save some work on
-      // resize operations...
-      readBackWidthInPixels  = pbufferWidth;
-      readBackHeightInPixels = panelHeight;
-
-      if (offscreenImage != null) {
-        offscreenImage.flush();
-        offscreenImage = null;
-      }
-    }
-
-    @Override
-    protected void doPaintComponentImpl() {
-      pbuffer.display();
-    }
-
-    @Override
-    protected int getGLPixelType() {
-      // This seems to be a good choice on all platforms
-      return GL2.GL_UNSIGNED_INT_8_8_8_8_REV;
-    }
-
-    @Override
-    protected boolean flipVertically() {
-      return true;
+      return offscreenDrawable.getGLProfile();
     }
   }
 
@@ -1342,7 +1385,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     private GraphicsConfiguration workaroundConfig;
 
     @Override
-    public boolean isUsingOwnThreadManagment() { return true; }
+    public boolean isUsingOwnLifecycle() { return true; }
 
     @Override
     public void initialize() {
@@ -1415,8 +1458,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     }
 
     @Override
-    public void handleReshape() {
+    public boolean handleReshape() {
       // Empty in this implementation
+      return true;
     }
 
     @Override
@@ -1561,7 +1605,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
       // Cause OpenGL pipeline to flush its results because
       // otherwise it's possible we will buffer up multiple frames'
       // rendering results, resulting in apparent mouse lag
-      GL gl = getGL();
+      GL gl = joglContext.getGL();
       gl.glFinish();
 
       if (Java2D.isFBOEnabled() &&
@@ -1652,7 +1696,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
                 }
                 isInitialized = false;
                 backend = null;
-                oglPipelineEnabled = false;
+                java2DGLPipelineOK = false;
                 handleReshape = true;
                 j2dContext.destroy();
                 j2dContext = null;
@@ -1706,28 +1750,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
                         System.err.println("-- Created External Drawable: "+joglDrawable);
                         System.err.println("-- Created Context: "+joglContext);
                     }
-                  } else if (factory.canCreateContextOnJava2DSurface(device)) {
-                    // Mac OS X code path
-                    joglContext = factory.createContextOnJava2DSurface(g, j2dContext);
-                    if (DEBUG) {
-                        System.err.println("-- Created Context: "+joglContext);
-                    }
                   }
-                  /*if (DEBUG) {
-                    joglContext.setGL(new DebugGL2(joglContext.getGL().getGL2()));
-                  }*/
-
                   if (Java2D.isFBOEnabled() &&
                       Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT &&
                       fbObjectWorkarounds) {
                     createNewDepthBuffer = true;
                   }
                 }
-                if (joglContext instanceof Java2DGLContext) {
-                  // Mac OS X code path
-                  ((Java2DGLContext) joglContext).setGraphics(g);
-                }
-
                 helper.invokeGL(joglDrawable, joglContext, updaterDisplayAction, updaterInitAction);
               }
             } finally {
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/RegionFactory.java b/src/jogl/classes/jogamp/graph/curve/opengl/RegionFactory.java
old mode 100755
new mode 100644
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/RegionRendererImpl01.java b/src/jogl/classes/jogamp/graph/curve/opengl/RegionRendererImpl01.java
old mode 100755
new mode 100644
index 2884aca..7f5afcd
--- a/src/jogl/classes/jogamp/graph/curve/opengl/RegionRendererImpl01.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/RegionRendererImpl01.java
@@ -46,22 +46,25 @@ public class RegionRendererImpl01 extends RegionRenderer {
         
     }
     
-    @Override
-    protected String getFragmentShaderName(GL2ES2 gl) {
-        final String type = Region.isNonUniformWeight(renderModes) ? "02" : "01" ;
-        final String pass = Region.isVBAA(renderModes) ? "b" : "a" ;
-        return "curverenderer" + type + pass + getShaderGLVersionSuffix(gl);
-    }
-    
     protected boolean initShaderProgram(GL2ES2 gl) {
         final ShaderState st = rs.getShaderState();
         
-        ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RegionRendererImpl01.class, "shader",
-                "shader/bin", getVertexShaderName(gl), false);
-        ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RegionRendererImpl01.class, "shader",
-                "shader/bin", getFragmentShaderName(gl), false);
-    
-        ShaderProgram sp = new ShaderProgram();
+        final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RegionRendererImpl01.class, "shader",
+                                                  "shader/bin", getVertexShaderName(), true);
+        final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RegionRendererImpl01.class, "shader",
+                                                  "shader/bin", getFragmentShaderName(), true);
+        rsVp.defaultShaderCustomization(gl, true, true);
+        // rsFp.defaultShaderCustomization(gl, true, true);
+        int pos = rsFp.addGLSLVersion(gl);
+        if( gl.isGLES2() ) {
+            pos = rsFp.insertShaderSource(0, pos, ShaderCode.extOESDerivativesEnable);            
+        }
+        final String rsFpDefPrecision =  getFragmentShaderPrecision(gl);
+        if( null != rsFpDefPrecision ) {
+            rsFp.insertShaderSource(0, pos, rsFpDefPrecision);
+        }
+        
+        final ShaderProgram sp = new ShaderProgram();
         sp.add(rsVp);
         sp.add(rsFp);
 
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/TextRendererImpl01.java b/src/jogl/classes/jogamp/graph/curve/opengl/TextRendererImpl01.java
index 0cf424c..81c4213 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/TextRendererImpl01.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/TextRendererImpl01.java
@@ -49,12 +49,22 @@ public class TextRendererImpl01 extends TextRenderer {
     protected boolean initShaderProgram(GL2ES2 gl){
         final ShaderState st = rs.getShaderState();
 
-        ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TextRendererImpl01.class, "shader",
-                "shader/bin", getVertexShaderName(gl), false);
-        ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TextRendererImpl01.class, "shader",
-                "shader/bin", getFragmentShaderName(gl), false);
+        final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TextRendererImpl01.class, "shader",
+                                                  "shader/bin", getVertexShaderName(), true);
+        final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TextRendererImpl01.class, "shader",
+                                                  "shader/bin", getFragmentShaderName(), true);
+        rsVp.defaultShaderCustomization(gl, true, true);
+        // rsFp.defaultShaderCustomization(gl, true, true);
+        int pos = rsFp.addGLSLVersion(gl);
+        if( gl.isGLES2() ) {
+            pos = rsFp.insertShaderSource(0, pos, ShaderCode.extOESDerivativesEnable);
+        }
+        final String rsFpDefPrecision =  getFragmentShaderPrecision(gl);
+        if( null != rsFpDefPrecision ) {
+            rsFp.insertShaderSource(0, pos, rsFpDefPrecision);
+        }
         
-        ShaderProgram sp = new ShaderProgram();
+        final ShaderProgram sp = new ShaderProgram();
         sp.add(rsVp);
         sp.add(rsFp);
         
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-xxx.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-1pass-weight.fp
similarity index 87%
rename from src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-xxx.fp
rename to src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-1pass-weight.fp
index d31bafb..7643dab 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-xxx.fp
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-1pass-weight.fp
@@ -4,6 +4,13 @@
 // 1-pass shader w/ weight
 //
 
+#if __VERSION__ >= 130
+  #define varying in
+  out vec4 mgl_FragColor;
+#else
+  #define mgl_FragColor gl_FragColor
+#endif
+
 #include uniforms.glsl
 #include varyings.glsl
 
@@ -44,5 +51,5 @@ void main (void)
         }
     }
 
-    gl_FragColor = vec4(c, alpha);
+    mgl_FragColor = vec4(c, alpha);
 }
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-xxx.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-1pass.fp
similarity index 88%
rename from src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-xxx.fp
rename to src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-1pass.fp
index f3a88ad..e12eef4 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-xxx.fp
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-1pass.fp
@@ -4,6 +4,13 @@
 // 1-pass shader w/o weight
 //
 
+#if __VERSION__ >= 130
+  #define varying in
+  out vec4 mgl_FragColor;
+#else
+  #define mgl_FragColor gl_FragColor
+#endif
+
 #include uniforms.glsl
 #include varyings.glsl
 
@@ -38,5 +45,5 @@ void main (void)
         }
     }
     
-    gl_FragColor = vec4(c, alpha);
+    mgl_FragColor = vec4(c, alpha);
 }
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-xxx.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass-weight.fp
similarity index 90%
rename from src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-xxx.fp
rename to src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass-weight.fp
index be73849..06edbea 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-xxx.fp
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass-weight.fp
@@ -4,6 +4,13 @@
 // 2-pass shader w/ weight
 //
 
+#if __VERSION__ >= 130
+  #define varying in
+  out vec4 mgl_FragColor;
+#else
+  #define mgl_FragColor gl_FragColor
+#endif
+
 #include uniforms.glsl
 #include varyings.glsl
 
@@ -48,10 +55,11 @@ void main (void)
         t += texture2D(gcu_TextureUnit, rtex + 4.0*size*(vec2(0, 1)))*tex_weights.w;
         t += texture2D(gcu_TextureUnit, rtex - 4.0*size*(vec2(0, 1)))*tex_weights.w;
         
-        /** discard freezes NV tegra2 compiler
+        #if 0
         if(t.w == 0.0) {
-            discard;
-        } */
+            discard; // discard freezes NV tegra2 compiler
+        }
+        #endif
         
         c = t.xyz;
         alpha = gcu_Alpha * t.w;
@@ -84,5 +92,5 @@ void main (void)
         }
     }
 
-    gl_FragColor = vec4(c, alpha);
+    mgl_FragColor = vec4(c, alpha);
 }
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-xxx.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass.fp
similarity index 92%
rename from src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-xxx.fp
rename to src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass.fp
index 879e41e..07a0057 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-xxx.fp
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-2pass.fp
@@ -4,6 +4,13 @@
 // 2-pass shader w/o weight
 //
 
+#if __VERSION__ >= 130
+  #define varying in
+  out vec4 mgl_FragColor;
+#else
+  #define mgl_FragColor gl_FragColor
+#endif
+
 #include uniforms.glsl
 #include varyings.glsl
 
@@ -49,10 +56,11 @@ void main (void)
         t += texture2D(gcu_TextureUnit, rtex + 4.0*size*(vec2(0, 1)))*tex_weights.w;
         t += texture2D(gcu_TextureUnit, rtex - 4.0*size*(vec2(0, 1)))*tex_weights.w;
         
-        /** discard freezes NV tegra2 compiler
+        #if 0
         if(t.w == 0.0){
-            discard;
-        } */
+            discard; // discard freezes NV tegra2 compiler
+        }
+        #endif
         
         c = t.xyz;
         alpha = gcu_Alpha * t.w;
@@ -78,5 +86,5 @@ void main (void)
         }
     }
 
-    gl_FragColor = vec4(c, alpha);
+    mgl_FragColor = vec4(c, alpha);
 }
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2-merged.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2-merged.vp
deleted file mode 100644
index 8fb985d..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2-merged.vp
+++ /dev/null
@@ -1,19 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#ifdef GL_ES
-  precision highp float;
-  precision highp int;
-#endif
-
-uniform mat4    gcu_PMVMatrix[3]; // P, Mv, and Mvi
-varying vec2    gcv_TexCoord;
-
-attribute vec4    gca_Vertices;
-attribute vec2    gca_TexCoords;
-
-
-void main(void)
-{
-  gl_Position = gcu_PMVMatrix[0] * gcu_PMVMatrix[1] * gca_Vertices;
-  gcv_TexCoord = gca_TexCoords;
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2.vp
deleted file mode 100644
index a5dc158..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-es2.vp
+++ /dev/null
@@ -1,9 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 100
-
-precision highp float;
-precision highp int;
-
-#include curverenderer01-xxx.vp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-gl2.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-gl2.vp
deleted file mode 100644
index 1ac33e8..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-gl2.vp
+++ /dev/null
@@ -1,6 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 110
-
-#include curverenderer01-xxx.vp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-xxx.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01.vp
similarity index 81%
rename from src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-xxx.vp
rename to src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01.vp
index 64a6835..4b5c8b1 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-xxx.vp
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01.vp
@@ -1,5 +1,10 @@
 //Copyright 2010 JogAmp Community. All rights reserved.
 
+#if __VERSION__ >= 130
+  #define attribute in
+  #define varying out
+#endif
+
 #include uniforms.glsl
 #include attributes.glsl
 #include varyings.glsl
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2-merged.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2-merged.fp
deleted file mode 100644
index a57d8fc..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2-merged.fp
+++ /dev/null
@@ -1,52 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#ifdef GL_ES
-  precision mediump float;
-  precision mediump int;
-#endif
-
-uniform mat4    gcu_PMVMatrix[3]; // P, Mv, and Mvi
-uniform vec3    gcu_ColorStatic;
-uniform float   gcu_Alpha;
-
-varying vec2    gcv_TexCoord;
-
-const vec3 b_color = vec3(1.0, 1.0, 1.0);
-
-void main (void)
-{
-    vec2 rtex = vec2(abs(gcv_TexCoord.x),abs(gcv_TexCoord.y));
-    vec3 c = gcu_ColorStatic;
-    
-    float alpha = 0.0;
-    
-    if((gcv_TexCoord.x == 0.0) && (gcv_TexCoord.y == 0.0)) {
-         alpha = gcu_Alpha;
-    }
-    else if ((gcv_TexCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)) {
-        vec2 dtx = dFdx(rtex);
-        vec2 dty = dFdy(rtex);
-          
-        rtex.y -= 0.1;
-          
-        if(rtex.y < 0.0) {
-          rtex.y = 0.0;
-        }
-          
-        vec2 f = vec2((dtx.y - dtx.x + 2.0*rtex.x*dtx.x), (dty.y - dty.x + 2.0*rtex.x*dty.x));
-        float position = rtex.y - (rtex.x * (1.0 - rtex.x));
-        float d = position/(length(f));
-
-        float a = (0.5 - d * sign(gcv_TexCoord.y));  
-        
-        if (a >= 1.0)  { 
-            alpha = gcu_Alpha;
-        } else if (a <= 0.0) {
-            alpha=0.0;
-        } else {           
-            alpha = gcu_Alpha * a;
-        }
-    }
-    
-    gl_FragColor = vec4(c, alpha);
-}
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2.fp
deleted file mode 100644
index e693891..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-es2.fp
+++ /dev/null
@@ -1,13 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 100
-
-// we require dFdx/dFdy
-// #extension OES_standard_derivatives : require
-#extension GL_OES_standard_derivatives : enable
-
-precision mediump float;
-precision mediump int;
-
-#include curverenderer01a-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-gl2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-gl2.fp
deleted file mode 100644
index d187fea..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01a-gl2.fp
+++ /dev/null
@@ -1,6 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 110
-
-#include curverenderer01a-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-es2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-es2.fp
deleted file mode 100644
index d474872..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-es2.fp
+++ /dev/null
@@ -1,14 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 100
-
-// we require dFdx/dFdy
-// #extension OES_standard_derivatives : require
-#extension GL_OES_standard_derivatives : enable
-
-precision mediump float;
-precision mediump int;
-precision mediump sampler2D; // default is lowp
-
-#include curverenderer01b-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-gl2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-gl2.fp
deleted file mode 100644
index 01e08ff..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01b-gl2.fp
+++ /dev/null
@@ -1,6 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 110
-
-#include curverenderer01b-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-es2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-es2.fp
deleted file mode 100644
index 240a6c3..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-es2.fp
+++ /dev/null
@@ -1,14 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 100
-
-// we require dFdx/dFdy
-// #extension OES_standard_derivatives : require
-#extension GL_OES_standard_derivatives : enable
-
-precision mediump float;
-precision mediump int;
-precision mediump sampler2D; // default is lowp
-
-#include curverenderer02a-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-gl2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-gl2.fp
deleted file mode 100644
index 01715da..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02a-gl2.fp
+++ /dev/null
@@ -1,6 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 110
-
-#include curverenderer02a-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-es2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-es2.fp
deleted file mode 100644
index 884e756..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-es2.fp
+++ /dev/null
@@ -1,14 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 100
-
-// we require dFdx/dFdy
-// #extension OES_standard_derivatives : require
-#extension GL_OES_standard_derivatives : enable
-
-precision mediump float;
-precision mediump int;
-precision mediump sampler2D; // default is lowp
-
-#include curverenderer02b-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-gl2.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-gl2.fp
deleted file mode 100644
index b1cc721..0000000
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer02b-gl2.fp
+++ /dev/null
@@ -1,6 +0,0 @@
-//Copyright 2010 JogAmp Community. All rights reserved.
-
-#version 110
-
-#include curverenderer02b-xxx.fp
-
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
index 10b6d68..e96c559 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
@@ -35,7 +35,7 @@ import com.jogamp.graph.curve.tess.Triangulator;
 import com.jogamp.graph.geom.Outline;
 import com.jogamp.graph.geom.Triangle;
 import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.math.VectorUtil;
+import com.jogamp.opengl.math.VectorUtil;
 
 import jogamp.opengl.Debug;
 
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
index b4b796b..6511790 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
@@ -30,10 +30,10 @@ package jogamp.graph.curve.tess;
 import java.util.ArrayList;
 
 
-import com.jogamp.graph.geom.AABBox;
 import com.jogamp.graph.geom.Vertex;
 import com.jogamp.graph.geom.Triangle;
-import com.jogamp.graph.math.VectorUtil;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.math.geom.AABBox;
 
 public class Loop {
     private HEdge root = null;
@@ -250,7 +250,7 @@ public class Loop {
                     continue;
                 }
                 inValid = VectorUtil.inCircle(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(),
-                        cand, e.getGraphPoint().getPoint());
+                                              cand, e.getGraphPoint().getPoint());
                 if(inValid){
                     break;
                 }
diff --git a/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java b/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java
index 5781486..751a7e7 100644
--- a/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java
+++ b/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java
@@ -34,7 +34,7 @@ import com.jogamp.graph.geom.Triangle;
 import com.jogamp.graph.geom.Vertex.Factory;
 
 import com.jogamp.graph.curve.OutlineShape;
-import com.jogamp.graph.math.Quaternion;
+import com.jogamp.opengl.math.Quaternion;
 
 public class GlyphShape {
     
diff --git a/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java b/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java
index f86d02f..cc850b8 100644
--- a/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java
+++ b/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java
@@ -30,7 +30,6 @@ package jogamp.graph.curve.text;
 import java.util.ArrayList;
 
 import com.jogamp.graph.font.Font;
-import com.jogamp.graph.geom.AABBox;
 import com.jogamp.graph.geom.Vertex;
 import com.jogamp.graph.geom.Triangle;
 import com.jogamp.graph.geom.Vertex.Factory;
@@ -45,6 +44,7 @@ import com.jogamp.graph.curve.OutlineShape;
 import com.jogamp.graph.curve.Region;
 import com.jogamp.graph.curve.opengl.GLRegion;
 import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.opengl.math.geom.AABBox;
 import com.jogamp.opengl.util.PMVMatrix;
 
 public class GlyphString {
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
index 8e465de..0441bf8 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
@@ -45,9 +45,9 @@ import com.jogamp.graph.curve.OutlineShape;
 import com.jogamp.graph.font.Font;
 import com.jogamp.graph.font.FontFactory;
 import com.jogamp.graph.font.Font.Glyph;
-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;
 
 class TypecastFont implements FontInt {
     static final boolean DEBUG = false;
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
index 0f762e7..8479c08 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
@@ -71,7 +71,7 @@ public class TypecastFontConstructor implements FontConstructor  {
                 int len=0;
                 Font f = null;
                 try {         
-                    tf = IOUtil.createTempFile( "jogl.font", ".ttf", false, null);
+                    tf = IOUtil.createTempFile( "jogl.font", ".ttf", false);
                     len = IOUtil.copyURLConn2File(fconn, tf);
                     if(len==0) {
                         tf.delete();
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
index a1f1a32..1205c65 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
@@ -34,7 +34,7 @@ import jogamp.graph.geom.plane.AffineTransform;
 import jogamp.graph.geom.plane.Path2D;
 
 import com.jogamp.graph.font.Font;
-import com.jogamp.graph.geom.AABBox;
+import com.jogamp.opengl.math.geom.AABBox;
 
 public class TypecastGlyph implements FontInt.GlyphInt {
     public class Advance
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
index 0dd7a61..f170f58 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastHMetrics.java
@@ -31,7 +31,7 @@ import jogamp.graph.font.typecast.ot.table.HeadTable;
 import jogamp.graph.font.typecast.ot.table.HheaTable;
 
 import com.jogamp.graph.font.Font.Metrics;
-import com.jogamp.graph.geom.AABBox;
+import com.jogamp.opengl.math.geom.AABBox;
 
 class TypecastHMetrics implements Metrics {
     private final TypecastFont fontImpl;
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java
index 5c00424..244ab40 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTGlyph.java
@@ -56,7 +56,7 @@ import jogamp.graph.font.typecast.ot.table.GlyfDescript;
 import jogamp.graph.font.typecast.ot.table.GlyphDescription;
 import jogamp.graph.font.typecast.t2.T2Interpreter;
 
-import com.jogamp.graph.geom.AABBox;
+import com.jogamp.opengl.math.geom.AABBox;
 
 
 
diff --git a/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java b/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
index fc086eb..0fd174c 100644
--- a/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
+++ b/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
@@ -22,11 +22,11 @@ package jogamp.graph.geom.plane;
 import java.io.IOException;
 import java.io.Serializable;
 
-import jogamp.graph.math.MathFloat;
 // import jogamp.opengl.util.HashCode;
 
 import com.jogamp.graph.geom.Vertex;
 import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.opengl.math.FloatUtil;
 
 public class AffineTransform implements Cloneable, Serializable {
 
@@ -285,13 +285,13 @@ public class AffineTransform implements Cloneable, Serializable {
     }
 
     public void setToRotation(float angle) {
-        float sin = MathFloat.sin(angle);
-        float cos = MathFloat.cos(angle);
-        if (MathFloat.abs(cos) < ZERO) {
+        float sin = FloatUtil.sin(angle);
+        float cos = FloatUtil.cos(angle);
+        if (FloatUtil.abs(cos) < ZERO) {
             cos = 0.0f;
             sin = sin > 0.0f ? 1.0f : -1.0f;
         } else
-            if (MathFloat.abs(sin) < ZERO) {
+            if (FloatUtil.abs(sin) < ZERO) {
                 sin = 0.0f;
                 cos = cos > 0.0f ? 1.0f : -1.0f;
             }
@@ -387,7 +387,7 @@ public class AffineTransform implements Cloneable, Serializable {
 
     public AffineTransform createInverse() throws NoninvertibleTransformException {
         float det = getDeterminant();
-        if (MathFloat.abs(det) < ZERO) {
+        if (FloatUtil.abs(det) < ZERO) {
             throw new NoninvertibleTransformException(determinantIsZero);
         }
         return new AffineTransform(
@@ -467,7 +467,7 @@ public class AffineTransform implements Cloneable, Serializable {
 
     public Vertex inverseTransform(Vertex src, Vertex dst) throws NoninvertibleTransformException {
         float det = getDeterminant();
-        if (MathFloat.abs(det) < ZERO) {
+        if (FloatUtil.abs(det) < ZERO) {
             throw new NoninvertibleTransformException(determinantIsZero);
         }
         if (dst == null) {
@@ -485,7 +485,7 @@ public class AffineTransform implements Cloneable, Serializable {
         throws NoninvertibleTransformException
     {
         float det = getDeterminant();
-        if (MathFloat.abs(det) < ZERO) {
+        if (FloatUtil.abs(det) < ZERO) {
             throw new NoninvertibleTransformException(determinantIsZero);            
         }
 
diff --git a/src/jogl/classes/jogamp/graph/math/plane/Crossing.java b/src/jogl/classes/jogamp/graph/geom/plane/Crossing.java
similarity index 97%
rename from src/jogl/classes/jogamp/graph/math/plane/Crossing.java
rename to src/jogl/classes/jogamp/graph/geom/plane/Crossing.java
index 9be5978..cd4ee2a 100644
--- a/src/jogl/classes/jogamp/graph/math/plane/Crossing.java
+++ b/src/jogl/classes/jogamp/graph/geom/plane/Crossing.java
@@ -17,11 +17,10 @@
 /**
  * @author Denis M. Kishenko
  */
-package jogamp.graph.math.plane;
+package jogamp.graph.geom.plane;
+
+import com.jogamp.opengl.math.FloatUtil;
 
-import jogamp.graph.geom.plane.Path2D;
-import jogamp.graph.geom.plane.PathIterator;
-import jogamp.graph.math.MathFloat;
 
 
 public class Crossing {
@@ -68,7 +67,7 @@ public class Crossing {
             if (d < 0.0) {
                 return 0;
             }
-            d = MathFloat.sqrt(d);
+            d = FloatUtil.sqrt(d);
             res[rc++] = (- b + d) / (a * 2.0f);
             // d != 0.0
             if (d != 0.0) {
@@ -101,15 +100,15 @@ public class Crossing {
         float n = - a / 3.0f;
 
         if (R2 < Q3) {
-            float t = MathFloat.acos(R / MathFloat.sqrt(Q3)) / 3.0f;
-            float p = 2.0f * MathFloat.PI / 3.0f;
-            float m = -2.0f * MathFloat.sqrt(Q);
-            res[rc++] = m * MathFloat.cos(t) + n;
-            res[rc++] = m * MathFloat.cos(t + p) + n;
-            res[rc++] = m * MathFloat.cos(t - p) + n;
+            float t = FloatUtil.acos(R / FloatUtil.sqrt(Q3)) / 3.0f;
+            float p = 2.0f * FloatUtil.PI / 3.0f;
+            float m = -2.0f * FloatUtil.sqrt(Q);
+            res[rc++] = m * FloatUtil.cos(t) + n;
+            res[rc++] = m * FloatUtil.cos(t + p) + n;
+            res[rc++] = m * FloatUtil.cos(t - p) + n;
         } else {
 //          Debug.println("R2 >= Q3 (" + R2 + "/" + Q3 + ")");
-            float A = MathFloat.pow(MathFloat.abs(R) + MathFloat.sqrt(R2 - Q3), 1.0f / 3.0f);
+            float A = FloatUtil.pow(FloatUtil.abs(R) + FloatUtil.sqrt(R2 - Q3), 1.0f / 3.0f);
             if (R > 0.0) {
                 A = -A;
             }
diff --git a/src/jogl/classes/jogamp/graph/geom/plane/Path2D.java b/src/jogl/classes/jogamp/graph/geom/plane/Path2D.java
index c895e83..945eece 100644
--- a/src/jogl/classes/jogamp/graph/geom/plane/Path2D.java
+++ b/src/jogl/classes/jogamp/graph/geom/plane/Path2D.java
@@ -21,11 +21,10 @@ package jogamp.graph.geom.plane;
 
 import java.util.NoSuchElementException;
 
-import com.jogamp.graph.geom.AABBox;
 import com.jogamp.graph.geom.Vertex;
 import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.opengl.math.geom.AABBox;
 
-import jogamp.graph.math.plane.Crossing;
 
 public final class Path2D implements Cloneable {
 
diff --git a/src/jogl/classes/jogamp/graph/math/MathFloat.java b/src/jogl/classes/jogamp/graph/math/MathFloat.java
deleted file mode 100644
index 82e7823..0000000
--- a/src/jogl/classes/jogamp/graph/math/MathFloat.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * 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 jogamp.graph.math;
-
-public class MathFloat {
-
-    public static final float E = 2.7182818284590452354f;
-
-    public static final float PI = 3.14159265358979323846f;
-    
-    public static float abs(float a) { return (float) java.lang.Math.abs(a);  }
-    public static float pow(float a, float b) { return (float) java.lang.Math.pow(a, b);  }
-    
-    public static float sin(float a) { return (float) java.lang.Math.sin(a);  }
-    public static float cos(float a) { return (float) java.lang.Math.cos(a);  }
-    public static float acos(float a) { return (float) java.lang.Math.acos(a);  }
-    
-    public static float sqrt(float a) { return (float) java.lang.Math.sqrt(a);  }
-    
-}
diff --git a/src/jogl/classes/jogamp/opengl/Debug.java b/src/jogl/classes/jogamp/opengl/Debug.java
index 4287c19..f87f1bb 100644
--- a/src/jogl/classes/jogamp/opengl/Debug.java
+++ b/src/jogl/classes/jogamp/opengl/Debug.java
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * 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
@@ -39,6 +40,9 @@
 
 package jogamp.opengl;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
 import com.jogamp.common.util.PropertyAccess;
 
 /** Helper routines for logging and debugging. */
@@ -49,7 +53,12 @@ public class Debug extends PropertyAccess {
   private static final boolean debugAll;
   
   static {
-    PropertyAccess.addTrustedPrefix("jogl.", Debug.class);
+    AccessController.doPrivileged(new PrivilegedAction<Object>() {
+        public Object run() {
+            PropertyAccess.addTrustedPrefix("jogl.");
+            return null;
+    } } );
+    
     verbose = isPropertyDefined("jogl.verbose", true);
     debugAll = isPropertyDefined("jogl.debug", true);
     if (verbose) {
@@ -60,18 +69,6 @@ public class Debug extends PropertyAccess {
     }
   }
 
-  public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) {
-    return PropertyAccess.isPropertyDefined(property, jnlpAlias, null);
-  }
-    
-  public static String getProperty(final String property, final boolean jnlpAlias) {
-    return PropertyAccess.getProperty(property, jnlpAlias, null);
-  }
-  
-  public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) {
-      return PropertyAccess.getBooleanProperty(property, jnlpAlias, null);
-  }
-  
   public static boolean verbose() {
     return verbose;
   }
diff --git a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
index f77f113..ef9477a 100644
--- a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
@@ -32,7 +32,7 @@ import java.util.List;
 import java.util.ArrayList;
 
 public abstract class DesktopGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
-    private static List<String> glueLibNames;
+    private static final List<String> glueLibNames;
     static {
         glueLibNames = new ArrayList<String>();
 
@@ -49,7 +49,7 @@ public abstract class DesktopGLDynamicLibraryBundleInfo extends GLDynamicLibrary
     }
     
     @Override
-    public boolean useToolGetProcAdressFirst(String funcName) {
+    public final boolean useToolGetProcAdressFirst(String funcName) {
         return true;
     }
     
diff --git a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java
index ff49303..8eb3468 100644
--- a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java
+++ b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java
@@ -37,9 +37,9 @@ public class DesktopGLDynamicLookupHelper extends GLDynamicLookupHelper {
         super(info);
     }
 
-    public DesktopGLDynamicLibraryBundleInfo getDesktopGLBundleInfo() { return (DesktopGLDynamicLibraryBundleInfo) getBundleInfo(); }
+    public final DesktopGLDynamicLibraryBundleInfo getDesktopGLBundleInfo() { return (DesktopGLDynamicLibraryBundleInfo) getBundleInfo(); }
 
-    public synchronized boolean loadGLULibrary() {
+    public final synchronized boolean loadGLULibrary() {
         /** hacky code .. where all platform GLU libs are tried ..*/
         if(null==gluLib) {
             List<String> gluLibNames = new ArrayList<String>();
diff --git a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
index 610f08e..7c7ea15 100644
--- a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
+++ b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
@@ -42,6 +42,8 @@ package jogamp.opengl;
 
 import javax.media.opengl.*;
 
+import com.jogamp.common.util.VersionNumber;
+
 import java.util.*;
 
 /**
@@ -218,8 +220,9 @@ final class ExtensionAvailabilityCache {
       }
 
       if(!context.isGLES()) {
-          int major[] = new int[] { context.getGLVersionMajor() };
-          int minor[] = new int[] { context.getGLVersionMinor() };
+          final VersionNumber version = context.getGLVersionNumber();
+          int major[] = new int[] { version.getMajor() };
+          int minor[] = new int[] { version.getMinor() };
           while (GLContext.isValidGLVersion(major[0], minor[0])) {
               availableExtensionCache.add("GL_VERSION_" + major[0] + "_" + minor[0]);
               if (DEBUG) {
@@ -247,8 +250,6 @@ final class ExtensionAvailabilityCache {
   private int glXExtensionCount = 0;
   private HashSet<String> availableExtensionCache = new HashSet<String>(50);
 
-  static String getThreadName() {
-    return Thread.currentThread().getName();
-  }
+  static String getThreadName() { return Thread.currentThread().getName(); }
 
 }
diff --git a/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java b/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java
index 27569d2..b74ac9f 100644
--- a/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java
+++ b/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java
@@ -103,6 +103,7 @@ public class FPSCounterImpl implements FPSCounter {
         fpsLastPeriod = 0;
         fpsTotalFrames = 0;
         fpsLast = 0f; fpsTotal = 0f;
+        fpsLastPeriod = 0; fpsTotalDuration=0;
     }
 
     public final synchronized int getUpdateFPSFrames() {
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index 85156e8..bfa748a 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -29,6 +29,7 @@
 package jogamp.opengl;
 
 import java.io.PrintStream;
+import java.util.List;
 
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.NativeSurface;
@@ -49,7 +50,8 @@ import javax.media.opengl.GLRunnable;
 
 import com.jogamp.common.util.locks.RecursiveLock;
 import com.jogamp.opengl.GLAutoDrawableDelegate;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.GLStateKeeper;
 
 
 /**
@@ -60,7 +62,7 @@ import com.jogamp.opengl.util.Animator;
  * @see GLPBufferImpl
  * @see GLWindow
  */
-public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
+public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeeper, FPSCounter {
     public static final boolean DEBUG = GLDrawableImpl.DEBUG;
     
     protected final GLDrawableHelper helper = new GLDrawableHelper();
@@ -68,14 +70,21 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
     
     protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
     protected GLContextImpl context;
+    protected boolean preserveGLELSAtDestroy;
+    protected GLEventListenerState glels;
+    protected GLStateKeeper.Listener glStateKeeperListener;
     protected final boolean ownsDevice;
     protected int additionalCtxCreationFlags = 0;
     protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking
     protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking
 
     /**
-     * @param drawable upstream {@link GLDrawableImpl} instance, may be null for lazy initialization
-     * @param context upstream {@link GLContextImpl} instance, may be null for lazy initialization
+     * @param drawable upstream {@link GLDrawableImpl} instance, 
+     *                 may be <code>null</code> for lazy initialization
+     * @param context upstream {@link GLContextImpl} instance, 
+     *                may not have been made current (created) yet,
+     *                may not be associated w/ <code>drawable<code> yet,
+     *                may be <code>null</code> for lazy initialization
      * @param ownsDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
      *                   otherwise pass <code>false</code>. Closing the device is required in case
      *                   the drawable is created w/ it's own new instance, e.g. offscreen drawables,
@@ -84,18 +93,103 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
     public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownsDevice) {
         this.drawable = drawable;
         this.context = context;
+        this.preserveGLELSAtDestroy = false;
+        this.glels = null;
+        this.glStateKeeperListener = null;
         this.ownsDevice = ownsDevice;
+        if(null != context && null != drawable) {
+            context.setGLDrawable(drawable, false);
+        }
         resetFPSCounter();        
     }
    
-    /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access. */ 
+    /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access on top of {@link NativeSurface#lockSurface()}. */ 
     protected abstract RecursiveLock getLock();
+
+    @Override
+    public final GLStateKeeper.Listener setGLStateKeeperListener(Listener l) {
+        final GLStateKeeper.Listener pre = glStateKeeperListener;
+        glStateKeeperListener = l;
+        return pre;        
+    }
+    
+    @Override
+    public final boolean preserveGLStateAtDestroy(boolean value) {
+        final boolean res = isGLStatePreservationSupported() ? true : false;
+        if( res ) {
+            if( DEBUG ) {
+                System.err.println("GLAutoDrawableBase.setPreserveGLStateAtDestroy: ("+getThreadName()+"): "+preserveGLELSAtDestroy+" -> "+value+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+            }
+            preserveGLELSAtDestroy = value;
+        }
+        return res;
+    }
+    
+    @Override
+    public boolean isGLStatePreservationSupported() { return false; }
+    
+    @Override
+    public final GLEventListenerState getPreservedGLState() {
+        return glels;
+    }
+
+    @Override
+    public final GLEventListenerState clearPreservedGLState() {
+        final GLEventListenerState r = glels;
+        glels = null;
+        return r;
+    }
+    
+    /**
+     * Pulls the {@link GLEventListenerState} from this {@link GLAutoDrawable}.
+     * 
+     * @return <code>true</code> if the {@link GLEventListenerState} is pulled successfully from this {@link GLAutoDrawable},
+     *         otherwise <code>false</code>.
+     * 
+     * @throws IllegalStateException if the {@link GLEventListenerState} is already pulled
+     * 
+     * @see #pushGLEventListenerState()
+     */
+    protected final boolean pullGLEventListenerState() throws IllegalStateException {
+        if( null != glels ) {
+            throw new IllegalStateException("GLEventListenerState already pulled");            
+        }
+        if( null != context && context.isCreated() ) {
+            if( null!= glStateKeeperListener) {
+                glStateKeeperListener.glStatePreserveNotify(this);
+            }
+            glels = GLEventListenerState.moveFrom(this);
+            return null != glels;
+        }
+        return false;
+    }
+    
+    /**
+     * Pushes a previously {@link #pullGLEventListenerState() pulled} {@link GLEventListenerState} to this {@link GLAutoDrawable}.
+     * 
+     * @return <code>true</code> if the {@link GLEventListenerState} was previously {@link #pullGLEventListenerState() pulled} 
+     *         and is pushed successfully to this {@link GLAutoDrawable},
+     *         otherwise <code>false</code>.
+     * 
+     * @see #pullGLEventListenerState()
+     */
+    protected final boolean pushGLEventListenerState() {
+        if( null != glels ) {
+            glels.moveTo(this);
+            glels = null;
+            if( null!= glStateKeeperListener) {
+                glStateKeeperListener.glStateRestored(this);
+            }            
+            return true;
+        }
+        return false;        
+    }
     
     /** Default implementation to handle repaint events from the windowing system */
     protected final void defaultWindowRepaintOp() {
         final GLDrawable _drawable = drawable;
         if( null != _drawable && _drawable.isRealized() ) {
-            if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isExternalAnimatorAnimating() ) {
+            if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimatingOnOtherThread() ) {
                 display();
             }
         }
@@ -106,7 +200,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
         GLDrawableImpl _drawable = drawable;
         if( null!=_drawable ) {
             if(DEBUG) {
-                System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+                System.err.println("GLAutoDrawableBase.sizeChanged: ("+getThreadName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
             }
             if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
                 final RecursiveLock _lock = getLock();
@@ -124,7 +218,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
             }
             sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
             if( _drawable.isRealized() ) {
-                if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isExternalAnimatorAnimating() ) {
+                if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimatingOnOtherThread() ) {
                     display();
                 }
             }
@@ -178,7 +272,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
         final GLAnimatorControl ctrl = helper.getAnimator();
         
         // Is an animator thread perform rendering?
-        if ( helper.isAnimatorRunningOnOtherThread() ) {
+        if ( helper.isAnimatorStartedOnOtherThread() ) {
             // Pause animations before initiating safe destroy.
             final boolean isPaused = ctrl.pause();
             destroy();
@@ -222,27 +316,30 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
      * In such case call <code>super.destroyImplInLock</code> first.</p>
      */
     protected void destroyImplInLock() {
-        final GLContext _context = context;
-        final GLDrawable _drawable = drawable;
-        if( null != _drawable ) {
-            if( _drawable.isRealized() ) {
-                if( null != _context && _context.isCreated() ) {
-                    // Catch dispose GLExceptions by GLEventListener, just 'print' them
-                    // so we can continue with the destruction.
-                    try {
-                        helper.disposeGL(this, _drawable, _context, null);
-                    } catch (GLException gle) {
-                        gle.printStackTrace();
-                    }
+        if( preserveGLELSAtDestroy ) {
+            preserveGLStateAtDestroy(false);
+            pullGLEventListenerState();
+        }
+        if( null != context ) {
+            if( context.isCreated() ) {        
+                // Catch dispose GLExceptions by GLEventListener, just 'print' them
+                // so we can continue with the destruction.
+                try {
+                    helper.disposeGL(this, context, true);
+                } catch (GLException gle) {
+                    gle.printStackTrace();
                 }
-                _drawable.setRealized(false);
             }
+            context = null;
+        }
+        if( null != drawable ) {
+            final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+            drawable.setRealized(false);
+            drawable = null;
             if( ownsDevice ) {
-                _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close();
+                device.close();
             }
-        }
-        context = null;
-        drawable = null;        
+        }        
     }
     
     public final void defaultSwapBuffers() throws GLException {
@@ -299,6 +396,16 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
         }
     }
         
+    protected final GLEventListener defaultDisposeGLEventListener(GLEventListener listener, boolean remove) {
+        final RecursiveLock _lock = getLock();
+        _lock.lock();
+        try {
+            return helper.disposeGLEventListener(GLAutoDrawableBase.this, drawable, context, listener, remove);
+        } finally {
+            _lock.unlock();
+        }        
+    }
+    
     @Override
     public final GLDrawable getDelegatedDrawable() {
         return drawable;
@@ -310,16 +417,13 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
     }
 
     @Override
-    public final GLContext setContext(GLContext newCtx) {
+    public final GLContext setContext(GLContext newCtx, boolean destroyPrevCtx) {
         final RecursiveLock lock = getLock();
         lock.lock();
         try {
             final GLContext oldCtx = context;
-            final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+            GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
             context=(GLContextImpl)newCtx;
-            if(newCtxCurrent) {
-                context.makeCurrent();
-            }
             return oldCtx;
         } finally {
             lock.unlock();
@@ -356,13 +460,33 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
     }
 
     @Override
-    public final void removeGLEventListener(GLEventListener listener) {
-        helper.removeGLEventListener(listener);        
+    public int getGLEventListenerCount() {
+        return helper.getGLEventListenerCount();
+    }
+
+    @Override
+    public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException {
+        return helper.getGLEventListener(index);
+    }
+
+    @Override
+    public boolean getGLEventListenerInitState(GLEventListener listener) {
+        return helper.getGLEventListenerInitState(listener);
+    }
+
+    @Override
+    public void setGLEventListenerInitState(GLEventListener listener, boolean initialized) {
+        helper.setGLEventListenerInitState(listener, initialized);
+    }
+   
+    @Override
+    public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove) {
+        return defaultDisposeGLEventListener(listener, remove);
     }
     
     @Override
-    public GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
-        return helper.removeGLEventListener(index);
+    public final GLEventListener removeGLEventListener(GLEventListener listener) {
+        return helper.removeGLEventListener(listener);        
     }
     
     @Override
@@ -377,11 +501,26 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
     }
 
     @Override
+    public final Thread setExclusiveContextThread(Thread t) throws GLException {
+        return helper.setExclusiveContextThread(t, context);
+    }
+
+    @Override
+    public final Thread getExclusiveContextThread() {
+        return helper.getExclusiveContextThread();
+    }
+    
+    @Override
     public final boolean invoke(boolean wait, GLRunnable glRunnable) {
         return helper.invoke(this, wait, glRunnable);        
     }
 
     @Override
+    public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) {
+        return helper.invoke(this, wait, glRunnables);
+    }
+    
+    @Override
     public final void setAutoSwapBufferMode(boolean enable) {
         helper.setAutoSwapBufferMode(enable);        
     }
@@ -480,6 +619,24 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
     }
 
     @Override
+    public final void setRealized(boolean realized) {
+        final RecursiveLock _lock = getLock();
+        _lock.lock();
+        try {            
+            final GLDrawable _drawable = drawable;
+            if( null == _drawable || realized && ( 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) ) {
+                return; 
+            }
+            _drawable.setRealized(realized);
+            if( realized && _drawable.isRealized() ) {
+                sendReshape=true; // ensure a reshape is being send ..
+            }
+        } finally {
+            _lock.unlock();
+        }
+    }
+    
+    @Override
     public final boolean isRealized() {
         final GLDrawable _drawable = drawable;
         return null != _drawable ? _drawable.isRealized() : false;
@@ -497,25 +654,12 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
         return null != _drawable ? _drawable.getHeight() : 0;
     }
 
-    /**
-     * @param t the thread for which context release shall be skipped, usually the animation thread,
-     *          ie. {@link Animator#getThread()}.
-     * @deprecated This is an experimental feature,
-     *             intended for measuring performance in regards to GL context switch.
-     */
-    @Deprecated
-    public void setSkipContextReleaseThread(Thread t) {
-        helper.setSkipContextReleaseThread(t);
-    }
-
-    /**
-     * @deprecated see {@link #setSkipContextReleaseThread(Thread)}
-     */
-    @Deprecated
-    public Thread getSkipContextReleaseThread() {
-        return helper.getSkipContextReleaseThread();
+    @Override
+    public boolean isGLOriented() {
+        final GLDrawable _drawable = drawable;
+        return null != _drawable ? _drawable.isGLOriented() : true;
     }
-
+  
     @Override
     public final GLCapabilitiesImmutable getChosenGLCapabilities() {
         final GLDrawable _drawable = drawable;
@@ -540,6 +684,8 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
         return null != _drawable ? _drawable.getHandle() : 0;
     }
     
+    protected static String getThreadName() { return Thread.currentThread().getName(); }
+
     @Override
     public String toString() {
         return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable +
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
index 4a1a81b..7f5316f 100644
--- a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
@@ -91,6 +91,7 @@ public class GLBufferStateTracker {
     bindingMap.setKeyNotFoundValue(0xFFFFFFFF);
 
     // Start with known unbound targets for known keys
+    // setBoundBufferObject(GL2GL3.GL_VERTEX_ARRAY_BINDING, 0); // not using default VAO (removed in GL3 core) - only explicit
     setBoundBufferObject(GL.GL_ARRAY_BUFFER,         0);
     setBoundBufferObject(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
     setBoundBufferObject(GL2.GL_PIXEL_PACK_BUFFER,   0);
@@ -120,6 +121,7 @@ public class GLBufferStateTracker {
       boolean gotQueryTarget = true;
       int queryTarget = 0;
       switch (target) {
+        case GL2GL3.GL_VERTEX_ARRAY_BINDING: queryTarget = GL2GL3.GL_VERTEX_ARRAY_BINDING;  break;
         case GL.GL_ARRAY_BUFFER:          queryTarget = GL.GL_ARRAY_BUFFER_BINDING;         break;
         case GL.GL_ELEMENT_ARRAY_BUFFER:  queryTarget = GL.GL_ELEMENT_ARRAY_BUFFER_BINDING; break;
         case GL2.GL_PIXEL_PACK_BUFFER:    queryTarget = GL2.GL_PIXEL_PACK_BUFFER_BINDING;    break;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 65b5233..d6f9766 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -42,6 +42,8 @@ package jogamp.opengl;
 
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -49,6 +51,8 @@ import com.jogamp.common.os.DynamicLookupHelper;
 import com.jogamp.common.os.Platform;
 import com.jogamp.common.util.ReflectionUtil;
 import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.VersionNumberString;
+import com.jogamp.common.util.locks.RecursiveLock;
 import com.jogamp.gluegen.runtime.FunctionAddressResolver;
 import com.jogamp.gluegen.runtime.ProcAddressTable;
 import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
@@ -59,6 +63,7 @@ import com.jogamp.opengl.GLRendererQuirks;
 import javax.media.nativewindow.AbstractGraphicsConfiguration;
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.opengl.GL;
 import javax.media.opengl.GL2ES2;
 import javax.media.opengl.GL2GL3;
@@ -87,6 +92,7 @@ public abstract class GLContextImpl extends GLContext {
   // OpenGL functions.
   private ProcAddressTable glProcAddressTable;
 
+  private String glVendor;
   private String glRenderer;
   private String glRendererLowerCase;
   private String glVersion;
@@ -103,6 +109,9 @@ public abstract class GLContextImpl extends GLContext {
   protected GLDrawableImpl drawable;
   protected GLDrawableImpl drawableRead;
   
+  private volatile boolean pixelDataEvaluated;
+  private int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType;
+  
   protected GL gl;
 
   protected static final Object mappedContextTypeObjectLock;
@@ -132,9 +141,6 @@ public abstract class GLContextImpl extends GLContext {
     GLContextShareSet.synchronizeBufferObjectSharing(shareWith, this);
 
     this.drawable = drawable;
-    if(null != drawable) {
-        drawable.associateContext(this, true);
-    }
     this.drawableRead = drawable;
 
     this.glDebugHandler = new GLDebugMessageHandler(this);
@@ -165,13 +171,17 @@ public abstract class GLContextImpl extends GLContext {
       contextFQN = null;
       additionalCtxCreationFlags = 0;
 
-      glRenderer = "";
-      glRendererLowerCase = glRenderer;       
+      glVendor = "";
+      glRenderer = glVendor;
+      glRendererLowerCase = glRenderer;
+      glVersion = glVendor;
       
       if (boundFBOTarget != null) { // <init>
           boundFBOTarget[0] = 0; // draw
           boundFBOTarget[1] = 0; // read
       }
+      
+      pixelDataEvaluated = false;
 
       super.resetStates();
   }
@@ -202,25 +212,41 @@ public abstract class GLContextImpl extends GLContext {
 
   @Override
   public final GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly) {
-    if(null==readWrite) {
-        throw new GLException("Null read/write drawable not allowed");
+    if( drawable == readWrite && ( setWriteOnly || drawableRead == readWrite ) ) {
+        return drawable; // no change.
+    }
+    final Thread currentThread = Thread.currentThread();
+    if( lock.isLockedByOtherThread() ) {
+        throw new GLException("GLContext current by other thread "+lock.getOwner().getName()+", operation not allowed on this thread "+currentThread.getName());
+    }    
+    final boolean lockHeld = lock.isOwner(currentThread);
+    if( lockHeld && lock.getHoldCount() > 1 ) {
+        // would need to makeCurrent * holdCount
+        throw new GLException("GLContext is recursively locked - unsupported for setGLDrawable(..)");
+    }
+    final GLDrawableImpl old = drawable;
+    if( isCreated() && null != old && old.isRealized() ) {
+        if(!lockHeld) {
+            makeCurrent();
+        }
+        associateDrawable(false);
+        if(!lockHeld) {
+            release();
+        }
     }
-    final boolean lockHeld = lock.isOwner(Thread.currentThread());
     if(lockHeld) {
         release();
-    } else if(lock.isLockedByOtherThread()) { // still could glitch ..
-        throw new GLException("GLContext current by other thread ("+lock.getOwner()+"), operation not allowed.");
-    }    
-    if(!setWriteOnly || drawableRead==drawable) { // if !setWriteOnly || !explicitReadDrawable
+    }
+    if( !setWriteOnly || drawableRead == drawable ) { // if !setWriteOnly || !explicitReadDrawable
         drawableRead = (GLDrawableImpl) readWrite;
     }
-    final GLDrawableImpl old = drawable;
-    old.associateContext(this, false);
-    drawableRetargeted = null != drawable;
+    drawableRetargeted |= null != drawable && readWrite != drawable;
     drawable = (GLDrawableImpl) readWrite ;
-    drawable.associateContext(this, true);
-    if(lockHeld) {
-        makeCurrent();
+    if( isCreated() && null != drawable && drawable.isRealized() ) {
+        makeCurrent(true); // implicit: associateDrawable(true)
+        if( !lockHeld ) {
+            release();
+        }
     }
     return old;
   }
@@ -244,7 +270,7 @@ public abstract class GLContextImpl extends GLContext {
     if(DEBUG) {
         String sgl1 = (null!=this.gl)?this.gl.getClass().getSimpleName()+", "+this.gl.toString():"<null>";
         String sgl2 = (null!=gl)?gl.getClass().getSimpleName()+", "+gl.toString():"<null>";
-        Exception e = new Exception("Info: setGL (OpenGL "+getGLVersion()+"): "+Thread.currentThread().getName()+", "+sgl1+" -> "+sgl2);
+        Exception e = new Exception("Info: setGL (OpenGL "+getGLVersion()+"): "+getThreadName()+", "+sgl1+" -> "+sgl2);
         e.printStackTrace();
     }
     this.gl = gl;
@@ -270,14 +296,25 @@ public abstract class GLContextImpl extends GLContext {
   @Override
   public void release() throws GLException {
     release(false);
-  }
+  }  
   private void release(boolean inDestruction) throws GLException {
-    if(TRACE_SWITCH) {
-        System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - release() - force: "+inDestruction+", "+lock);
+    if( TRACE_SWITCH ) {
+        System.err.println(getThreadName() +": GLContext.ContextSwitch[release.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+", inDestruction: "+inDestruction+", "+lock);
     }
     if ( !lock.isOwner(Thread.currentThread()) ) {
-        throw new GLException("Context not current on current thread "+Thread.currentThread().getName()+": "+this);
+        final String msg = getThreadName() +": Context not current on current thread, obj " + toHexString(hashCode())+", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+", inDestruction: "+inDestruction+", "+lock;
+        if( DEBUG_TRACE_SWITCH ) {
+            System.err.println(msg);
+            if( null != lastCtxReleaseStack ) {
+                System.err.print("Last release call: ");
+                lastCtxReleaseStack.printStackTrace();
+            } else {
+                System.err.println("Last release call: NONE");
+            }
+        }
+        throw new GLException(msg);
     }
+    
     Throwable drawableContextMadeCurrentException = null;
     final boolean actualRelease = ( inDestruction || lock.getHoldCount() == 1 ) && 0 != contextHandle;
     try {
@@ -298,8 +335,13 @@ public abstract class GLContextImpl extends GLContext {
       }
       drawable.unlockSurface();
       lock.unlock();
-      if(TRACE_SWITCH) {
-          System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+(actualRelease?"switch":"keep  ")+" - CONTEXT_RELEASE - "+lock);
+      if( DEBUG_TRACE_SWITCH ) {
+          final String msg = getThreadName() +": GLContext.ContextSwitch[release.X]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+(actualRelease?"switch":"keep  ")+" - "+lock;
+          lastCtxReleaseStack = new Throwable(msg);
+          if( TRACE_SWITCH ) {
+              System.err.println(msg);
+              // Thread.dumpStack();
+          }
       }
     }
     if(null != drawableContextMadeCurrentException) {
@@ -307,48 +349,53 @@ public abstract class GLContextImpl extends GLContext {
     }
     
   }
+  private Throwable lastCtxReleaseStack = null;
   protected abstract void releaseImpl() throws GLException;
 
   @Override
   public final void destroy() {
-      if (DEBUG || TRACE_SWITCH) {
+      if ( DEBUG_TRACE_SWITCH ) {
+          final long drawH = null != drawable ? drawable.getHandle() : 0;
           System.err.println(getThreadName() + ": GLContextImpl.destroy.0: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
-                  ", surf "+toHexString(drawable.getHandle())+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
+                  ", surf "+toHexString(drawH)+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
       }
-      if (contextHandle != 0) {
-          int lockRes = drawable.lockSurface();
-          if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
+      if ( 0 != contextHandle ) { // isCreated() ?
+          if ( null == drawable ) {
+              throw new GLException("GLContext created but drawable is null: "+toString());
+          }
+          final int lockRes = drawable.lockSurface();
+          if ( NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes ) {
                 // this would be odd ..
                 throw new GLException("Surface not ready to lock: "+drawable);
           }
-          Throwable drawableContextRealizedException = null;
+          Throwable associateDrawableException = null;
           try {
+              if ( !drawable.isRealized() ) {
+                  throw new GLException("GLContext created but drawable not realized: "+toString());
+              }
               // Must hold the lock around the destroy operation to make sure we
               // don't destroy the context while another thread renders to it.
-              lock.lock(); // holdCount++ -> 1 - 3 (1: not locked, 2-3: destroy while rendering)
+              lock.lock(); // holdCount++ -> 1 - n (1: not locked, 2-n: destroy while rendering)
               if ( lock.getHoldCount() > 2 ) {
                   final String msg = getThreadName() + ": GLContextImpl.destroy: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle);
-                  if (DEBUG || TRACE_SWITCH) {
+                  if ( DEBUG_TRACE_SWITCH ) {
                       System.err.println(msg+" - Lock was hold more than once - makeCurrent/release imbalance: "+lock);
                       Thread.dumpStack();
                   }
-                  if ( lock.getHoldCount() > 3 ) {
-                      throw new GLException(msg+" - Lock was hold more than twice - makeCurrent/release imbalance: "+lock);
-                  }
               }
               try {
-                  // release current context
-                  if(lock.getHoldCount() == 1) {
-                      // needs current context to disable debug handler
-                      makeCurrent();
+                  // if not current, makeCurrent(), to call associateDrawable(..) and to disable debug handler
+                  if ( lock.getHoldCount() == 1 ) {
+                      if ( GLContext.CONTEXT_NOT_CURRENT == makeCurrent() ) {
+                          throw new GLException("GLContext.makeCurrent() failed: "+toString());
+                      }
                   }
                   try {
-                      contextRealized(false);
-                      drawable.associateContext(this, false);
+                      associateDrawable(false);
                   } catch (Throwable t) {
-                      drawableContextRealizedException = t;
+                      associateDrawableException = t;
                   }
-                  if(0 != defaultVAO) {
+                  if ( 0 != defaultVAO ) {
                       int[] tmp = new int[] { defaultVAO };
                       gl.getGL2GL3().glBindVertexArray(0);
                       gl.getGL2GL3().glDeleteVertexArrays(1, tmp, 0);
@@ -368,7 +415,7 @@ public abstract class GLContextImpl extends GLContext {
                   }
               } finally {
                   lock.unlock();
-                  if (TRACE_SWITCH) {
+                  if ( DEBUG_TRACE_SWITCH ) {
                       System.err.println(getThreadName() + ": GLContextImpl.destroy.X: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
                               ", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
                   }
@@ -376,8 +423,8 @@ public abstract class GLContextImpl extends GLContext {
           } finally {
               drawable.unlockSurface();
           }
-          if(null != drawableContextRealizedException) {
-              throw new GLException("GLContext.destroy() during GLDrawableImpl.contextRealized(this, false)", drawableContextRealizedException);
+          if( null != associateDrawableException ) {
+              throw new GLException("GLContext.destroy() during associateDrawable(false)", associateDrawableException);
           }
       }
       resetStates();
@@ -393,8 +440,8 @@ public abstract class GLContextImpl extends GLContext {
       throw new GLException("Destination OpenGL context has not been created");
     }
 
-    int lockRes = drawable.lockSurface();
-    if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
+    final int lockRes = drawable.lockSurface();
+    if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
         // this would be odd ..
         throw new GLException("Surface not ready to lock");
     }
@@ -447,74 +494,82 @@ public abstract class GLContextImpl extends GLContext {
    * @see #destroyContextARBImpl
    */
   @Override
-  public int makeCurrent() throws GLException {
-    boolean unlockContextAndDrawable = false;
-    int res = CONTEXT_NOT_CURRENT;
+  public final int makeCurrent() throws GLException {
+      return makeCurrent(false);
+  }
+  
+  protected final int makeCurrent(boolean forceDrawableAssociation) throws GLException {
+    if( TRACE_SWITCH ) {
+        System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+lock);
+    }      
 
     // Note: the surface is locked within [makeCurrent .. swap .. release]
-    int lockRes = drawable.lockSurface();
+    final int lockRes = drawable.lockSurface();
     if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
+        if( DEBUG_TRACE_SWITCH ) {
+            System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X1]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - Surface Not Ready - CONTEXT_NOT_CURRENT - "+lock);                        
+        }
         return CONTEXT_NOT_CURRENT;
     }
+    
+    boolean unlockResources = true; // Must be cleared if successful, otherwise finally block will release context and/or surface!
+    int res = CONTEXT_NOT_CURRENT;
     try {
-        if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
-            drawable.updateHandle();
-        }
-
-        lock.lock();
-        try {
-            // One context can only be current by one thread,
-            // and one thread can only have one context current!
-            final GLContext current = getCurrent();
-            if (current != null) {
-                if (current == this) {
-                    // Assume we don't need to make this context current again
-                    // For Mac OS X, however, we need to update the context to track resizes
-                    drawableUpdatedNotify();
-                    if(TRACE_SWITCH) {
-                        System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - keep   - CONTEXT_CURRENT - "+lock);                        
-                    }
-                    return CONTEXT_CURRENT;
-                } else {
-                    current.release();
-                }
-            }
-            if (0 == drawable.getHandle()) {
+        if ( drawable.isRealized() ) {
+            if ( 0 == drawable.getHandle() ) {
                 throw new GLException("drawable has invalid handle: "+drawable);
             }
-            res = makeCurrentWithinLock(lockRes);
-            unlockContextAndDrawable = CONTEXT_NOT_CURRENT == res;
-
-            /**
-             * FIXME: refactor dependence on Java 2D / JOGL bridge
-                if ((tracker != null) &&
-                    (res == CONTEXT_CURRENT_NEW)) {
-                    // Increase reference count of GLObjectTracker
-                    tracker.ref();
+            lock.lock();
+            try {
+                // One context can only be current by one thread,
+                // and one thread can only have one context current!
+                final GLContext current = getCurrent();
+                if (current != null) {
+                    if (current == this) { // implicit recursive locking!
+                        // Assume we don't need to make this context current again
+                        // For Mac OS X, however, we need to update the context to track resizes
+                        drawableUpdatedNotify();
+                        unlockResources = false; // success
+                        if( TRACE_SWITCH ) {
+                            System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X2]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - keep   - CONTEXT_CURRENT - "+lock);                        
+                        }
+                        return CONTEXT_CURRENT;
+                    } else {
+                        current.release();
+                    }
                 }
-             */
-        } catch (RuntimeException e) {
-          unlockContextAndDrawable = true;
-          throw e;
-        } finally {
-          if (unlockContextAndDrawable) {
-            lock.unlock();
-          }
-        }
+                res = makeCurrentWithinLock(lockRes);
+                unlockResources = CONTEXT_NOT_CURRENT == res; // success ?
+                
+                /**
+                 * FIXME: refactor dependence on Java 2D / JOGL bridge
+                    if ( tracker != null && res == CONTEXT_CURRENT_NEW ) {
+                        // Increase reference count of GLObjectTracker
+                        tracker.ref();
+                    }
+                 */
+            } catch (RuntimeException e) {
+              unlockResources = true;
+              throw e;
+            } finally {
+              if (unlockResources) {
+                if( DEBUG_TRACE_SWITCH ) {
+                  System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.1]: Context lock.unlock() due to error, res "+makeCurrentResultToString(res)+", "+lock);
+                }
+                lock.unlock();
+              }
+            }
+        } /* if ( drawable.isRealized() ) */
     } catch (RuntimeException e) {
-      unlockContextAndDrawable = true;
+      unlockResources = true;
       throw e;
     } finally {
-      if (unlockContextAndDrawable) {
+      if (unlockResources) {
         drawable.unlockSurface();
       }
     }
 
-    if (res == CONTEXT_NOT_CURRENT) {
-      if(TRACE_SWITCH) {
-          System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - switch - CONTEXT_NOT_CURRENT - "+lock);
-      }
-    } else {
+    if (res != CONTEXT_NOT_CURRENT) {
       setCurrent(this);
       if(res == CONTEXT_CURRENT_NEW) {
         // check if the drawable's and the GL's GLProfile are equal
@@ -533,15 +588,13 @@ public abstract class GLContextImpl extends GLContext {
             gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) );
         }
         
-        contextRealized(true);
-        
-        if(DEBUG || TRACE_SWITCH) {
-            System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - switch - CONTEXT_CURRENT_NEW - "+lock);
-        }
-      } else if(TRACE_SWITCH) {
-         System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - switch - CONTEXT_CURRENT - "+lock);
+        forceDrawableAssociation = true;
       }
-
+      
+      if( forceDrawableAssociation ) {
+          associateDrawable(true);
+      }
+      
       contextMadeCurrent(true);
       
       /* FIXME: refactor dependence on Java 2D / JOGL bridge
@@ -553,11 +606,21 @@ public abstract class GLContextImpl extends GLContext {
       }
       */
     }
+    if( TRACE_SWITCH ) {
+        System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X3]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - switch - "+makeCurrentResultToString(res)+" - "+lock);
+    }      
     return res;
   }
-
+  
   private final int makeCurrentWithinLock(int surfaceLockRes) throws GLException {
       if (!isCreated()) {
+        if( 0 >= drawable.getWidth() || 0 >= drawable.getHeight() ) {
+            if ( DEBUG_TRACE_SWITCH ) {
+                System.err.println(getThreadName() + ": Create GL context REJECTED (zero surface size) obj " + toHexString(hashCode()) + ", surf "+toHexString(drawable.getHandle())+" for " + getClass().getName());
+                System.err.println(drawable.toString());
+            }
+            return CONTEXT_NOT_CURRENT;
+        }
         if(DEBUG_GL) {
             // only impacts w/ createContextARB(..)
             additionalCtxCreationFlags |= GLContext.CTX_OPTION_DEBUG ;
@@ -570,9 +633,10 @@ public abstract class GLContextImpl extends GLContext {
         final boolean created;
         try {
             created = createImpl(shareWith); // may throws exception if fails!
-            if( created && isGL3core() && ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=2 ) ) {
-                // Due to GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331)
-                // There is no more default VAO buffer 0 bound, hence generating and binding one
+            if( created && isGL3core() ) {
+                // Due to GL 3.1 core spec: E.1. DEPRECATED AND REMOVED FEATURES (p 296),
+                //        GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331)
+                // there is no more default VAO buffer 0 bound, hence generating and binding one
                 // to avoid INVALID_OPERATION at VertexAttribPointer. 
                 // More clear is GL 4.3 core spec: 10.4 (p 307).
                 final int[] tmp = new int[1];
@@ -585,7 +649,7 @@ public abstract class GLContextImpl extends GLContext {
                 shareWith.getDrawableImpl().unlockSurface();
             }
         }
-        if (DEBUG || TRACE_SWITCH) {
+        if ( DEBUG_TRACE_SWITCH ) {
             if(created) {
                 System.err.println(getThreadName() + ": Create GL context OK: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) + ", surf "+toHexString(drawable.getHandle())+" for " + getClass().getName()+" - "+getGLVersion());
                 // Thread.dumpStack();
@@ -607,10 +671,10 @@ public abstract class GLContextImpl extends GLContext {
                 if( 0 == ( ctxOptions & GLContext.CTX_PROFILE_ES) ) {   // not ES profile
                     final int reqMajor;
                     final int reqProfile;
-                    if(ctxMajorVersion<3 || ctxMajorVersion==3 && ctxMinorVersion==0) {
+                    if( ctxVersion.compareTo(Version30) <= 0 ) {
                         reqMajor = 2;
                     } else {
-                        reqMajor = ctxMajorVersion;
+                        reqMajor = ctxVersion.getMajor();
                     }
                     if( 0 != ( ctxOptions & GLContext.CTX_PROFILE_CORE) ) {
                         reqProfile = GLContext.CTX_PROFILE_CORE;
@@ -618,7 +682,7 @@ public abstract class GLContextImpl extends GLContext {
                         reqProfile = GLContext.CTX_PROFILE_COMPAT;
                     }
                     GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
-                                                    ctxMajorVersion, ctxMinorVersion, ctxOptions);
+                                                    ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
                     GLContext.setAvailableGLVersionsSet(device);
                     
                     if (DEBUG) {
@@ -636,14 +700,14 @@ public abstract class GLContextImpl extends GLContext {
   protected abstract void makeCurrentImpl() throws GLException;
 
   /**
-   * @see GLDrawableImpl#contextRealized(GLContext, boolean) 
+   * Calls {@link GLDrawableImpl#associateContext(GLContext, boolean)} 
    */ 
-  protected void contextRealized(boolean realized) {
-      drawable.contextRealized(this, realized);
+  protected void associateDrawable(boolean bound) { 
+      drawable.associateContext(this, bound);      
   }
   
   /**
-   * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean) 
+   * Calls {@link GLDrawableImpl#contextMadeCurrent(GLContext, boolean)} 
    */ 
   protected void contextMadeCurrent(boolean current) {
       drawable.contextMadeCurrent(this, current);      
@@ -693,8 +757,7 @@ public abstract class GLContextImpl extends GLContext {
    * @see #createContextARBImpl
    * @see #destroyContextARBImpl
    */
-  protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags,
-                                               int major, int minor);
+  protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags, int major, int minor);
 
   /**
    * Destroy the context created by {@link #createContextARBImpl}.
@@ -757,7 +820,7 @@ public abstract class GLContextImpl extends GLContext {
         _ctp[0] |= additionalCtxCreationFlags;
         _ctx = createContextARBImpl(share, direct, _ctp[0], _major[0], _minor[0]);
         if(0!=_ctx) {
-            setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0]);
+            setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0], false);
         }
     }
     return _ctx;
@@ -773,15 +836,42 @@ public abstract class GLContextImpl extends GLContext {
         boolean hasGL2   = false;
         boolean hasGL4   = false;
         boolean hasGL3   = false;
+        
+        // Even w/ PROFILE_ALIASING, try to use true core GL profiles
+        // ensuring proper user behavior across platforms due to different feature sets!
+        //
+        if(!hasGL4) {
+            hasGL4   = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE);    // GL4
+            success |= hasGL4;
+            if(hasGL4) {
+                // Map all lower compatible profiles: GL3
+                GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);                
+                if(PROFILE_ALIASING) {
+                    hasGL3   = true;
+                }
+                resetStates(); // clean context states, since creation was temporary
+            }
+        }
+        if(!hasGL3) {
+            hasGL3   = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE);    // GL3
+            success |= hasGL3;
+            if(hasGL3) {
+                resetStates(); // clean this context states, since creation was temporary                
+            }
+        }
         if(!hasGL4bc) {
             hasGL4bc = createContextARBMapVersionsAvailable(4, CTX_PROFILE_COMPAT);  // GL4bc
             success |= hasGL4bc;
             if(hasGL4bc) {
                 // Map all lower compatible profiles: GL3bc, GL2, GL4, GL3
-                GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions);
-                GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions);
-                GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE,   ctxMajorVersion, ctxMinorVersion, ctxOptions);
-                GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE,   ctxMajorVersion, ctxMinorVersion, ctxOptions);
+                GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+                GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+                if(!hasGL4) {
+                    GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+                }
+                if(!hasGL3) {
+                    GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+                }
                 if(PROFILE_ALIASING) {
                     hasGL3bc = true;
                     hasGL2   = true;
@@ -796,8 +886,10 @@ public abstract class GLContextImpl extends GLContext {
             success |= hasGL3bc;
             if(hasGL3bc) {
                 // Map all lower compatible profiles: GL2 and GL3
-                GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions);
-                GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE,   ctxMajorVersion, ctxMinorVersion, ctxOptions);
+                GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+                if(!hasGL3) {
+                    GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+                }
                 if(PROFILE_ALIASING) {
                     hasGL2   = true;
                     hasGL3   = true;
@@ -812,25 +904,6 @@ public abstract class GLContextImpl extends GLContext {
                 resetStates(); // clean this context states, since creation was temporary                
             }
         }
-        if(!hasGL4) {
-            hasGL4   = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE);    // GL4
-            success |= hasGL4;
-            if(hasGL4) {
-                // Map all lower compatible profiles: GL3
-                GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE,   ctxMajorVersion, ctxMinorVersion, ctxOptions);                
-                if(PROFILE_ALIASING) {
-                    hasGL3   = true;
-                }
-                resetStates(); // clean this context states, since creation was temporary
-            }
-        }
-        if(!hasGL3) {
-            hasGL3   = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE);    // GL3
-            success |= hasGL3;
-            if(hasGL3) {
-                resetStates(); // clean this context states, since creation was temporary                
-            }
-        }
         if(success) {
             // only claim GL versions set [and hence detected] if ARB context creation was successful
             GLContext.setAvailableGLVersionsSet(device);
@@ -883,7 +956,7 @@ public abstract class GLContextImpl extends GLContext {
                                         /* min */ majorMin, minorMin,
                                         /* res */ major, minor);
 
-    if(0==_context && CTX_PROFILE_CORE == reqProfile) {
+    if( 0 == _context && CTX_PROFILE_CORE == reqProfile && !PROFILE_ALIASING ) {
         // try w/ FORWARD instead of CORE
         ctp &= ~CTX_PROFILE_CORE ;
         ctp |=  CTX_OPTION_FORWARD ;
@@ -891,7 +964,7 @@ public abstract class GLContextImpl extends GLContext {
                                             /* max */ majorMax, minorMax,
                                             /* min */ majorMin, minorMin,
                                             /* res */ major, minor);
-       if(0==_context) {
+       if( 0 == _context ) {
             // Try a compatible one .. even though not requested .. last resort
             ctp &= ~CTX_PROFILE_CORE ;
             ctp &= ~CTX_OPTION_FORWARD ;
@@ -903,11 +976,11 @@ public abstract class GLContextImpl extends GLContext {
        }
     }
     final boolean res;
-    if(0!=_context) {
+    if( 0 != _context ) {
         AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
         // ctxMajorVersion, ctxMinorVersion, ctxOptions is being set by
         //   createContextARBVersions(..) -> setGLFunctionAvailbility(..) -> setContextVersion(..)
-        GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxMajorVersion, ctxMinorVersion, ctxOptions);
+        GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
         destroyContextARBImpl(_context);
         if (DEBUG) {
           System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable HAVE: " +reqMajor+"."+reqProfile+ " -> "+getGLVersion());
@@ -929,10 +1002,8 @@ public abstract class GLContextImpl extends GLContext {
     major[0]=majorMax;
     minor[0]=minorMax;
     long _context=0;
-    boolean ok = false;
 
-    while ( !ok &&
-            GLContext.isValidGLVersion(major[0], minor[0]) &&
+    while ( GLContext.isValidGLVersion(major[0], minor[0]) &&
             ( major[0]>majorMin || major[0]==majorMin && minor[0] >=minorMin ) ) {
         if (DEBUG) {
             System.err.println(getThreadName() + ": createContextARBVersions: share "+share+", direct "+direct+", version "+major[0]+"."+minor[0]);
@@ -940,29 +1011,16 @@ public abstract class GLContextImpl extends GLContext {
         _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]);
 
         if(0 != _context) {
-            ok = true;
-            setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags);
-        } else {
-            ok = false;
-        }
-
-        if(ok && major[0]>=3) {
-            int[] hasMajor = new int[1]; int[] hasMinor = new int[1];
-            gl.glGetIntegerv(GL2GL3.GL_MAJOR_VERSION, hasMajor, 0);
-            gl.glGetIntegerv(GL2GL3.GL_MINOR_VERSION, hasMinor, 0);
-            ok = hasMajor[0]>major[0] || ( hasMajor[0]==major[0] && hasMinor[0]>=minor[0] ) ;
-            if(!ok) {
-                removeCachedVersion(major[0], minor[0], ctxOptionFlags);
+            if( setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags, true) ) {
+                break;
+            } else {
                 destroyContextARBImpl(_context);
                 _context = 0;
             }
-            if (DEBUG) {
-                System.err.println(getThreadName() + ": createContextARBVersions: version verification - expected "+major[0]+"."+minor[0]+", has "+hasMajor[0]+"."+hasMinor[0]+" == "+ok);
-            }
         }
 
-        if(!ok) {
-            if(!GLContext.decrementGLVersion(major, minor)) break;
+        if(!GLContext.decrementGLVersion(major, minor)) {
+            break;
         }
     }
     return _context;
@@ -977,7 +1035,7 @@ public abstract class GLContextImpl extends GLContext {
    * If major > 0 || minor > 0 : Use passed values, determined at creation time
    * Otherwise .. don't touch ..
    */
-  private final void setContextVersion(int major, int minor, int ctp, boolean setVersionString) {
+  private final void setContextVersion(int major, int minor, int ctp, VersionNumberString glVendorVersion, boolean useGL) {
       if ( 0 == ctp ) {
         throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp));
       }
@@ -985,50 +1043,27 @@ public abstract class GLContextImpl extends GLContext {
       if (!GLContext.isValidGLVersion(major, minor)) {
         throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp));
       }
-      ctxMajorVersion = major;
-      ctxMinorVersion = minor;
+      ctxVersion = new VersionNumber(major, minor, 0);
+      ctxVersionString = getGLVersion(major, minor, ctxOptions, glVersion);
+      ctxVendorVersion = glVendorVersion;
       ctxOptions = ctp;
-      if(setVersionString) {
-          ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, gl.glGetString(GL.GL_VERSION));
-          ctxGLSLVersion = null;
-          if(ctxMajorVersion >= 2) { // >= ES2 || GL2.0
-              final String glslVersion = gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION);
+      if(useGL) {
+          ctxGLSLVersion = VersionNumber.zeroVersion;
+          if( hasGLSL() ) { // >= ES2 || GL2.0
+              final String glslVersion = isGLES() ? null : gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) ; // Use static GLSL version for ES to be safe!
               if( null != glslVersion ) {
-                  ctxGLSLVersion = new VersionNumber(glslVersion, ".");
+                  ctxGLSLVersion = new VersionNumber(glslVersion);
                   if( ctxGLSLVersion.getMajor() < 1 ) {
-                      ctxGLSLVersion = null; // failed ..
+                      ctxGLSLVersion = VersionNumber.zeroVersion; // failed ..
                   }
               }
+              if( ctxGLSLVersion.isZero() ) {
+                  ctxGLSLVersion = getStaticGLSLVersionNumber(major, minor, ctxOptions);
+              }
           } 
-          if( null == ctxGLSLVersion ){
-              final int[] sver = new int[2];
-              getStaticGLSLVersionNumber(ctxMajorVersion, ctxMinorVersion, ctxOptions, sver);
-              ctxGLSLVersion = new VersionNumber(sver[0], sver[1], 0);
-          }
       }
   }
   
-  private static final VersionNumber getGLVersionNumber(int ctp, String glVersionStr) {
-      if( null != glVersionStr ) {
-          final GLVersionNumber version = new GLVersionNumber(glVersionStr);
-          if (version.isValid()) {
-              int major = version.getMajor();
-              int minor = version.getMinor();
-              // We cannot promote a non ARB context to >= 3.1,
-              // reduce it to 3.0 then.
-              if ( 0 == (ctp & CTX_IS_ARB_CREATED) && 
-                   ( major > 3 || major == 3 && minor >= 1 ) ) {
-                  major = 3;
-                  minor = 0;
-              }
-              if ( GLContext.isValidGLVersion(major, minor) ) {
-                  return new VersionNumber(major, minor, 0);
-              }
-          }
-      }
-      return null;      
-  }
-
   //----------------------------------------------------------------------
   // Helpers for various context implementations
   //
@@ -1111,24 +1146,37 @@ public abstract class GLContextImpl extends GLContext {
 
   /** Helper routine which resets a ProcAddressTable generated by the
       GLEmitter by looking up anew all of its function pointers. */
-  protected final void resetProcAddressTable(ProcAddressTable table) {
-    table.reset(getDrawableImpl().getGLDynamicLookupHelper() );
+  protected final void resetProcAddressTable(final ProcAddressTable table) {
+    AccessController.doPrivileged(new PrivilegedAction<Object>() {
+        public Object run() {
+            table.reset(getDrawableImpl().getGLDynamicLookupHelper() );
+            return null;
+        }
+    } );
   }
-
+  
   private final boolean initGLRendererAndGLVersionStrings()  {
     final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper();
     final long _glGetString = glDynLookupHelper.dynamicLookupFunction("glGetString");
     if(0 == _glGetString) {
-        // FIXME
-        System.err.println("Warning: Entry point to 'glGetString' is NULL.");
+        System.err.println("Error: Entry point to 'glGetString' is NULL.");
         if(DEBUG) {
             Thread.dumpStack();
         }
         return false;
     } else {
+        final String _glVendor = glGetStringInt(GL.GL_VENDOR, _glGetString);
+        if(null == _glVendor) {
+            if(DEBUG) {
+                System.err.println("Warning: GL_VENDOR is NULL.");
+                Thread.dumpStack();
+            }
+            return false;
+        }
+        glVendor = _glVendor;
+        
         final String _glRenderer = glGetStringInt(GL.GL_RENDERER, _glGetString);
         if(null == _glRenderer) {
-            // FIXME
             if(DEBUG) {
                 System.err.println("Warning: GL_RENDERER is NULL.");
                 Thread.dumpStack();
@@ -1148,17 +1196,77 @@ public abstract class GLContextImpl extends GLContext {
             return false;
         }
         glVersion = _glVersion;
+        
         return true;
     }
   }
 
   /**
+   * We cannot promote a non ARB context to >= 3.1, reduce it to 3.0 then.
+   */
+  private static void limitNonARBContextVersion(int[] major, int[] minor, int ctp) {
+      if ( 0 == (ctp & CTX_IS_ARB_CREATED) && ( major[0] > 3 || major[0] == 3 && minor[0] >= 1 ) ) {
+          major[0] = 3;
+          minor[0] = 0;
+      }
+  }
+  
+  /**
+   * Returns null if version string is invalid, otherwise a valid instance.
+   * <p>
+   * Note: Non ARB ctx is limited to GL 3.0.
+   * </p>
+   */
+  private static final VersionNumber getGLVersionNumber(int ctp, String glVersionStr) {
+      if( null != glVersionStr ) {
+          final GLVersionNumber version = GLVersionNumber.create(glVersionStr);
+          if ( version.isValid() ) {
+              int[] major = new int[] { version.getMajor() };
+              int[] minor = new int[] { version.getMinor() };
+              limitNonARBContextVersion(major, minor, ctp);
+              if ( GLContext.isValidGLVersion(major[0], minor[0]) ) {
+                  return new VersionNumber(major[0], minor[0], 0);
+              }
+          }
+      }
+      return null;
+  }
+
+  /**
+   * Returns false if <code>glGetIntegerv</code> is inaccessible, otherwise queries major.minor
+   * version for given arrays.
+   * <p>
+   * If the GL query fails, major will be zero.
+   * </p> 
+   * <p>
+   * Note: Non ARB ctx is limited to GL 3.0.
+   * </p>
+   */
+  private final boolean getGLIntVersion(int[] glIntMajor, int[] glIntMinor, int ctp)  {
+    glIntMajor[0] = 0; // clear
+    final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper();
+    final long _glGetIntegerv = glDynLookupHelper.dynamicLookupFunction("glGetIntegerv");
+    if( 0 == _glGetIntegerv ) {
+        System.err.println("Error: Entry point to 'glGetIntegerv' is NULL.");
+        if(DEBUG) {
+            Thread.dumpStack();
+        }
+        return false;        
+    } else {
+        glGetIntegervInt(GL2GL3.GL_MAJOR_VERSION, glIntMajor, 0, _glGetIntegerv);
+        glGetIntegervInt(GL2GL3.GL_MINOR_VERSION, glIntMinor, 0, _glGetIntegerv);
+        limitNonARBContextVersion(glIntMajor, glIntMinor, ctp);
+        return true;        
+    }
+  }
+  
+  /**
    * Sets the OpenGL implementation class and
    * the cache of which GL functions are available for calling through this
    * context. See {@link #isFunctionAvailable(String)} for more information on
    * the definition of "available".
    * <br>
-   * All ProcaddressTables are being determined, the GL version is being set
+   * All ProcaddressTables are being determined and cached, the GL version is being set
    * and the extension cache is determined as well.
    *
    * @param force force the setting, even if is already being set.
@@ -1166,17 +1274,27 @@ public abstract class GLContextImpl extends GLContext {
    * @param major OpenGL major version
    * @param minor OpenGL minor version
    * @param ctxProfileBits OpenGL context profile and option bits, see {@link javax.media.opengl.GLContext#CTX_OPTION_ANY}
-   *
+   * @param strictMatch if <code>true</code> the ctx must
+   *                    <ul>
+   *                      <li>be greater or equal than the requested <code>major.minor</code> version, and</li>
+   *                      <li>match the ctxProfileBits</li>
+   *                    </ul>, otherwise method aborts and returns <code>false</code>.
+   * @return returns <code>true</code> if successful, otherwise <code>false</code>. See <code>strictMatch</code>. 
+   *                 If <code>false</code> is returned, no data has been cached or mapped, i.e. ProcAddressTable, Extensions, Version, etc. 
    * @see #setContextVersion
    * @see javax.media.opengl.GLContext#CTX_OPTION_ANY
    * @see javax.media.opengl.GLContext#CTX_PROFILE_COMPAT
    * @see javax.media.opengl.GLContext#CTX_IMPL_ES2_COMPAT
    */
-  protected final void setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits) {
+  protected final boolean setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits, boolean strictMatch) {
     if(null!=this.gl && null!=glProcAddressTable && !force) {
-        return; // already done and not forced
+        return true; // already done and not forced
     }
 
+    if ( 0 < major && !GLContext.isValidGLVersion(major, minor) ) {
+        throw new GLException("Invalid GL Version Request "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
+    }
+    
     if(null==this.gl || !verifyInstance(gl.getGLProfile(), "Impl", this.gl)) {
         setGL( createGL( getGLDrawable().getGLProfile() ) );
     }
@@ -1187,42 +1305,130 @@ public abstract class GLContextImpl extends GLContext {
     
     {
         final boolean initGLRendererAndGLVersionStringsOK = initGLRendererAndGLVersionStrings();
-        if(DEBUG) {
-            if( !initGLRendererAndGLVersionStringsOK ) {
-                System.err.println("Warning: setGLFunctionAvailability: intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
+        if( !initGLRendererAndGLVersionStringsOK ) {
+            final String errMsg = "Intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null);
+            if( strictMatch ) {
+                // query mode .. simply fail
+                if(DEBUG) {
+                    System.err.println("Warning: setGLFunctionAvailability: "+errMsg);
+                }
+                return false;
             } else {
-                System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Given "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion));
+                // unusable GL context - non query mode - hard fail!
+                throw new GLException(errMsg);
             }
+        } else if(DEBUG) {
+            System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Given "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion));
         }
     }
-
-    if(!isCurrentContextHardwareRasterizer()) {
-        ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
-    }
     
-    // Pick the version from the GL-version string, 
-    // if smaller _or_ given major == 0.
-    final VersionNumber glVersionNumber;
+    //
+    // Validate GL version either by GL-Integer or GL-String
+    //
+    if (DEBUG) {
+        System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Pre version verification - expected "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+", strictMatch "+strictMatch);
+    }
+    boolean versionValidated = false;
+    boolean versionGL3IntFailed = false;
     {
+        // Validate the requested version w/ the GL-version from an integer query. 
+        final int[] glIntMajor = new int[] { 0 }, glIntMinor = new int[] { 0 }; 
+        final boolean getGLIntVersionOK = getGLIntVersion(glIntMajor, glIntMinor, ctxProfileBits);
+        if( !getGLIntVersionOK ) {
+            final String errMsg = "Fetching GL Integer Version failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null);
+            if( strictMatch ) {
+                // query mode .. simply fail
+                if(DEBUG) {
+                    System.err.println("Warning: setGLFunctionAvailability: "+errMsg);
+                }
+                return false;
+            } else {
+                // unusable GL context - non query mode - hard fail!
+                throw new GLException(errMsg);
+            }
+        }        
+        if (DEBUG) {
+            System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: version verification (Int): "+glVersion+", "+glIntMajor[0]+"."+glIntMinor[0]);
+        }
+        
+        // Only validate if a valid int version was fetched, otherwise cont. w/ version-string method -> 3.0 > Version || Version > MAX!
+        if ( GLContext.isValidGLVersion(glIntMajor[0], glIntMinor[0]) ) {
+            if( glIntMajor[0]<major || ( glIntMajor[0]==major && glIntMinor[0]<minor ) || 0 == major ) {        
+                if( strictMatch && 2 < major ) { // relaxed match for versions major < 3 requests, last resort!
+                    if(DEBUG) {
+                        System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (Int): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+glIntMajor[0]+"."+glIntMinor[0]);
+                    }
+                    return false;
+                }
+                major = glIntMajor[0];
+                minor = glIntMinor[0];
+            }
+            versionValidated = true;
+        } else {
+            versionGL3IntFailed = true;
+        }
+    }
+    if( !versionValidated ) {
+        // Validate the requested version w/ the GL-version from the version string. 
         final VersionNumber setGLVersionNumber = new VersionNumber(major, minor, 0);
         final VersionNumber strGLVersionNumber = getGLVersionNumber(ctxProfileBits, glVersion);
-        if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) <= 0 || 0 == major ) ) {
-            glVersionNumber = strGLVersionNumber;
-            major = glVersionNumber.getMajor();
-            minor = glVersionNumber.getMinor();
-        } else {
-            glVersionNumber = setGLVersionNumber;
+        if (DEBUG) {
+            System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: version verification (String): "+glVersion+", "+strGLVersionNumber);
+        }
+        
+        // Only validate if a valid string version was fetched -> MIN > Version || Version > MAX!
+        if( null != strGLVersionNumber ) {
+            if( strGLVersionNumber.compareTo(setGLVersionNumber) < 0 || 0 == major ) {
+                if( strictMatch && 2 < major ) { // relaxed match for versions major < 3 requests, last resort!
+                    if(DEBUG) {
+                        System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (String): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+strGLVersionNumber);
+                    }
+                    return false;
+                }
+                major = strGLVersionNumber.getMajor();
+                minor = strGLVersionNumber.getMinor();
+            }
+            if( strictMatch && versionGL3IntFailed && major >= 3 ) {
+                if(DEBUG) {
+                    System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL3 version Int failed, String: "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+strGLVersionNumber);
+                }
+                return false;            
+            }
+            versionValidated = true;
         }
     }
-    if ( !GLContext.isValidGLVersion(major, minor) ) {
-        throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctxProfileBits)+", "+glVersion+", "+glVersionNumber);
+    if( strictMatch && !versionValidated && 0 < major ) {
+        if(DEBUG) {
+            System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, No GL version validation possible: "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion);
+        }
+        return false;                    
     }
+    if (DEBUG) {
+        System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: post version verification "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+", strictMatch "+strictMatch+", versionValidated "+versionValidated+", versionGL3IntFailed "+versionGL3IntFailed);
+    }
+    
     if( 2 > major ) { // there is no ES2-compat for a profile w/ major < 2
         ctxProfileBits &= ~GLContext.CTX_IMPL_ES2_COMPAT;
     }
+    
+    final VersionNumberString vendorVersion = GLVersionNumber.createVendorVersion(glVersion);
+    
+    setRendererQuirks(adevice, major, minor, ctxProfileBits, vendorVersion);
+    
+    if( strictMatch && glRendererQuirks.exist(GLRendererQuirks.GLNonCompliant) ) {
+        if(DEBUG) {
+            System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL is not compliant: "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)+", "+glRenderer);
+        }
+        return false;
+    }
+    
+    if(!isCurrentContextHardwareRasterizer()) {
+        ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
+    }
+
     contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits);
     if (DEBUG) {
-        System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion) + ", "+glVersionNumber);
+        System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion));
     }
 
     //
@@ -1268,7 +1474,7 @@ public abstract class GLContextImpl extends GLContext {
         }
     } else {
         extensionAvailability = new ExtensionAvailabilityCache();
-        setContextVersion(major, minor, ctxProfileBits, false); // pre-set of GL version, required for extension cache usage
+        setContextVersion(major, minor, ctxProfileBits, vendorVersion, false); // pre-set of GL version, required for extension cache usage
         extensionAvailability.reset(this);
         synchronized(mappedContextTypeObjectLock) {
             mappedExtensionAvailabilityCache.put(contextFQN, extensionAvailability);
@@ -1292,53 +1498,150 @@ public abstract class GLContextImpl extends GLContext {
     //
     // Set GL Version (complete w/ version string)
     //
-    setContextVersion(major, minor, ctxProfileBits, true);
+    setContextVersion(major, minor, ctxProfileBits, vendorVersion, true);
     
-    setRendererQuirks( 0 == ( ctxProfileBits & GLContext.CTX_IMPL_ACCEL_SOFT ) );
-
     setDefaultSwapInterval();
     
+    final int glErrX = gl.glGetError(); // clear GL error, maybe caused by above operations
+    
     if(DEBUG) {
-        System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null));
+        System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: OK "+contextFQN+" - "+GLContext.getGLVersion(ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions, null)+" - glErr "+toHexString(glErrX));
     }
+    return true;
   }
   
-  private final void setRendererQuirks(boolean hwAccel) {
-    int[] quirks = new int[GLRendererQuirks.COUNT];
+  private final void setRendererQuirks(final AbstractGraphicsDevice adevice, int major, int minor, int ctp, final VersionNumberString vendorVersion) {
+    int[] quirks = new int[GLRendererQuirks.COUNT + 1]; // + 1 ( NoFullFBOSupport )
     int i = 0;
     
+    final String MesaSP = "Mesa ";
+    final String MesaRendererAMDsp = " AMD "; 
+    final String MesaRendererIntelsp = "Intel(R)"; 
+    final boolean hwAccel = 0 == ( ctp & GLContext.CTX_IMPL_ACCEL_SOFT );
+    final boolean compatCtx = 0 != ( ctp & GLContext.CTX_PROFILE_COMPAT );
+    final boolean isDriverMesa = glRenderer.contains(MesaSP) || glRenderer.contains("Gallium ");
+    final boolean isDriverATICatalyst = !isDriverMesa && ( glVendor.contains("ATI Technologies") || glRenderer.startsWith("ATI ") );
+    final boolean isDriverNVIDIAGeForce = !isDriverMesa && ( glVendor.contains("NVIDIA Corporation") || glRenderer.contains("NVIDIA ") );
+    
+    //
     // OS related quirks
+    //
     if( Platform.getOSType() == Platform.OSType.MACOS ) {
-        final int quirk1 = GLRendererQuirks.NoOffscreenBitmap;
-        if(DEBUG) {
-            System.err.println("Quirk: "+GLRendererQuirks.toString(quirk1)+": cause: OS "+Platform.getOSType());
+        //
+        // OSX
+        //
+        {
+            final int quirk = GLRendererQuirks.NoOffscreenBitmap;
+            if(DEBUG) {
+                System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+            }
+            quirks[i++] = quirk;
         }
-        quirks[i++] = quirk1;
-    } else if( Platform.getOSType() == Platform.OSType.WINDOWS ) {
-        final int quirk = GLRendererQuirks.NoDoubleBufferedBitmap;
-        if(DEBUG) {
-            System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+        
+        final VersionNumber OSXVersion173 = new VersionNumber(1,7,3);
+        if( Platform.getOSVersionNumber().compareTo(OSXVersion173) < 0 && isDriverNVIDIAGeForce ) {
+            final int quirk = GLRendererQuirks.GLFlushBeforeRelease;
+            if(DEBUG) {
+                System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", Renderer "+glRenderer);
+            }
+            quirks[i++] = quirk;
+        }
+    } else if( Platform.getOSType() == Platform.OSType.WINDOWS ) {        
+        //
+        // WINDOWS
+        //
+        {
+            final int quirk = GLRendererQuirks.NoDoubleBufferedBitmap;
+            if(DEBUG) {
+                System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+            }
+            quirks[i++] = quirk;
+        }
+        
+        if( isDriverATICatalyst ) {
+            final VersionNumber winXPVersionNumber = new VersionNumber ( 5, 1, 0);          
+            final VersionNumber amdSafeMobilityVersion = new VersionNumber(12, 102, 3);  
+            
+            if ( vendorVersion.compareTo(amdSafeMobilityVersion) < 0 ) { // includes: vendorVersion.isZero()
+                final int quirk = GLRendererQuirks.NeedCurrCtx4ARBCreateContext;
+                if(DEBUG) {
+                    System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", [Vendor "+glVendor+" or Renderer "+glRenderer+"], driverVersion "+vendorVersion);
+                }
+                quirks[i++] = quirk;                
+            }
+            
+            if( Platform.getOSVersionNumber().compareTo(winXPVersionNumber) <= 0 ) {
+                final int quirk = GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries;
+                if(DEBUG) {
+                    System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS-Version "+Platform.getOSType()+" "+Platform.getOSVersionNumber()+", [Vendor "+glVendor+" or Renderer "+glRenderer+"]");
+                }
+                quirks[i++] = quirk;                
+            }
+        }
+    } else if( Platform.OSType.ANDROID == Platform.getOSType() ) {    
+        //
+        // ANDROID
+        //
+        // Renderer related quirks, may also involve OS
+        if( glRenderer.contains("PowerVR") ) {
+            final int quirk = GLRendererQuirks.NoSetSwapInterval;
+            if(DEBUG) {
+                System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer);
+            }
+            quirks[i++] = quirk;
         }
-        quirks[i++] = quirk;
     }
     
-    // Renderer related quirks, may also involve OS
-    if( Platform.OSType.ANDROID == Platform.getOSType() && glRendererLowerCase.contains("powervr") ) {
-        final int quirk = GLRendererQuirks.NoSetSwapInterval;
-        if(DEBUG) {
-            System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer);
+    //
+    // Windowing Toolkit related quirks
+    //
+    if( NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
+        //
+        // X11
+        //
+        {
+            //
+            // Quirk: DontCloseX11Display
+            //
+            final int quirk = GLRendererQuirks.DontCloseX11Display;
+            if( glRenderer.contains(MesaSP) ) {
+                if ( glRenderer.contains("X11") && vendorVersion.compareTo(Version80) < 0 ) {
+                    if(DEBUG) {
+                        System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]");
+                    }
+                    quirks[i++] = quirk;
+                }
+            } else if( isDriverATICatalyst ) {
+                {
+                    if(DEBUG) {
+                        System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer);
+                    }
+                    quirks[i++] = quirk;
+                }
+            } else if( jogamp.nativewindow.x11.X11Util.getMarkAllDisplaysUnclosable() ) {
+                {
+                    if(DEBUG) {
+                        System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11Util Downstream");
+                    }
+                    quirks[i++] = quirk;
+                }
+            }
         }
-        quirks[i++] = quirk;
     }
-    if( glRendererLowerCase.contains("mesa") || glRendererLowerCase.contains("gallium") ) {
+    
+    
+    //
+    // RENDERER related quirks
+    //
+    if( isDriverMesa ) {
         {
             final int quirk = GLRendererQuirks.NoSetSwapIntervalPostRetarget;
             if(DEBUG) {
                 System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
             }
-            quirks[i++] = quirk;            
+            quirks[i++] = quirk;
         }
-        if( hwAccel /* glRendererLowerCase.contains("intel(r)") || glRendererLowerCase.contains("amd") */ )
+        if( hwAccel /* glRenderer.contains( MesaRendererIntelsp ) || glRenderer.contains( MesaRendererAMDsp ) */ )
         {
             final int quirk = GLRendererQuirks.NoDoubleBufferedPBuffer;
             if(DEBUG) {
@@ -1346,11 +1649,44 @@ public abstract class GLContextImpl extends GLContext {
             }
             quirks[i++] = quirk;
         }
+        if( ( (glRenderer.contains( MesaRendererIntelsp ) && compatCtx) || glRenderer.contains( MesaRendererAMDsp ) ) && 
+            ( major > 3 || major == 3 && minor >= 1 ) 
+          )
+        {
+            // FIXME: Apply vendor version constraints!
+            final int quirk = GLRendererQuirks.GLNonCompliant;
+            if(DEBUG) {
+                System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
+            }
+            quirks[i++] = quirk;
+        }
+        if( Platform.getOSType() == Platform.OSType.WINDOWS && glRenderer.contains("SVGA3D") )
+        {
+            final VersionNumber mesaSafeFBOVersion = new VersionNumber(8, 0, 0);              
+            if ( vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) { // includes: vendorVersion.isZero()            
+                final int quirk = GLRendererQuirks.NoFullFBOSupport;
+                if(DEBUG) {
+                    System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
+                }
+                quirks[i++] = quirk;
+            }
+        }
+    }
+    
+    //
+    // Property related quirks
+    //
+    if( FORCE_MIN_FBO_SUPPORT ) {
+        final int quirk = GLRendererQuirks.NoFullFBOSupport;
+        if(DEBUG) {
+            System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: property");
+        }
+        quirks[i++] = quirk;        
     }
+    
     glRendererQuirks = new GLRendererQuirks(quirks, 0, i);
   }
-  
-  
+    
   private static final boolean hasFBOImpl(int major, int ctp, ExtensionAvailabilityCache extCache) {
     return ( 0 != (ctp & CTX_PROFILE_ES) && major >= 2 ) ||   // ES >= 2.0
             
@@ -1380,16 +1716,18 @@ public abstract class GLContextImpl extends GLContext {
     }
 
     synchronized(mappedContextTypeObjectLock) {
-        ProcAddressTable table = mappedGLProcAddress.remove( contextFQN );
+        final ProcAddressTable table = mappedGLProcAddress.remove( contextFQN );
         if(DEBUG) {
-            System.err.println(getThreadName() + ": RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+table.hashCode());
+            final int hc = null != table ? table.hashCode() : 0;
+            System.err.println(getThreadName() + ": RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+toHexString(hc));
         }
     }
 
     synchronized(mappedContextTypeObjectLock) {
-        ExtensionAvailabilityCache  eCache = mappedExtensionAvailabilityCache.remove( contextFQN );
+        final ExtensionAvailabilityCache  eCache = mappedExtensionAvailabilityCache.remove( contextFQN );
         if(DEBUG) {
-            System.err.println(getThreadName() + ": RM GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+eCache.hashCode());
+            final int hc = null != eCache ? eCache.hashCode() : 0;
+            System.err.println(getThreadName() + ": RM GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+toHexString(hc));
         }
     }
   }
@@ -1400,8 +1738,8 @@ public abstract class GLContextImpl extends GLContext {
     if(!drawable.getChosenGLCapabilities().getHardwareAccelerated()) {
         isHardwareRasterizer = false;
     } else {
-        isHardwareRasterizer = ! ( glRendererLowerCase.contains("software") /* Mesa3D */  ||
-                                   glRendererLowerCase.contains("mesa x11") /* Mesa3D*/   ||
+        isHardwareRasterizer = ! ( glRendererLowerCase.contains("software") /* Mesa3D  */ ||
+                                   glRendererLowerCase.contains("mesa x11") /* Mesa3D  */ ||
                                    glRendererLowerCase.contains("softpipe") /* Gallium */ ||
                                    glRendererLowerCase.contains("llvmpipe") /* Gallium */
                                  );
@@ -1421,7 +1759,7 @@ public abstract class GLContextImpl extends GLContext {
     // Check GL 1st (cached)
     if(null!=glProcAddressTable) { // null if this context wasn't not created
         try {
-            if(0!=glProcAddressTable.getAddressFor(glFunctionName)) {
+            if( glProcAddressTable.isFunctionAvailable( glFunctionName ) ) {
                 return true;
             }
         } catch (Exception e) {}
@@ -1431,27 +1769,24 @@ public abstract class GLContextImpl extends GLContext {
     final ProcAddressTable pTable = getPlatformExtProcAddressTable();
     if(null!=pTable) {
         try {
-            if(0!=pTable.getAddressFor(glFunctionName)) {
+            if( pTable.isFunctionAvailable( glFunctionName ) ) {
                 return true;
             }
         } catch (Exception e) {}
     }
 
     // dynamic function lookup at last incl name aliasing (not cached)
-    DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
-    String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true);
-    long addr = 0;
+    final DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
+    final String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true);
+    boolean res = false;
     int  variants = GLNameResolver.getFuncNamePermutationNumber(tmpBase);
-    for(int i = 0; 0==addr && i < variants; i++) {
-        String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i);
+    for(int i = 0; !res && i < variants; i++) {
+        final String tmp = GLNameResolver.getFuncNamePermutation(tmpBase, i);
         try {
-            addr = dynLookup.dynamicLookupFunction(tmp);
+            res = dynLookup.isFunctionAvailable(tmp);
         } catch (Exception e) { }
     }
-    if(0!=addr) {
-        return true;
-    }
-    return false;
+    return res;
   }
 
   @Override
@@ -1502,7 +1837,7 @@ public abstract class GLContextImpl extends GLContext {
       return device.getUniqueID() + "-" + toHexString(composeBits(major, minor, ctxProfileBits));
   }
 
-  protected String getContextFQN() {
+  protected final String getContextFQN() {
       return contextFQN;
   }
 
@@ -1513,44 +1848,105 @@ public abstract class GLContextImpl extends GLContext {
     throw new GLException("Not supported on non-pbuffer contexts");
   }
 
-  /** On some platforms the mismatch between OpenGL's coordinate
-      system (origin at bottom left) and the window system's
-      coordinate system (origin at top left) necessitates a vertical
-      flip of pixels read from offscreen contexts. */
-  public abstract boolean offscreenImageNeedsVerticalFlip();
-
-  /** Only called for offscreen contexts; needed by glReadPixels */
-  public abstract int getOffscreenContextPixelDataType();
+  @Override
+  public int getDefaultPixelDataType() {
+      evalPixelDataType();
+      return pixelDataType;
+  }
 
+  @Override
+  public int getDefaultPixelDataFormat() {
+      evalPixelDataType();
+      return pixelDataFormat;
+  }
+  
+  private final void evalPixelDataType() {
+    if(!pixelDataEvaluated) {
+        synchronized(this) {
+            if(!pixelDataEvaluated) {
+                /* if(isGL2GL3() && 3 == components) {
+                    pixelDataInternalFormat=GL.GL_RGB;
+                    pixelDataFormat=GL.GL_RGB;
+                    pixelDataType = GL.GL_UNSIGNED_BYTE;            
+                } else */ if(isGLES2Compatible() || isExtensionAvailable(GLExtensions.OES_read_format)) {
+                    final int[] glImplColorReadVals = new int[] { 0, 0 };
+                    gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
+                    gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);            
+                    // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
+                    pixelDataFormat = glImplColorReadVals[0];
+                    pixelDataType = glImplColorReadVals[1];
+                } else {
+                    // RGBA read is safe for all GL profiles 
+                    // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
+                    pixelDataFormat=GL.GL_RGBA;
+                    pixelDataType = GL.GL_UNSIGNED_BYTE;
+                }            
+                // TODO: Consider:
+                // return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
+                pixelDataEvaluated = true;
+            }
+        }
+    }
+  }
 
   //----------------------------------------------------------------------
   // Helpers for buffer object optimizations
 
-  public void setBufferSizeTracker(GLBufferSizeTracker bufferSizeTracker) {
+  public final void setBufferSizeTracker(GLBufferSizeTracker bufferSizeTracker) {
     this.bufferSizeTracker = bufferSizeTracker;
   }
 
-  public GLBufferSizeTracker getBufferSizeTracker() {
+  public final GLBufferSizeTracker getBufferSizeTracker() {
     return bufferSizeTracker;
   }
 
-  public GLBufferStateTracker getBufferStateTracker() {
+  public final GLBufferStateTracker getBufferStateTracker() {
     return bufferStateTracker;
   }
 
-  public GLStateTracker getGLStateTracker() {
+  public final GLStateTracker getGLStateTracker() {
     return glStateTracker;
   }
+  
+  public final boolean isDefaultVAO(int vao) {
+      return defaultVAO == vao;
+  }
 
   //---------------------------------------------------------------------------
   // Helpers for context optimization where the last context is left
   // current on the OpenGL worker thread
   //
 
-  public boolean hasWaiters() {
+  /** 
+   * Returns true if the given thread is owner, otherwise false.
+   * <p>
+   * Method exists merely for code validation of {@link #isCurrent()}.
+   * </p> 
+   */
+  public final boolean isOwner(Thread thread) {
+      return lock.isOwner(thread);
+  }
+  
+  /** 
+   * Returns true if there are other threads waiting for this GLContext to {@link #makeCurrent()}, otherwise false.
+   * <p>
+   * Since method does not perform any synchronization, accurate result are returned if lock is hold - only.
+   * </p> 
+   */
+  public final boolean hasWaiters() {
     return lock.getQueueLength()>0;
   }
-
+  
+  /** 
+   * Returns the number of hold locks. See {@link RecursiveLock#getHoldCount()} for semantics.
+   * <p>
+   * Since method does not perform any synchronization, accurate result are returned if lock is hold - only.
+   * </p> 
+   */
+  public final int getLockCount() {
+      return lock.getHoldCount();
+  }
+  
   //---------------------------------------------------------------------------
   // Special FBO hook
   //
@@ -1599,8 +1995,10 @@ public abstract class GLContextImpl extends GLContext {
   @Override
   public final int getDefaultDrawFramebuffer() { return drawable.getDefaultDrawFramebuffer(); }  
   @Override
-  public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); }
-  
+  public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); }  
+  @Override
+  public final int getDefaultReadBuffer() { return drawable.getDefaultReadBuffer(gl); }
+    
   //---------------------------------------------------------------------------
   // GL_ARB_debug_output, GL_AMD_debug_output helpers
   //
@@ -1688,5 +2086,8 @@ public abstract class GLContextImpl extends GLContext {
   }
 
   /** Internal bootstraping glGetString(GL_RENDERER) */
-  protected static native String glGetStringInt(int name, long procAddress);
+  private static native String glGetStringInt(int name, long procAddress);
+  
+  /** Internal bootstraping glGetIntegerv(..) for version */
+  private static native void glGetIntegervInt(int pname, int[] params, int params_offset, long procAddress);
 }
diff --git a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
index 0000e61..10cdd51 100644
--- a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
+++ b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
@@ -27,6 +27,8 @@
  */
 package jogamp.opengl;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 
 import javax.media.nativewindow.NativeWindowException;
@@ -39,8 +41,6 @@ import com.jogamp.common.os.Platform;
 import com.jogamp.gluegen.runtime.ProcAddressTable;
 import com.jogamp.opengl.GLExtensions;
 
-import jogamp.opengl.gl4.GL4bcProcAddressTable;
-
 /**
  * The GLDebugMessageHandler, handling <i>GL_ARB_debug_output</i> or <i>GL_AMD_debug_output</i>
  * debug messages.<br>
@@ -107,6 +107,18 @@ public class GLDebugMessageHandler {
         }
     }
     
+    private final long getAddressFor(final ProcAddressTable table, final String functionName) {
+        return AccessController.doPrivileged(new PrivilegedAction<Long>() {
+            public Long run() {
+                try {
+                    return Long.valueOf( table.getAddressFor(functionName) );
+                } catch (IllegalArgumentException iae) { 
+                    return Long.valueOf(0);
+                }
+            }
+        } ).longValue();
+    }
+
     public void init() {
         ctx.validateCurrent();
         if( isAvailable()) {
@@ -148,17 +160,17 @@ public class GLDebugMessageHandler {
         }
                 
         final ProcAddressTable procAddressTable = ctx.getGLProcAddressTable();
-        if( procAddressTable instanceof GL4bcProcAddressTable) {
-            final GL4bcProcAddressTable desktopProcAddressTable = (GL4bcProcAddressTable)procAddressTable;
+        if( !ctx.isGLES1() && !ctx.isGLES2() ) {
             switch(extType) {
                 case EXT_ARB: 
-                    glDebugMessageCallbackProcAddress = desktopProcAddressTable._addressof_glDebugMessageCallbackARB;
+                    glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallbackARB");
                     break;
                 case EXT_AMD: 
-                    glDebugMessageCallbackProcAddress = desktopProcAddressTable._addressof_glDebugMessageCallbackAMD;
+                    glDebugMessageCallbackProcAddress = getAddressFor(procAddressTable, "glDebugMessageCallbackAMD");
                     break;
             }
         } else {
+            glDebugMessageCallbackProcAddress = 0;
             if(DEBUG) {
                 System.err.println("Non desktop context not supported");    
             }            
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index 2bb22f7..4ac4135 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -80,30 +80,61 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
     super();
   }
 
-  @Override
-  public GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device) {
-      final GLContext ctx = getOrCreateSharedContextImpl(device);
-      if(null != ctx) {
-          return ctx.getRendererQuirks();
+  /**
+   * Returns the shared resource mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()},
+   * either a pre-existing or newly created, or <code>null</code> if creation failed or not supported.<br>
+   * Creation of the shared resource is tried only once.
+   *
+   * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+   */
+  protected final SharedResourceRunner.Resource getOrCreateSharedResource(AbstractGraphicsDevice device) {
+      try {
+          device = validateDevice(device);
+          if( null != device) {
+              return getOrCreateSharedResourceImpl( device );
+          }
+      } catch (GLException gle) {
+          if(DEBUG) {
+              System.err.println("Catched Exception on thread "+getThreadName()); 
+              gle.printStackTrace();
+          }
       }
       return null;
   }
-
+  protected abstract SharedResourceRunner.Resource getOrCreateSharedResourceImpl(AbstractGraphicsDevice device);
+  
   /**
    * Returns the shared context mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()},
-   * either a pre-existing or newly created, or <code>null</code> if creation failed or not supported.<br>
+   * either a pre-existing or newly created, or <code>null</code> if creation failed or <b>not supported</b>.<br>
    * Creation of the shared context is tried only once.
    *
    * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
    */
   public final GLContext getOrCreateSharedContext(AbstractGraphicsDevice device) {
-      device = validateDevice(device);
-      if(null!=device) {
-        return getOrCreateSharedContextImpl(device);
+      final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+      if(null!=sr) {
+        return sr.getContext();
+      }
+      return null;
+  }
+
+  @Override
+  protected final boolean createSharedResourceImpl(AbstractGraphicsDevice device) {
+      final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+      if(null!=sr) {
+          return sr.isValid();
+      }
+      return false;
+  }
+
+  @Override
+  public final GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device) {
+      final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+      if(null!=sr) {
+          return sr.getRendererQuirks();
       }
       return null;
   }
-  protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device);
 
   /**
    * Returns the shared device mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()},
@@ -113,15 +144,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
    * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
    */
   protected final AbstractGraphicsDevice getOrCreateSharedDevice(AbstractGraphicsDevice device) {
-      device = validateDevice(device);
-      if( null != device) {
-          return getOrCreateSharedDeviceImpl(device);
+      final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+      if(null!=sr) {
+        return sr.getDevice();
       }
       return null;
   }
-  protected abstract AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device);
 
-  
   /**
    * Returns the GLDynamicLookupHelper
    * @param profile if EGL/ES, profile <code>1</code> refers to ES1 and <code>2</code> to ES2,
@@ -147,6 +176,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
         final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
         if(null != ols) {
             final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, this, adevice);
+            
             // layered surface -> Offscreen/[FBO|PBuffer]
             if( !chosenCapsMod.isFBO() && !chosenCapsMod.isPBuffer() ) {
                 throw new GLException("Neither FBO nor Pbuffer is available for "+chosenCapsMod+", "+target);
@@ -155,7 +185,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
             ols.setChosenCapabilities(chosenCapsMod);
             if(DEBUG) {
                 System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer");
-                System.err.println("chosenCaps: "+chosenCaps);
+                System.err.println("chosenCaps:    "+chosenCaps);
                 System.err.println("chosenCapsMod: "+chosenCapsMod);
                 System.err.println("OffscreenLayerSurface: **** "+ols);
                 System.err.println("Target: **** "+target);
@@ -165,7 +195,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
                 throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
             }            
             if( chosenCapsMod.isFBO() ) {
-                // target surface is already a native one
                 result = createFBODrawableImpl(target, chosenCapsMod, 0);
             } else {            
                 result = createOffscreenDrawableImpl(target);
@@ -273,7 +302,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
                                                              GLCapabilitiesChooser chooser,
                                                              int width, int height,
                                                              GLContext shareWith) {
-    final GLDrawable drawable = createOffscreenDrawable( deviceReq, capsRequested, chooser, width, height ); 
+    final GLDrawable drawable = createOffscreenDrawable( deviceReq, capsRequested, chooser, width, height );
     drawable.setRealized(true);
     final GLContext context = drawable.createContext(shareWith);
     if(drawable instanceof GLFBODrawableImpl) {
@@ -297,20 +326,14 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
     
     final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, this, device);
 
-    if( capsChosen.isFBO() ) {
-        device.lock();
-        try {
+    device.lock();
+    try {
+        if( capsChosen.isFBO() ) {
             // Use minimum GLCapabilities for the dummy surface w/ same profile 
             final ProxySurface dummySurface = createDummySurfaceImpl(device, true, new GLCapabilities(capsChosen.getGLProfile()), capsRequested, null, width, height);
             final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
             return new GLFBODrawableImpl.ResizeableImpl(this, dummyDrawable, dummySurface, capsChosen, 0);
-        } finally {
-            device.unlock();
-        }
-    }
-    
-    device.lock();
-    try {
+        }    
         return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, 
                                                                      new UpstreamSurfaceHookMutableSize(width, height) ) );
     } finally {
@@ -318,13 +341,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
     }
   }
 
-  /** Creates a platform independent FBO offscreen GLDrawable */ 
+  /** Creates a platform independent unrealized FBO offscreen GLDrawable */ 
   protected GLFBODrawable createFBODrawableImpl(NativeSurface dummySurface, GLCapabilitiesImmutable fboCaps, int textureUnit) {
     final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
     return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, fboCaps, textureUnit);
   }
   
-  /** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */  
+  /** Creates a platform dependent unrealized offscreen pbuffer/pixmap GLDrawable instance */  
   protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
 
   /**
@@ -469,17 +492,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
     return (GLDrawableFactoryImpl) getFactory(glp);
   }
 
-  //---------------------------------------------------------------------------
-  // Support for Java2D/JOGL bridge on Mac OS X; the external
-  // GLDrawable mechanism in the public API is sufficient to
-  // implement this functionality on all other platforms
-  //
-
-  public abstract boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device);
-
-  public abstract GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
-    throws GLException;
-
   //----------------------------------------------------------------------
   // Gamma adjustment support
   // Thanks to the LWJGL team for illustrating how to make these
@@ -563,16 +575,16 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
         rampEntry = 0.0f;
       gammaRamp[i] = rampEntry;
     }
-    registerGammaShutdownHook();
+    needsGammaRampReset = true;
     return setGammaRamp(gammaRamp);
   }
 
+  @Override
   public synchronized void resetDisplayGamma() {
-    if (gammaShutdownHook == null) {
-      throw new IllegalArgumentException("Should not call this unless setDisplayGamma called first");
+    if( needsGammaRampReset ) {
+        resetGammaRamp(originalGammaRamp);
+        needsGammaRampReset = false;
     }
-    resetGammaRamp(originalGammaRamp);
-    unregisterGammaShutdownHook();
   }
 
   //------------------------------------------------------
@@ -604,35 +616,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
   }
 
   // Shutdown hook mechanism for resetting gamma
-  private boolean gammaShutdownHookRegistered;
-  private Thread  gammaShutdownHook;
-  private Buffer  originalGammaRamp;
-  private synchronized void registerGammaShutdownHook() {
-    if (gammaShutdownHookRegistered)
-      return;
-    if (gammaShutdownHook == null) {
-      gammaShutdownHook = new Thread(new Runnable() {
-          @Override
-        public void run() {
-            synchronized (GLDrawableFactoryImpl.this) {
-              resetGammaRamp(originalGammaRamp);
-            }
-          }
-        });
-      originalGammaRamp = getGammaRamp();
-    }
-    Runtime.getRuntime().addShutdownHook(gammaShutdownHook);
-    gammaShutdownHookRegistered = true;
-  }
-
-  private synchronized void unregisterGammaShutdownHook() {
-    if (!gammaShutdownHookRegistered)
-      return;
-    if (gammaShutdownHook == null) {
-      throw new InternalError("Error in gamma shutdown hook logic");
-    }
-    Runtime.getRuntime().removeShutdownHook(gammaShutdownHook);
-    gammaShutdownHookRegistered = false;
-    // Leave the original gamma ramp data alone
-  }
+  private volatile Buffer originalGammaRamp;
+  private volatile boolean needsGammaRampReset = false;
 }
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index d4ff970..8be910c 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -41,6 +41,7 @@
 package jogamp.opengl;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.HashSet;
 
 import javax.media.nativewindow.NativeSurface;
@@ -57,11 +58,8 @@ import javax.media.opengl.GLException;
 import javax.media.opengl.GLFBODrawable;
 import javax.media.opengl.GLRunnable;
 
-import com.jogamp.opengl.util.Animator;
-
 /** Encapsulates the implementation of most of the GLAutoDrawable's
-    methods to be able to share it between GLCanvas and GLJPanel. */
-
+    methods to be able to share it between GLAutoDrawable implementations like GLAutoDrawableBase, GLCanvas and GLJPanel. */
 public class GLDrawableHelper {
   /** true if property <code>jogl.debug.GLDrawable.PerfStats</code> is defined. */
   private static final boolean PERF_STATS = Debug.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true);
@@ -73,8 +71,11 @@ public class GLDrawableHelper {
   private final Object glRunnablesLock = new Object();
   private volatile ArrayList<GLRunnableTask> glRunnables = new ArrayList<GLRunnableTask>();
   private boolean autoSwapBufferMode;
-  private Thread skipContextReleaseThread;
+  private volatile Thread exclusiveContextThread;
+  /** -1 release, 0 nop, 1 claim */
+  private volatile int exclusiveContextSwitch;
   private GLAnimatorControl animatorCtrl;
+  private static Runnable nop = new Runnable() { public void run() {} };
 
   public GLDrawableHelper() {
     reset();
@@ -86,7 +87,8 @@ public class GLDrawableHelper {
         listenersToBeInit.clear();
     }
     autoSwapBufferMode = true;
-    skipContextReleaseThread = null;
+    exclusiveContextThread = null;
+    exclusiveContextSwitch = 0;
     synchronized(glRunnablesLock) {
         glRunnables.clear();
     }
@@ -111,44 +113,71 @@ public class GLDrawableHelper {
     return sb.toString();
   }
 
+  /** Limit release calls of {@link #forceNativeRelease(GLContext)} to {@value}. */
+  private static final int MAX_RELEASE_ITER = 512;
+  
   /**
-   * Associate a new context to the drawable and also propagates the context/drawable switch by 
-   * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
-   * <p> 
-   * If the old or new context was current on this thread, it is being released before switching the drawable.
+   * Since GLContext's {@link GLContext#makeCurrent()} and {@link GLContext#release()}
+   * is recursive, a call to {@link GLContext#release()} may not natively release the context.
+   * <p>
+   * This methods continues calling {@link GLContext#release()} until the context has been natively released.
+   * </p>
+   * @param ctx
+   */
+  public static final void forceNativeRelease(GLContext ctx) {
+      int releaseCount = 0;
+      do {
+          ctx.release();
+          releaseCount++;
+          if (DEBUG) {
+              System.err.println("GLDrawableHelper.forceNativeRelease() #"+releaseCount+" -- currentThread "+Thread.currentThread()+" -> "+GLContext.getCurrent());
+          }
+      } while( MAX_RELEASE_ITER > releaseCount && ctx.isCurrent() );
+      
+      if( ctx.isCurrent() ) {
+          throw new GLException("Context still current after "+MAX_RELEASE_ITER+" releases: "+ctx);
+      }
+  }
+        
+  /**
+   * Switch {@link GLContext} / {@link GLDrawable} association.
+   * <p>
+   * The <code>oldCtx</code> will be destroyed if <code>destroyPrevCtx</code> is <code>true</code>,
+   * otherwise dis-associate <code>oldCtx</code> from <code>drawable</code> 
+   * via {@link GLContext#setGLDrawable(GLDrawable, boolean) oldCtx.setGLDrawable(null, true);}.
    * </p>
    * <p>
-   * Be aware that the old context is still bound to the drawable, 
-   * and that one context can only bound to one drawable at one time! 
+   * Re-associate <code>newCtx</code> with <code>drawable</code> 
+   * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
+   * </p>
+   * <p> 
+   * If the old or new context was current on this thread, it is being released before switching the drawable.
    * </p>
    * <p>
    * No locking is being performed on the drawable, caller is required to take care of it.
    * </p>
    * 
    * @param drawable the drawable which context is changed
-   * @param oldCtx the old context
-   * @param newCtx the new context
+   * @param oldCtx the old context, maybe <code>null</code>.
+   * @param destroyOldCtx if <code>true</code>, destroy the <code>oldCtx</code>
+   * @param newCtx the new context, maybe <code>null</code> for dis-association.
    * @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)}
-   * @return true if the new context was current, otherwise false
    *  
-   * @see GLAutoDrawable#setContext(GLContext)
+   * @see GLAutoDrawable#setContext(GLContext, boolean)
    */
-  public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) {
-      if( null != oldCtx && oldCtx.isCurrent() ) {
-          oldCtx.release();
+  public static final void switchContext(GLDrawable drawable, GLContext oldCtx, boolean destroyOldCtx, GLContext newCtx, int newCtxCreationFlags) {
+      if( null != oldCtx ) {
+          if( destroyOldCtx ) {
+              oldCtx.destroy();
+          } else {
+              oldCtx.setGLDrawable(null, true); // dis-associate old pair
+          }
       }
-      final boolean newCtxCurrent;
+      
       if(null!=newCtx) {
-          newCtxCurrent = newCtx.isCurrent();
-          if(newCtxCurrent) {
-              newCtx.release();
-          }
           newCtx.setContextCreationFlags(newCtxCreationFlags);
-          newCtx.setGLDrawable(drawable, true); // propagate context/drawable switch
-      } else {
-          newCtxCurrent = false;
+          newCtx.setGLDrawable(drawable, true); // re-associate new pair          
       }
-      return newCtxCurrent;
   }
   
   /**
@@ -161,7 +190,7 @@ public class GLDrawableHelper {
    *  <li>make context current, if it was current</li>
    * </ul>
    * <p>
-   * No locking is being performed, caller is required to take care of it.
+   * Locking is performed via {@link GLContext#makeCurrent()} on the passed <code>context</code>.
    * </p>
    * 
    * @param drawable
@@ -172,13 +201,18 @@ public class GLDrawableHelper {
       if( ! drawable.isRealized() ) {
           return drawable;
       }
-      final boolean contextCurrent = null != context && context.isCurrent();
+      final GLContext currentContext = GLContext.getCurrent();
       final GLDrawableFactory factory = drawable.getFactory();
       final NativeSurface surface = drawable.getNativeSurface();
       final ProxySurface proxySurface = (surface instanceof ProxySurface) ? (ProxySurface)surface : null;
       
-      if(contextCurrent) {
-          context.release();
+      if( null != context ) {
+          // Ensure to sync GL command stream
+          if( currentContext != context ) {
+              context.makeCurrent();
+          }
+          context.getGL().glFinish();
+          context.setGLDrawable(null, true); // dis-associate
       }
       
       if(null != proxySurface) {
@@ -198,8 +232,8 @@ public class GLDrawableHelper {
           context.setGLDrawable(drawable, true); // re-association
       }
       
-      if(contextCurrent) {
-          context.makeCurrent();
+      if( null != currentContext ) {
+          currentContext.makeCurrent();
       }
       return drawable;
   }
@@ -289,49 +323,218 @@ public class GLDrawableHelper {
         // GLEventListener may be added after context is created,
         // hence we earmark initialization for the next display call.
         listenersToBeInit.add(listener);
+        
         listeners.add(index, listener);
     }
   }
-  
-  public final void removeGLEventListener(GLEventListener listener) {
+
+  /**
+   * Note that no {@link GLEventListener#dispose(GLAutoDrawable)} call is being issued
+   * due to the lack of a current context. 
+   * Consider calling {@link #disposeGLEventListener(GLAutoDrawable, GLDrawable, GLContext, GLEventListener)}.
+   * @return the removed listener, or null if listener was not added
+   */
+  public final GLEventListener removeGLEventListener(GLEventListener listener) {
+    synchronized(listenersLock) {
+        listenersToBeInit.remove(listener);
+        return listeners.remove(listener) ? listener : null;
+    }
+  }
+
+  public final GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
     synchronized(listenersLock) {
-        listeners.remove(listener);
+        if(0>index) {
+            index = listeners.size()-1;
+        }
+        final GLEventListener listener = listeners.remove(index);
         listenersToBeInit.remove(listener);
+        return listener;
     }
   }
+  
+  public final int getGLEventListenerCount() {
+    synchronized(listenersLock) {
+        return listeners.size();
+    }      
+  }
 
-  public final GLEventListener removeGLEventListener(int index)
-    throws IndexOutOfBoundsException {
+  public final GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException {
     synchronized(listenersLock) {
         if(0>index) {
             index = listeners.size()-1;
         }
-        return listeners.remove(index);
+        return listeners.get(index);
+    }
+  }
+  
+  public final boolean getGLEventListenerInitState(GLEventListener listener) {
+    synchronized(listenersLock) {
+        return !listenersToBeInit.contains(listener);
+    }
+  }
+  
+  public final void setGLEventListenerInitState(GLEventListener listener, boolean initialized) {
+    synchronized(listenersLock) {
+        if(initialized) {
+            listenersToBeInit.remove(listener);
+        } else {
+            listenersToBeInit.add(listener);
+        }
     }
   }
   
   /**
-   * Issues {@link javax.media.opengl.GLEventListener#dispose(javax.media.opengl.GLAutoDrawable)}
-   * to all listeners.
+   * Disposes the given {@link GLEventListener} via {@link GLEventListener#dispose(GLAutoDrawable)} 
+   * if it has been initialized and added to this queue.
    * <p>
-   * Please consider using {@link #disposeGL(GLAutoDrawable, GLDrawable, GLContext, Runnable)}
-   * for correctness!
+   * If <code>remove</code> is <code>true</code>, the {@link GLEventListener} is removed from this drawable queue before disposal,
+   * otherwise marked uninitialized.
    * </p>
-   * @param drawable
+   * <p>
+   * Please consider using {@link #disposeGLEventListener(GLAutoDrawable, GLDrawable, GLContext, GLEventListener)} 
+   * for correctness, i.e. encapsulating all calls w/ makeCurrent etc.
+   * </p>
+   * @param autoDrawable
+   * @param remove if true, the listener gets removed
+   * @return the disposed and/or removed listener, otherwise null if neither action is performed
    */
-  public final void dispose(GLAutoDrawable drawable) {
+  public final GLEventListener disposeGLEventListener(GLAutoDrawable autoDrawable, GLEventListener listener, boolean remove) {
+      synchronized(listenersLock) {
+          if( remove ) {              
+              if( listeners.remove(listener) ) {
+                  if( !listenersToBeInit.remove(listener) ) {              
+                      listener.dispose(autoDrawable);
+                  }
+                  return listener;
+              }
+          } else {
+              if( listeners.contains(listener) && !listenersToBeInit.contains(listener) ) {
+                  listener.dispose(autoDrawable);
+                  listenersToBeInit.add(listener);
+                  return listener;
+              }              
+          }
+      }
+      return null;
+  }
+  
+  /**
+   * Disposes all added initialized {@link GLEventListener}s via {@link GLEventListener#dispose(GLAutoDrawable)}.
+   * <p>
+   * If <code>remove</code> is <code>true</code>, the {@link GLEventListener}s are removed from this drawable queue before disposal,
+   * otherwise maked uninitialized.
+   * </p>
+   * <p>
+   * Please consider using {@link #disposeAllGLEventListener(GLAutoDrawable, GLContext, boolean)}
+   * or {@link #disposeGL(GLAutoDrawable, GLContext, boolean)}
+   * for correctness, i.e. encapsulating all calls w/ makeCurrent etc.
+   * </p>
+   * @param autoDrawable
+   * @return the disposal count
+   */
+  public final int disposeAllGLEventListener(GLAutoDrawable autoDrawable, boolean remove) {
+    int disposeCount = 0;
     synchronized(listenersLock) {
-        final ArrayList<GLEventListener> _listeners = listeners;
-        for (int i=0; i < _listeners.size(); i++) {
-          _listeners.get(i).dispose(drawable);
+        if( remove ) {
+            for (int count = listeners.size(); 0 < count && 0 < listeners.size(); count--) {
+              final GLEventListener listener = listeners.remove(0);
+              if( !listenersToBeInit.remove(listener) ) {
+                  listener.dispose(autoDrawable);
+                  disposeCount++;
+              }
+            }
+        } else {
+            for (int i = 0; i < listeners.size(); i++) {
+              final GLEventListener listener = listeners.get(i);
+              if( !listenersToBeInit.contains(listener) ) {
+                  listener.dispose(autoDrawable);
+                  listenersToBeInit.add(listener);
+                  disposeCount++;
+              }
+            }            
         }
     }
+    return disposeCount;
   }
 
-  private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) {
+  /**
+   * Principal helper method which runs {@link #disposeGLEventListener(GLAutoDrawable, GLEventListener, boolean)} 
+   * with the context made current.
+   * <p>
+   * If an {@link GLAnimatorControl} is being attached and the current thread is different 
+   * than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+   * </p>
+   * 
+   * @param autoDrawable
+   * @param context
+   * @param listener
+   * @param initAction
+   */
+  public final GLEventListener disposeGLEventListener(final GLAutoDrawable autoDrawable,
+                                                      final GLDrawable drawable,
+                                                      final GLContext context, 
+                                                      final GLEventListener listener,
+                                                      final boolean remove) {
+      synchronized(listenersLock) {
+          // fast path for uninitialized listener
+          if( listenersToBeInit.contains(listener) ) {
+             if( remove ) {
+                 listenersToBeInit.remove(listener);
+                 return listeners.remove(listener) ? listener : null; 
+             }
+             return null;
+          }
+      }
+      final boolean isPaused = isAnimatorAnimatingOnOtherThread() && animatorCtrl.pause();
+      final GLEventListener[] res = new GLEventListener[] { null };
+      final Runnable action = new Runnable() {
+          public void run() {
+              res[0] = disposeGLEventListener(autoDrawable, listener, remove);
+          }
+      };
+      invokeGL(drawable, context, action, nop);
+      
+      if(isPaused) {
+          animatorCtrl.resume();
+      }
+      return res[0];
+  }
+  
+  /**
+   * Principal helper method which runs {@link #disposeAllGLEventListener(GLAutoDrawable, boolean)} 
+   * with the context made current.
+   * <p>
+   * If an {@link GLAnimatorControl} is being attached and the current thread is different 
+   * than {@link GLAnimatorControl#getThread() the animator's thread}, it is paused during the operation.
+   * </p>
+   * 
+   * @param autoDrawable
+   * @param context
+   * @param remove
+   */
+  public final void disposeAllGLEventListener(final GLAutoDrawable autoDrawable,
+                                              final GLDrawable drawable,
+                                              final GLContext context,
+                                              final boolean remove) {
+      
+      final boolean isPaused = isAnimatorAnimatingOnOtherThread() && animatorCtrl.pause();
+      
+      final Runnable action = new Runnable() {
+          public void run() {
+              disposeAllGLEventListener(autoDrawable, remove);
+          }
+      };
+      invokeGL(drawable, context, action, nop);
+      
+      if(isPaused) {
+          animatorCtrl.resume();
+      }
+  }
+  
+  private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape, boolean setViewport) {
       l.init(drawable);
       if(sendReshape) {
-          reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */);
+          reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), setViewport, false /* checkInit */);
       }
   }
 
@@ -342,39 +545,46 @@ public class GLDrawableHelper {
   public final void init(GLAutoDrawable drawable, boolean sendReshape) {
     synchronized(listenersLock) {
         final ArrayList<GLEventListener> _listeners = listeners;
-        for (int i=0; i < _listeners.size(); i++) {
-          final GLEventListener listener = _listeners.get(i) ;
-
-          // If make ctx current, invoked by invokGL(..), results in a new ctx, init gets called.
-          // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window),
-          // hence it must be called unconditional, always.
-          listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init
-          init( listener, drawable, sendReshape);
+        final int listenerCount = _listeners.size();
+        if( listenerCount > 0 ) {
+            for (int i=0; i < listenerCount; i++) {
+              final GLEventListener listener = _listeners.get(i) ;
+    
+              // If make ctx current, invoked by invokGL(..), results in a new ctx, init gets called.
+              // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window),
+              // hence it must be called unconditional, always.
+              listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init
+              init( listener, drawable, sendReshape, 0==i /* setViewport */);
+            }
+        } else {
+            // Expose same GL initialization if not using GLEventListener
+            drawable.getGL().glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
         }
     }
   }
 
   public final void display(GLAutoDrawable drawable) {
     displayImpl(drawable);
-    if(!execGLRunnables(drawable)) {
+    if( glRunnables.size()>0 && !execGLRunnables(drawable) ) { // glRunnables volatile OK; execGL.. only executed if size > 0
         displayImpl(drawable);  
     }
   }
   private final void displayImpl(GLAutoDrawable drawable) {
       synchronized(listenersLock) {
           final ArrayList<GLEventListener> _listeners = listeners;
-          for (int i=0; i < _listeners.size(); i++) {
+          final int listenerCount = _listeners.size();
+          for (int i=0; i < listenerCount; i++) {
             final GLEventListener listener = _listeners.get(i) ;
             // GLEventListener may need to be init, 
             // in case this one is added after the realization of the GLAutoDrawable
             if( listenersToBeInit.remove(listener) ) {
-                init( listener, drawable, true /* sendReshape */) ;
+                init( listener, drawable, true /* sendReshape */, listenersToBeInit.size() + 1 == listenerCount /* setViewport if 1st init */ );
             }
             listener.display(drawable);
           }
       }
   }
-
+  
   private final void reshape(GLEventListener listener, GLAutoDrawable drawable,
                              int x, int y, int width, int height, boolean setViewport, boolean checkInit) {
     if(checkInit) {
@@ -382,7 +592,7 @@ public class GLDrawableHelper {
         // in case this one is added after the realization of the GLAutoDrawable
         synchronized(listenersLock) {
             if( listenersToBeInit.remove(listener) ) {
-                init( listener, drawable, false /* sendReshape */) ;
+                listener.init(drawable);
             }
         }
     }
@@ -395,29 +605,27 @@ public class GLDrawableHelper {
   public final void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
     synchronized(listenersLock) {
         for (int i=0; i < listeners.size(); i++) {
-          reshape((GLEventListener) listeners.get(i), drawable, x, y, width, height, 0==i, true);
+          reshape((GLEventListener) listeners.get(i), drawable, x, y, width, height, 0==i /* setViewport */, true /* checkInit */);
         }
     }
   }
 
-  private final boolean execGLRunnables(GLAutoDrawable drawable) {
+  private final boolean execGLRunnables(GLAutoDrawable drawable) { // glRunnables.size()>0
     boolean res = true;
-    if(glRunnables.size()>0) { // volatile OK
-        // swap one-shot list asap
-        final ArrayList<GLRunnableTask> _glRunnables;
-        synchronized(glRunnablesLock) {
-            if(glRunnables.size()>0) {
-                _glRunnables = glRunnables;
-                glRunnables = new ArrayList<GLRunnableTask>();
-            } else {
-                _glRunnables = null;
-            }
+    // swap one-shot list asap
+    final ArrayList<GLRunnableTask> _glRunnables;
+    synchronized(glRunnablesLock) {
+        if(glRunnables.size()>0) {
+            _glRunnables = glRunnables;
+            glRunnables = new ArrayList<GLRunnableTask>();
+        } else {
+            _glRunnables = null;
         }
-        
-        if(null!=_glRunnables) {
-            for (int i=0; i < _glRunnables.size(); i++) {
-                res = _glRunnables.get(i).run(drawable) && res;
-            }
+    }
+    
+    if(null!=_glRunnables) {
+        for (int i=0; i < _glRunnables.size(); i++) {
+            res = _glRunnables.get(i).run(drawable) && res;
         }
     }
     return res;
@@ -459,15 +667,15 @@ public class GLDrawableHelper {
     }
   }
 
-  public final boolean isAnimatorRunningOnOtherThread() {
+  public final boolean isAnimatorStartedOnOtherThread() {
     return ( null != animatorCtrl ) ? animatorCtrl.isStarted() && animatorCtrl.getThread() != Thread.currentThread() : false ;
   }
 
-  public final boolean isAnimatorRunning() {
+  public final boolean isAnimatorStarted() {
     return ( null != animatorCtrl ) ? animatorCtrl.isStarted() : false ;
   }
 
-  public final boolean isExternalAnimatorAnimating() {
+  public final boolean isAnimatorAnimatingOnOtherThread() {
     return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() && animatorCtrl.getThread() != Thread.currentThread() : false ;
   }
 
@@ -497,13 +705,13 @@ public class GLDrawableHelper {
         return false;
     }
     
-    Throwable throwable = null;
     GLRunnableTask rTask = null;
     Object rTaskLock = new Object();
+    Throwable throwable = null;
     synchronized(rTaskLock) {
-        boolean deferred;
+        final boolean deferred;
         synchronized(glRunnablesLock) {
-            deferred = isExternalAnimatorAnimating();
+            deferred = isAnimatorAnimatingOnOtherThread();
             if(!deferred) {
                 wait = false; // don't wait if exec immediatly
             }
@@ -530,7 +738,60 @@ public class GLDrawableHelper {
     }
     return true;
   }
+  
+  public final boolean invoke(GLAutoDrawable drawable, boolean wait, List<GLRunnable> newGLRunnables) {
+    if( null == newGLRunnables || newGLRunnables.size() == 0 || null == drawable ||
+        wait && ( !drawable.isRealized() || null==drawable.getContext() ) ) {
+        return false;
+    }
+    
+    final int count = newGLRunnables.size();
+    GLRunnableTask rTask = null;
+    Object rTaskLock = new Object();
+    Throwable throwable = null;
+    synchronized(rTaskLock) {
+        final boolean deferred;
+        synchronized(glRunnablesLock) {
+            deferred = isAnimatorAnimatingOnOtherThread() || !drawable.isRealized();
+            if(!deferred) {
+                wait = false; // don't wait if exec immediately
+            }
+            for(int i=0; i<count-1; i++) {
+                glRunnables.add( new GLRunnableTask(newGLRunnables.get(i), null, false) );
+            }
+            rTask = new GLRunnableTask(newGLRunnables.get(count-1),
+                                       wait ? rTaskLock : null,
+                                       wait  /* catch Exceptions if waiting for result */);
+            glRunnables.add(rTask);
+        }
+        if( !deferred ) {
+            drawable.display();
+        } else if( wait ) {
+            try {
+                rTaskLock.wait(); // free lock, allow execution of rTask
+            } catch (InterruptedException ie) {
+                throwable = ie;
+            }
+            if(null==throwable) {
+                throwable = rTask.getThrowable();
+            }
+            if(null!=throwable) {
+                throw new RuntimeException(throwable);
+            }
+        }
+    }
+    return true;      
+  }
 
+  public final void enqueue(GLRunnable glRunnable) {
+    if( null == glRunnable) {
+        return;
+    }    
+    synchronized(glRunnablesLock) {
+        glRunnables.add( new GLRunnableTask(glRunnable, null, false) );
+    }
+  }
+  
   public final void setAutoSwapBufferMode(boolean enable) {
     autoSwapBufferMode = enable;
   }
@@ -539,23 +800,72 @@ public class GLDrawableHelper {
     return autoSwapBufferMode;
   }
 
+  private final String getExclusiveContextSwitchString() {
+      return 0 == exclusiveContextSwitch ? "nop" : ( 0 > exclusiveContextSwitch ? "released" : "claimed" ) ;
+  }
+
   /**
-   * @param t the thread for which context release shall be skipped, usually the animation thread,
-   *          ie. {@link Animator#getThread()}.
-   * @deprecated this is an experimental feature, 
-   *             intended for measuring performance in regards to GL context switch
-   *             and only being used if {@link #PERF_STATS} is enabled
-   *             by defining property <code>jogl.debug.GLDrawable.PerfStats</code>.
+   * Dedicates this instance's {@link GLContext} to the given thread.<br/>
+   * The thread will exclusively claim the {@link GLContext} via {@link #display()} and not release it
+   * until {@link #destroy()} or <code>setExclusiveContextThread(null)</code> has been called. 
+   * <p>
+   * Default non-exclusive behavior is <i>requested</i> via <code>setExclusiveContextThread(null)</code>,
+   * which will cause the next call of {@link #display()} on the exclusive thread to 
+   * release the {@link GLContext}. Only after it's async release, {@link #getExclusiveContextThread()} 
+   * will return <code>null</code>.
+   * </p>
+   * <p>
+   * To release a previous made exclusive thread, a user issues <code>setExclusiveContextThread(null)</code>
+   * and may poll {@link #getExclusiveContextThread()} until it returns <code>null</code>, 
+   * <i>while</i> the exclusive thread is still running.  
+   * </p>
+   * <p>
+   * Note: Setting a new exclusive thread without properly releasing a previous one
+   * will throw an GLException.
+   * </p>
+   * <p>
+   * One scenario could be to dedicate the context to the {@link com.jogamp.opengl.util.AnimatorBase#getThread() animator thread}
+   * and spare redundant context switches.
+   * </p>
+   * @param t the exclusive thread to claim the context, or <code>null</code> for default operation.
+   * @return previous exclusive context thread 
+   * @throws GLException If an exclusive thread is still active but a new one is attempted to be set
    */
-  public final void setSkipContextReleaseThread(Thread t) {
-    skipContextReleaseThread = t;
+  public final Thread setExclusiveContextThread(Thread t, GLContext context) throws GLException {
+    if (DEBUG) {
+      System.err.println("GLDrawableHelper.setExclusiveContextThread(): START switch "+getExclusiveContextSwitchString()+", thread "+exclusiveContextThread+" -> "+t+" -- currentThread "+Thread.currentThread());
+    }
+    final Thread oldExclusiveContextThread = exclusiveContextThread;
+    if( exclusiveContextThread == t ) {
+        exclusiveContextSwitch =  0; // keep
+    } else if( null == t ) {
+        exclusiveContextSwitch = -1; // release
+    } else {
+        exclusiveContextSwitch =  1; // claim
+        if( null != exclusiveContextThread ) {
+            throw new GLException("Release current exclusive Context Thread "+exclusiveContextThread+" first");
+        }
+        if( null != context && context.isCurrent() ) {
+            try {
+                forceNativeRelease(context);
+            } catch (Throwable ex) {
+                ex.printStackTrace();
+                throw new GLException(ex);
+            }
+        }        
+        exclusiveContextThread = t;
+    }
+    if (DEBUG) {
+      System.err.println("GLDrawableHelper.setExclusiveContextThread(): END switch "+getExclusiveContextSwitchString()+", thread "+exclusiveContextThread+" -- currentThread "+Thread.currentThread());
+    }
+    return oldExclusiveContextThread;
   }
-
+  
   /**
-   * @deprecated see {@link #setSkipContextReleaseThread(Thread)} 
+   * @see #setExclusiveContextThread(Thread, GLContext) 
    */
-  public final Thread getSkipContextReleaseThread() {
-    return skipContextReleaseThread;
+  public final Thread getExclusiveContextThread() {
+    return exclusiveContextThread;
   }
   
   private static final ThreadLocal<Runnable> perThreadInitAction = new ThreadLocal<Runnable>();
@@ -576,105 +886,76 @@ public class GLDrawableHelper {
    * @param runnable
    * @param initAction
    */
-  public final void invokeGL(GLDrawable drawable,
-                             GLContext context,
-                             Runnable  runnable,
-                             Runnable  initAction) {
+  public final void invokeGL(final GLDrawable drawable,
+                             final GLContext context,
+                             final Runnable  runnable,
+                             final Runnable  initAction) {
     if(null==context) {
         if (DEBUG) {
-            Exception e = new GLException(Thread.currentThread().getName()+" Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext");
+            Exception e = new GLException(getThreadName()+" Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext");
             e.printStackTrace();
         }
         return;
     }
 
     if(PERF_STATS) {
-        invokeGLImplStats(drawable, context, runnable, initAction, null);    
+        invokeGLImplStats(drawable, context, runnable, initAction);    
     } else {
-        invokeGLImpl(drawable, context, runnable, initAction, null);
+        invokeGLImpl(drawable, context, runnable, initAction);
     }
   }
 
   /** 
-   * Principal helper method which runs {@link #dispose(GLAutoDrawable)} with the context
-   * made current and destroys the context afterwards while holding the lock.  
-   * 
+   * Principal helper method which runs 
+   * {@link #disposeAllGLEventListener(GLAutoDrawable, boolean) disposeAllGLEventListener(autoDrawable, false)} 
+   * with the context made current.
+   * <p>
+   * If <code>destroyContext</code> is <code>true</code> the context is destroyed in the end while holding the lock.
+   * </p>
+   * <p>
+   * If <code>destroyContext</code> is <code>false</code> the context is natively released, i.e. released as often as locked before.
+   * </p>
    * @param autoDrawable
-   * @param drawable
    * @param context
-   * @param postAction
+   * @param destroyContext destroy context in the end while holding the lock
    */
-  public final void disposeGL(GLAutoDrawable autoDrawable,
-                              GLDrawable drawable,
-                              GLContext context,
-                              Runnable  postAction) {
-    if(PERF_STATS) {
-        invokeGLImplStats(drawable, context, null, null, autoDrawable);    
-    } else {
-        invokeGLImpl(drawable, context, null, null, autoDrawable);
-    }
-    if(null != postAction) {
-        postAction.run();
-    }
-  }
-  
-  private final void invokeGLImpl(GLDrawable drawable,
-                                  GLContext context,
-                                  Runnable  runnable,
-                                  Runnable  initAction,
-                                  GLAutoDrawable disposeAutoDrawable) {
-    final Thread currentThread = Thread.currentThread();
-    
-    final boolean isDisposeAction = null==initAction ;
-        
+  public final void disposeGL(final GLAutoDrawable autoDrawable,
+                              final GLContext context, boolean destroyContext) {
     // Support for recursive makeCurrent() calls as well as calling
     // other drawables' display() methods from within another one's
     GLContext lastContext = GLContext.getCurrent();
     Runnable  lastInitAction = null;
     if (lastContext != null) {
         if (lastContext == context) {
-            lastContext = null; // utilize recursive locking
+            lastContext = null;
         } else {
+            // utilize recursive locking
             lastInitAction = perThreadInitAction.get();
             lastContext.release();
         }
     }
-    int res = GLContext.CONTEXT_NOT_CURRENT;
-  
+
+    int res;    
     try {
       res = context.makeCurrent();
       if (GLContext.CONTEXT_NOT_CURRENT != res) {
-        if(!isDisposeAction) {
-            perThreadInitAction.set(initAction);
-            if (GLContext.CONTEXT_CURRENT_NEW == res) {
-              if (DEBUG) {
-                System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
-              }
-              initAction.run();
-            }
-            runnable.run();
-            if (autoSwapBufferMode) {
-                drawable.swapBuffers();
-            }
-        } else {
-            if(GLContext.CONTEXT_CURRENT_NEW == res) {
-                throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
-            }
-            if(listeners.size()>0) {
-                dispose(disposeAutoDrawable);
-            }
+        if(GLContext.CONTEXT_CURRENT_NEW == res) {
+            throw new GLException(getThreadName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
+        }
+        if( listeners.size() > 0 && null != autoDrawable ) {
+            disposeAllGLEventListener(autoDrawable, false);
         }
       }
     } finally {
       try {
-          if(isDisposeAction) {
+          if(destroyContext) {
               context.destroy();
-              flushGLRunnables();
-          } else if( GLContext.CONTEXT_NOT_CURRENT != res ) {
-              context.release();
+          } else {
+              forceNativeRelease(context);
           }
+          flushGLRunnables();
       } catch (Exception e) {
-          System.err.println("Catched: "+e.getMessage());
+          System.err.println("Catched Exception on thread "+getThreadName());
           e.printStackTrace();
       }
       if (lastContext != null) {
@@ -685,100 +966,206 @@ public class GLDrawableHelper {
       }
     }
   }
-  
-  private final void invokeGLImplStats(GLDrawable drawable,
-                                       GLContext context,
-                                       Runnable  runnable,
-                                       Runnable  initAction,
-                                       GLAutoDrawable disposeAutoDrawable) {
-    final Thread currentThread = Thread.currentThread();
-    
-    final boolean isDisposeAction = null==initAction ;
-    
-    // Support for recursive makeCurrent() calls as well as calling
-    // other drawables' display() methods from within another one's
-    int res = GLContext.CONTEXT_NOT_CURRENT;
-    GLContext lastContext = GLContext.getCurrent();
-    Runnable  lastInitAction = null;
-    if (lastContext != null) {
-        if (lastContext == context) {
-            if( currentThread == skipContextReleaseThread ) {
-                res = GLContext.CONTEXT_CURRENT;
-            } // else: utilize recursive locking
-            lastContext = null;
-        } else {
-            lastInitAction = perThreadInitAction.get();
-            lastContext.release();
-        }
-    }
-  
-    long t0 = System.currentTimeMillis();
-    long tdA = 0; // makeCurrent
-    long tdR = 0; // render time
-    long tdS = 0; // swapBuffers
-    long tdX = 0; // release
-    boolean ctxClaimed = false;
-    boolean ctxReleased = false;
-    boolean ctxDestroyed = false;    
-    try {
-      if (res == GLContext.CONTEXT_NOT_CURRENT) {
-          res = context.makeCurrent();
-          ctxClaimed = true;
+
+  private final void invokeGLImpl(final GLDrawable drawable,
+          final GLContext context,
+          final Runnable  runnable,
+          final Runnable  initAction) {                                  
+      final Thread currentThread = Thread.currentThread();
+
+      // Exclusive Cases:
+      //   1: lock - unlock  : default
+      //   2: lock - -       : exclusive,    not locked yet
+      //   3: -    - -       : exclusive,    already locked
+      //   4: -    - unlock  : ex-exclusive, already locked
+      final boolean _isExclusiveThread, _releaseExclusiveThread;
+      if( null != exclusiveContextThread) {
+          if( currentThread == exclusiveContextThread ) {
+              _releaseExclusiveThread = 0 > exclusiveContextSwitch;
+              _isExclusiveThread = !_releaseExclusiveThread;
+              exclusiveContextSwitch = 0;
+          } else {
+              // Exclusive thread usage, but on other thread
+              return;
+          }
+      } else {
+          _releaseExclusiveThread = false;
+          _isExclusiveThread = false;
       }
-      if (res != GLContext.CONTEXT_NOT_CURRENT) {
-        if(!isDisposeAction) {
-            perThreadInitAction.set(initAction);
-            if (res == GLContext.CONTEXT_CURRENT_NEW) {
-              if (DEBUG) {
-                System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
-              }
-              initAction.run();
-            }
-            tdR = System.currentTimeMillis();        
-            tdA = tdR - t0; // makeCurrent
-            runnable.run();
-            tdS = System.currentTimeMillis();
-            tdR = tdS - tdR; // render time
-            if (autoSwapBufferMode) {
-                drawable.swapBuffers();
-                tdX = System.currentTimeMillis();
-                tdS = tdX - tdS; // swapBuffers
-            }
-        } else {
-            if(res == GLContext.CONTEXT_CURRENT_NEW) {
-                throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
-            }
-            if(listeners.size()>0) {
-                dispose(disposeAutoDrawable);
-            }
-        }
+
+      // Support for recursive makeCurrent() calls as well as calling
+      // other drawables' display() methods from within another one's
+      int res = GLContext.CONTEXT_NOT_CURRENT;
+      GLContext lastContext = GLContext.getCurrent();
+      Runnable  lastInitAction = null;
+      if (lastContext != null) {
+          if (lastContext == context) {
+              res = GLContext.CONTEXT_CURRENT;
+              lastContext = null;
+          } else {
+              // utilize recursive locking
+              lastInitAction = perThreadInitAction.get();
+              lastContext.release();
+          }
       }
-    } finally {
+      
       try {
-          if(isDisposeAction) {
-              context.destroy();
-              flushGLRunnables();
-              ctxDestroyed = true;
-          } else if( res != GLContext.CONTEXT_NOT_CURRENT &&
-                     (null == skipContextReleaseThread || currentThread != skipContextReleaseThread) ) {
-              context.release();
-              ctxReleased = true;
+          final boolean releaseContext;
+          if( GLContext.CONTEXT_NOT_CURRENT == res ) {
+              res = context.makeCurrent();
+              releaseContext = !_isExclusiveThread;
+          } else {
+              releaseContext = _releaseExclusiveThread;
+          }
+          if (GLContext.CONTEXT_NOT_CURRENT != res) {
+              try {
+                  perThreadInitAction.set(initAction);
+                  if (GLContext.CONTEXT_CURRENT_NEW == res) {
+                      if (DEBUG) {
+                          System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
+                      }
+                      initAction.run();
+                  }
+                  runnable.run();
+                  if ( autoSwapBufferMode ) {
+                      drawable.swapBuffers();
+                  }
+              } finally {
+                  if( _releaseExclusiveThread ) {
+                      exclusiveContextThread = null;
+                      if (DEBUG) {
+                          System.err.println("GLDrawableHelper.invokeGL() - Release ExclusiveContextThread -- currentThread "+Thread.currentThread());
+                      }
+                  }
+                  if( releaseContext ) {
+                      try {
+                          context.release();
+                      } catch (Exception e) {
+                          System.err.println("Catched Exception on thread "+getThreadName());
+                          e.printStackTrace();
+                      }
+                  }
+              }
+          }
+      } finally {
+          if (lastContext != null) {
+              final int res2 = lastContext.makeCurrent();
+              if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
+                  lastInitAction.run();
+              }
           }
-      } catch (Exception e) {
-          System.err.println("Catched: "+e.getMessage());
-          e.printStackTrace();
       }
+  }
+
+  private final void invokeGLImplStats(final GLDrawable drawable,
+          final GLContext context,
+          final Runnable  runnable,
+          final Runnable  initAction) {
+      final Thread currentThread = Thread.currentThread();
 
-      tdX = System.currentTimeMillis() - tdX; // release / destroy
+      // Exclusive Cases:
+      //   1: lock - unlock  : default
+      //   2: lock - -       : exclusive, not locked yet
+      //   3: -    - -       : exclusive, already locked
+      //   4: -    - unlock  : ex-exclusive, already locked
+      final boolean _isExclusiveThread, _releaseExclusiveThread;
+      if( null != exclusiveContextThread) {
+          if( currentThread == exclusiveContextThread ) {
+              _releaseExclusiveThread = 0 > exclusiveContextSwitch;
+              _isExclusiveThread = !_releaseExclusiveThread;
+          } else {
+              // Exclusive thread usage, but on other thread
+              return;
+          }
+      } else {
+          _releaseExclusiveThread = false;
+          _isExclusiveThread = false;
+      }
+
+      // Support for recursive makeCurrent() calls as well as calling
+      // other drawables' display() methods from within another one's
+      int res = GLContext.CONTEXT_NOT_CURRENT;
+      GLContext lastContext = GLContext.getCurrent();
+      Runnable  lastInitAction = null;
       if (lastContext != null) {
-        final int res2 = lastContext.makeCurrent();
-        if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
-          lastInitAction.run();
-        }
+          if (lastContext == context) {
+              res = GLContext.CONTEXT_CURRENT;
+              lastContext = null;
+          } else {
+              // utilize recursive locking
+              lastInitAction = perThreadInitAction.get();
+              lastContext.release();
+          }
       }
-    }
-    long td = System.currentTimeMillis() - t0;
-    System.err.println("td0 "+td+"ms, fps "+(1.0/(td/1000.0))+", td-makeCurrent: "+tdA+"ms, td-render "+tdR+"ms, td-swap "+tdS+"ms, td-release "+tdX+"ms, ctx claimed: "+ctxClaimed+", ctx release: "+ctxReleased+", ctx destroyed "+ctxDestroyed);
+
+      long t0 = System.currentTimeMillis();
+      long tdA = 0; // makeCurrent
+      long tdR = 0; // render time
+      long tdS = 0; // swapBuffers
+      long tdX = 0; // release
+      boolean ctxClaimed = false;
+      boolean ctxReleased = false;
+      boolean ctxDestroyed = false;    
+      try {
+          final boolean releaseContext;
+          if( GLContext.CONTEXT_NOT_CURRENT == res ) {
+              res = context.makeCurrent();
+              releaseContext = !_isExclusiveThread;
+              ctxClaimed = true;
+          } else {
+              releaseContext = _releaseExclusiveThread;
+          }
+          if (GLContext.CONTEXT_NOT_CURRENT != res) {
+              try {
+                  perThreadInitAction.set(initAction);
+                  if (GLContext.CONTEXT_CURRENT_NEW == res) {
+                      if (DEBUG) {
+                          System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
+                      }
+                      initAction.run();
+                  }
+                  tdR = System.currentTimeMillis();        
+                  tdA = tdR - t0; // makeCurrent
+                  runnable.run();
+                  tdS = System.currentTimeMillis();
+                  tdR = tdS - tdR; // render time
+                  if ( autoSwapBufferMode ) {
+                      drawable.swapBuffers();
+                      tdX = System.currentTimeMillis();
+                      tdS = tdX - tdS; // swapBuffers
+                  }
+              } finally {
+                  if( _releaseExclusiveThread ) {
+                      exclusiveContextSwitch = 0;
+                      exclusiveContextThread = null;
+                      if (DEBUG) {
+                          System.err.println("GLDrawableHelper.invokeGL() - Release ExclusiveContextThread -- currentThread "+Thread.currentThread());
+                      }
+                  }
+                  if( releaseContext ) {
+                      try {
+                          context.release();
+                          ctxReleased = true;
+                      } catch (Exception e) {
+                          System.err.println("Catched Exception on thread "+getThreadName());
+                          e.printStackTrace();
+                      }
+                  }
+              }
+          }
+      } finally {
+          tdX = System.currentTimeMillis() - tdX; // release / destroy
+          if (lastContext != null) {
+              final int res2 = lastContext.makeCurrent();
+              if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
+                  lastInitAction.run();
+              }
+          }
+      }
+      long td = System.currentTimeMillis() - t0;
+      System.err.println("td0 "+td+"ms, fps "+(1.0/(td/1000.0))+", td-makeCurrent: "+tdA+"ms, td-render "+tdR+"ms, td-swap "+tdS+"ms, td-release "+tdX+"ms, ctx claimed: "+ctxClaimed+", ctx release: "+ctxReleased+", ctx destroyed "+ctxDestroyed);
   }
+
+  protected static String getThreadName() { return Thread.currentThread().getName(); }
     
 }
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index df7f742..e1088da 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -76,28 +76,27 @@ public abstract class GLDrawableImpl implements GLDrawable {
 
   @Override
   public final void swapBuffers() throws GLException {
-    if( !realized ) {
+    if( !realized ) { // volatile OK (locked below)
         return; // destroyed already
     }
-    int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release]
+    final int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release]
     if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
         return;
     }
     try {
-        if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
-            updateHandle();
-        }
-        final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
-        if ( caps.getDoubleBuffered() ) {
-            if(!surface.surfaceSwap()) {
-                swapBuffersImpl(true);
-            }
-        } else {
-            final GLContext ctx = GLContext.getCurrent();
-            if(null!=ctx && ctx.getGLDrawable()==this) {
-                ctx.getGL().glFlush();
+        if( realized ) { // volatile OK
+            final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
+            if ( caps.getDoubleBuffered() ) {
+                if(!surface.surfaceSwap()) {
+                    swapBuffersImpl(true);
+                }
+            } else {
+                final GLContext ctx = GLContext.getCurrent();
+                if(null!=ctx && ctx.getGLDrawable()==this) {
+                    ctx.getGL().glFlush();
+                }
+                swapBuffersImpl(false);
             }
-            swapBuffersImpl(false);
         }
     } finally {
         unlockSurface();
@@ -117,6 +116,7 @@ public abstract class GLDrawableImpl implements GLDrawable {
    * {@link GL#glFlush()} has been called already and 
    * the implementation may execute implementation specific code.
    * </p>
+   * @param doubleBuffered indicates whether double buffering is enabled, see above.
    */
   protected abstract void swapBuffersImpl(boolean doubleBuffered);
 
@@ -143,11 +143,21 @@ public abstract class GLDrawableImpl implements GLDrawable {
     return surface;
   }
 
-  /** called with locked surface @ setRealized(false) */
+  /** 
+   * called with locked surface @ setRealized(false) or @ lockSurface(..) when surface changed
+   * <p>
+   * Must be paired w/ {@link #createHandle()}.
+   * </p> 
+   */
   protected void destroyHandle() {}
 
-  /** called with locked surface @ setRealized(true) or @ lockSurface(..) when surface changed */
-  protected void updateHandle() {}
+  /** 
+   * called with locked surface @ setRealized(true) or @ lockSurface(..) when surface changed
+   * <p>
+   * Must be paired w/ {@link #destroyHandle()}.
+   * </p> 
+   */
+  protected void createHandle() {}
 
   @Override
   public long getHandle() {
@@ -160,37 +170,41 @@ public abstract class GLDrawableImpl implements GLDrawable {
   }
 
   @Override
-  public final synchronized void setRealized(boolean realizedArg) {
-    if ( realized != realizedArg ) {
+  public final void setRealized(boolean realizedArg) {
+    if ( realized != realizedArg ) { // volatile: OK (locked below)
+        final boolean isProxySurface = surface instanceof ProxySurface;
         if(DEBUG) {
-            System.err.println(getThreadName() + ": setRealized: "+getClass().getSimpleName()+" "+realized+" -> "+realizedArg);
+            System.err.println(getThreadName() + ": setRealized: drawable "+getClass().getSimpleName()+", surface "+surface.getClass().getSimpleName()+", isProxySurface "+isProxySurface+": "+realized+" -> "+realizedArg);
+            Thread.dumpStack();
         }
-        realized = realizedArg;
         AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice();
         if(realizedArg) {
-            if(surface instanceof ProxySurface) {
+            if(isProxySurface) {
                 ((ProxySurface)surface).createNotify();
             }
-            if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) {
+            if(NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface()) {
                 throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)");
             }
         } else {
             aDevice.lock();
         }
         try {
-            if(realizedArg) {
-                setRealizedImpl();
-                updateHandle();
-            } else {
-                destroyHandle();
-                setRealizedImpl();
+            if ( realized != realizedArg ) { // volatile: OK
+                realized = realizedArg;
+                if(realizedArg) {
+                    setRealizedImpl();
+                    createHandle();
+                } else {
+                    destroyHandle();
+                    setRealizedImpl();
+                }
             }
         } finally {
             if(realizedArg) {
-                unlockSurface();
+                surface.unlockSurface();
             } else {
                 aDevice.unlock();
-                if(surface instanceof ProxySurface) {
+                if(isProxySurface) {
                     ((ProxySurface)surface).destroyNotify();
                 }
             }
@@ -199,23 +213,32 @@ public abstract class GLDrawableImpl implements GLDrawable {
         System.err.println(getThreadName() + ": setRealized: "+getClass().getName()+" "+this.realized+" == "+realizedArg);
     }
   }
+  
   /**
    * Platform specific realization of drawable 
    */
   protected abstract void setRealizedImpl();
 
-  /** 
-   * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: <code>construct</code>, <code>destroy</code>.
+  /**
+   * Callback for special implementations, allowing
+   * <ul>
+   *   <li>to associate bound context to this drawable (bound == true) 
+   *       or to remove such association (bound == false).</li>
+   *   <li>to trigger GLContext/GLDrawable related lifecycle: <code>construct</code>, <code>destroy</code>.</li>
+   * </ul>
    * <p>
-   * If <code>realized</code> is <code>true</code>, the context has just been created and made current.
+   * If <code>bound</code> is <code>true</code>, the context is current and being newly associated w/ this drawable.
    * </p>
    * <p>
-   * If <code>realized</code> is <code>false</code>, the context is still current and will be released and destroyed after this method returns.
+   * If <code>bound</code> is <code>false</code>, the context is still current and will be unbound (released and destroyed, or simply disassociated).
    * </p>
    * <p>
-   * @see #contextMadeCurrent(GLContext, boolean)
+   * Being called by {@link GLContextImpl#associateDrawable(boolean)}.
+   * </p>
+   * @param ctx the just bounded or unbounded context
+   * @param bound if <code>true</code> create an association, otherwise remove it
    */
-  protected void contextRealized(GLContext glc, boolean realized) {}
+  protected void associateContext(GLContext ctx, boolean bound) { }
   
   /** 
    * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: <code>makeCurrent</code>, <code>release</code>.
@@ -226,28 +249,28 @@ public abstract class GLDrawableImpl implements GLDrawable {
    * If <code>current</code> is <code>false</code>, the context is still current and will be release after this method returns.
    * </p>
    * <p>
-   * Note: Will also be called after {@link #contextRealized(GLContext, boolean) contextRealized(ctx, true)}
-   * but not at context destruction, i.e. {@link #contextRealized(GLContext, boolean) contextRealized(ctx, false)}.
+   * Being called by {@link GLContextImpl#contextMadeCurrent(boolean)}.
    * </p>
-   * @see #contextRealized(GLContext, boolean)
+   * @see #associateContext(GLContext, boolean)
    */ 
   protected void contextMadeCurrent(GLContext glc, boolean current) { }
 
-  /**
-   * Callback for special implementations, allowing to associate bound context to this drawable (bound == true) 
-   * or to remove such association (bound == false).
-   * @param ctx the just bounded or unbounded context
-   * @param bound if <code>true</code> create an association, otherwise remove it
-   */
-  protected void associateContext(GLContext ctx, boolean bound) { }
-  
   /** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/
   protected int getDefaultDrawFramebuffer() { return 0; }
   /** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */
-  protected int getDefaultReadFramebuffer() { return 0; }
+  protected int getDefaultReadFramebuffer() { return 0; }  
+  /** Callback for special implementations, allowing GLContext to fetch a custom default read buffer of current framebuffer. */
+  protected int getDefaultReadBuffer(GL gl) {
+      if(gl.isGLES() || getChosenGLCapabilities().getDoubleBuffered()) {
+          // Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+          // Note-2: ES3 only supports GL_BACK, GL_NONE or GL_COLOR_ATTACHMENT0+i
+          return GL.GL_BACK;
+      }
+      return GL.GL_FRONT ; 
+  }
   
   @Override
-  public final synchronized boolean isRealized() {
+  public final boolean isRealized() {
     return realized;
   }
 
@@ -261,12 +284,52 @@ public abstract class GLDrawableImpl implements GLDrawable {
     return surface.getHeight();
   }
 
-  /** @see NativeSurface#lockSurface() */
+  @Override
+  public boolean isGLOriented() {
+      return true;      
+  }
+  
+  /** 
+   * {@link NativeSurface#lockSurface() Locks} the underlying windowing toolkit's {@link NativeSurface surface}.
+   * <p>
+   * <i>If</i> drawable is {@link #setRealized(boolean) realized},
+   * the {@link #getHandle() drawable handle} is valid after successfully {@link NativeSurface#lockSurface() locking} 
+   * it's {@link NativeSurface surface} until being {@link #unlockSurface() unlocked}.
+   * </p>
+   * <p>
+   * In case the {@link NativeSurface surface} has changed as indicated by it's 
+   * {@link NativeSurface#lockSurface() lock} result {@link NativeSurface#LOCK_SURFACE_CHANGED},
+   * the implementation is required to update this information as needed within it's implementation. 
+   * </p>
+   * 
+   * @see NativeSurface#lockSurface()
+   * @see #getHandle()
+   */
   public final int lockSurface() throws GLException {
-    return surface.lockSurface();
+    final int lockRes = surface.lockSurface();
+    if ( NativeSurface.LOCK_SURFACE_CHANGED == lockRes && realized ) {
+        // Update the drawable handle, in case the surface handle has changed.
+        final long _handle1 = getHandle();
+        destroyHandle();
+        createHandle();
+        final long _handle2 = getHandle();        
+        if(DEBUG) {
+            if( _handle1 != _handle2) {
+                System.err.println(getThreadName() + ": Drawable handle changed: "+toHexString(_handle1)+" -> "+toHexString(_handle2));
+            }
+        }
+    }
+    return lockRes;
+    
   }
 
-  /** @see NativeSurface#unlockSurface() */
+  /** 
+   * {@link NativeSurface#unlockSurface() Unlocks} the underlying windowing toolkit {@link NativeSurface surface},
+   * which may render the {@link #getHandle() drawable handle} invalid.
+   * 
+   * @see NativeSurface#unlockSurface() 
+   * @see #getHandle()
+   */
   public final void unlockSurface() {
     surface.unlockSurface();
   }
@@ -279,9 +342,7 @@ public abstract class GLDrawableImpl implements GLDrawable {
                 ",\n\tSurface   "+getNativeSurface()+"]";
   }
 
-  protected static String getThreadName() {
-    return Thread.currentThread().getName();
-  }
+  protected static String getThreadName() { return Thread.currentThread().getName(); }
 
   protected GLDrawableFactory factory;
   protected NativeSurface surface;
@@ -297,6 +358,6 @@ public abstract class GLDrawableImpl implements GLDrawable {
   // result of calling show() on the main thread. To work around this
   // we prevent any JAWT or OpenGL operations from being done until
   // addNotify() is called on the surface.
-  protected boolean realized;
+  protected volatile boolean realized;
 
 }
diff --git a/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java
index 4c82fc2..8ba9f61 100644
--- a/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java
@@ -36,16 +36,29 @@ public abstract class GLDynamicLibraryBundleInfo implements DynamicLibraryBundle
     protected GLDynamicLibraryBundleInfo() {
     }
 
-    /** default **/
-    @Override
-    public boolean shallLinkGlobal() { return false; }
-
-    /** default **/
+    /** 
+     * Returns <code>true</code>,
+     * since we might load a desktop GL library and allow symbol access to subsequent libs.
+     * <p>
+     * This respects old DRI requirements:
+     * <pre>
+     * http://dri.sourceforge.net/doc/DRIuserguide.html
+     * </pre>
+     * </p>
+     */
+    public final boolean shallLinkGlobal() { return true; }
+    
+    /**
+     * {@inheritDoc}
+     * <p>
+     * Returns <code>false</code>.
+     * </p>
+     */ 
     @Override
     public boolean shallLookupGlobal() { return false; }
 
     @Override
-    public RunnableExecutor getLibLoaderExecutor() {
+    public final RunnableExecutor getLibLoaderExecutor() {
         return DynamicLibraryBundle.getDefaultRunnableExecutor();
     }    
 }
diff --git a/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java b/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java
index d2dac81..1ed73f1 100644
--- a/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java
@@ -36,7 +36,7 @@ public class GLDynamicLookupHelper extends DynamicLibraryBundle {
         super(info);
     }
 
-    public GLDynamicLibraryBundleInfo getGLBundleInfo() { return (GLDynamicLibraryBundleInfo) getBundleInfo(); }
+    public final GLDynamicLibraryBundleInfo getGLBundleInfo() { return (GLDynamicLibraryBundleInfo) getBundleInfo(); }
 
     /** NOP per default */
     public boolean loadGLULibrary() { return false; }
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index b5b723f..27024d4 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -11,7 +11,6 @@ import javax.media.opengl.GLContext;
 import javax.media.opengl.GLException;
 import javax.media.opengl.GLFBODrawable;
 
-import com.jogamp.common.os.Platform;
 import com.jogamp.common.util.VersionUtil;
 import com.jogamp.nativewindow.MutableGraphicsConfiguration;
 import com.jogamp.opengl.FBObject;
@@ -39,6 +38,7 @@ import com.jogamp.opengl.JoglVersion;
  */
 public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
     protected static final boolean DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject");
+    protected static final boolean DEBUG_SWAP = Debug.isPropertyDefined("jogl.debug.FBObject.Swap", true);
     
     private final GLDrawableImpl parent;
     private GLCapabilitiesImmutable origParentChosenCaps;
@@ -52,10 +52,16 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
     private int fboIBack;  // points to GL_BACK buffer
     private int fboIFront; // points to GL_FRONT buffer
     private int pendingFBOReset = -1;
+    /** Indicated whether the FBO is bound. */
     private boolean fboBound;
+    /** Indicated whether the FBO is swapped, resets to false after makeCurrent -> contextMadeCurrent. */
+    private boolean fboSwapped;
 
-    private static volatile boolean resetQuirkInfoDumped = false;
-    private static final int bufferCount = 2; // number of FBOs for double buffering. TODO: Possible to configure!
+    /** dump fboResetQuirk info only once pre ClassLoader and only in DEBUG mode */
+    private static volatile boolean resetQuirkInfoDumped = false; 
+    
+    /** number of FBOs for double buffering. TODO: Possible to configure! */
+    private static final int bufferCount = 2; 
     
     // private DoubleBufferMode doubleBufferMode; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
     
@@ -90,6 +96,9 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
     }
     
     private final void initialize(boolean realize, GL gl) {
+        if( initialized == realize ) {
+            throw new InternalError("Already set to initialize := "+realize+": "+this);
+        }
         if(realize) {
             final GLCapabilities chosenFBOCaps = (GLCapabilities) getChosenGLCapabilities(); // cloned at setRealized(true)
             
@@ -133,21 +142,20 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
                 }
             }
             fbos[fboIFront].resetSamplingSink(gl);
-            fboBound = false;
+
             fbos[0].formatToGLCapabilities(chosenFBOCaps);
             chosenFBOCaps.setDoubleBuffered( chosenFBOCaps.getDoubleBuffered() || samples > 0 );
-            
-            initialized = true;            
         } else {
-            initialized = false;
-            
             for(int i=0; i<fbos.length; i++) {
                 fbos[i].destroy(gl);
             }
             fbos=null;
-            fboBound = false;   
-            pendingFBOReset = -1;
         }
+        fboBound = false;
+        fboSwapped = false;
+        pendingFBOReset = -1;
+        initialized = realize;
+        
         if(DEBUG) {
             System.err.println("GLFBODrawableImpl.initialize("+realize+"): "+this);
             Thread.dumpStack();
@@ -167,23 +175,23 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
                 }
                 return;
             } catch (GLException e) {
+                fboResetQuirk = true;
                 if(DEBUG) {
-                    e.printStackTrace();
-                }
-                if(!resetQuirkInfoDumped) { // dump info only once
-                    resetQuirkInfoDumped = true;
-                    System.err.println("GLFBODrawable: FBO Reset failed: "+e.getMessage());
-                    System.err.println("GLFBODrawable: Enabling FBOResetQuirk, due to GL driver bug.");
-                    final JoglVersion joglVersion = JoglVersion.getInstance();
-                    if(DEBUG) {
-                        System.err.println(VersionUtil.getPlatformInfo());
-                        System.err.println(joglVersion.toString());
-                        System.err.println(JoglVersion.getGLInfo(gl, null));
-                    } else {
-                        System.err.println(joglVersion.getBriefOSGLBuildInfo(gl, null));                        
+                    if(!resetQuirkInfoDumped) {
+                        resetQuirkInfoDumped = true;
+                        System.err.println("GLFBODrawable: FBO Reset failed: "+e.getMessage());
+                        System.err.println("GLFBODrawable: Enabling FBOResetQuirk, due to GL driver bug.");
+                        final JoglVersion joglVersion = JoglVersion.getInstance();
+                        if(DEBUG) {
+                            System.err.println(VersionUtil.getPlatformInfo());
+                            System.err.println(joglVersion.toString());
+                            System.err.println(JoglVersion.getGLInfo(gl, null));
+                        } else {
+                            System.err.println(joglVersion.getBriefOSGLBuildInfo(gl, null));                        
+                        }
+                        e.printStackTrace();
                     }
                 }
-                fboResetQuirk = true;
                 // 'fallthrough' intended
             }
         }
@@ -222,7 +230,9 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
         Throwable tFBO = null;
         Throwable tGL = null;
         ourContext.makeCurrent();
+        gl.glFinish(); // sync GL command stream
         fboBound = false; // clear bound-flag immediatly, caused by contextMadeCurrent(..) - otherwise we would swap @ release
+        fboSwapped = false;
         try {
             final int maxSamples = gl.getMaxRenderbufferSamples();        
             newSamples = newSamples <= maxSamples ? newSamples : maxSamples;
@@ -302,6 +312,9 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
     protected final int getDefaultReadFramebuffer() { return initialized ? fbos[fboIFront].getReadFramebuffer() : 0; }
 
     @Override
+    protected final int getDefaultReadBuffer(GL gl) { return initialized ? fbos[fboIFront].getDefaultReadBuffer() : GL.GL_COLOR_ATTACHMENT0 ; }
+    
+    @Override
     protected final void setRealizedImpl() {
         final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration();
         if(realized) {
@@ -317,24 +330,27 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
     }
     
     @Override
-    protected final void contextRealized(GLContext glc, boolean realized) {
-        initialize(realized, glc.getGL());
+    protected void associateContext(GLContext glc, boolean bound) {
+        initialize(bound, glc.getGL());        
     }
     
     @Override
     protected final void contextMadeCurrent(GLContext glc, boolean current) {
         final GL gl = glc.getGL();
         if(current) {
+            if( !initialized ) {
+                throw new GLException("Not initialized: "+this);
+            }
             fbos[fboIBack].bind(gl);
             fboBound = true;
-        } else {
-            if(fboBound) {
-                swapFBOImpl(glc);
-                swapFBOImplPost(glc);
-                fboBound=false;
-                if(DEBUG) {
-                    System.err.println("Post FBO swap(@release): done");
-                }
+            fboSwapped = false;
+        } else if( fboBound && !fboSwapped ) {
+            swapFBOImpl(glc);
+            swapFBOImplPost(glc);
+            fboBound=false;
+            fboSwapped=true;
+            if(DEBUG_SWAP) {
+                System.err.println("Post FBO swap(@release): done");
             }
         }
     }
@@ -342,18 +358,18 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
     @Override
     protected void swapBuffersImpl(boolean doubleBuffered) {
         final GLContext ctx = GLContext.getCurrent();
-        boolean doPostSwap = false;
-        if(null!=ctx && ctx.getGLDrawable()==this) {
-            if(fboBound) {
-                swapFBOImpl(ctx);
-                doPostSwap = true;
-                fboBound=false;
-                if(DEBUG) {
-                    System.err.println("Post FBO swap(@swap): done");
-                }
+        boolean doPostSwap;
+        if( null != ctx && ctx.getGLDrawable() == this && fboBound ) {
+            swapFBOImpl(ctx);
+            doPostSwap = true;
+            fboSwapped = true;
+            if(DEBUG_SWAP) {
+                System.err.println("Post FBO swap(@swap): done");
             }
+        } else {
+            doPostSwap = false;
         }
-        if(null != swapBufferContext) {
+        if( null != swapBufferContext ) {
             swapBufferContext.swapBuffers(doubleBuffered);
         }
         if(doPostSwap) {
@@ -400,7 +416,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
                 gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbos[fboIFront].getReadFramebuffer());
         } */
         
-        if(DEBUG) {
+        if(DEBUG_SWAP) {
             System.err.println("Post FBO swap(X): fboI back "+fboIBack+", front "+fboIFront+", num "+fbos.length);
         }
     }
@@ -435,6 +451,17 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
         }
     }
     
+    @Override
+    public final int setNumBuffers(int bufferCount) throws GLException {
+        // FIXME: Implement
+        return bufferCount;
+    }
+    
+    @Override
+    public final int getNumBuffers() {
+        return bufferCount;
+    }
+    
     /** // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
     @Override
     public final DoubleBufferMode getDoubleBufferMode() {
@@ -525,7 +552,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
         @Override
         public final void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException {
             if(DEBUG) {
-                System.err.println("GLFBODrawableImpl.ResizeableImpl setSize: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+                System.err.println("GLFBODrawableImpl.ResizeableImpl setSize: ("+getThreadName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
             }
             int lockRes = lockSurface();
             if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
index 31e52b8..48b5092 100644
--- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
+++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
@@ -33,6 +33,7 @@ import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLCapabilitiesImmutable;
 import javax.media.opengl.GLContext;
 import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLProfile;
 
 import com.jogamp.opengl.GLRendererQuirks;
 
@@ -101,17 +102,16 @@ public class GLGraphicsConfigurationUtil {
      * @return bitmask representing the input boolean in exclusive or logic, ie only one bit will be set.
      */
     public static final int getExclusiveWinAttributeBits(boolean isOnscreen, boolean isFBO, boolean isPBuffer, boolean isBitmap) {
-        int winattrbits = 0;
+        final int winattrbits;
         if(isOnscreen) {
-            winattrbits |= WINDOW_BIT;
+            winattrbits = WINDOW_BIT;
         } else if(isFBO) {
-            winattrbits |= FBO_BIT;
+            winattrbits = FBO_BIT;
         } else if(isPBuffer ){
-            winattrbits |= PBUFFER_BIT;
+            winattrbits = PBUFFER_BIT;
         } else if(isBitmap) {
-            winattrbits |= BITMAP_BIT;                
-        }
-        if(0 == winattrbits) {
+            winattrbits = BITMAP_BIT;                
+        } else {
             throw new InternalError("Empty bitmask");
         }
         return winattrbits;
@@ -287,4 +287,45 @@ public class GLGraphicsConfigurationUtil {
         }
         return capsRequested;
     }
+    
+    public static GLCapabilitiesImmutable clipRGBAGLCapabilities(GLCapabilitiesImmutable caps, boolean allowRGB555, boolean allowAlpha)
+    {
+        final int iR = caps.getRedBits();
+        final int iG = caps.getGreenBits();
+        final int iB = caps.getBlueBits();
+        final int iA = caps.getAlphaBits();
+        final int oR = clipColor(iR, allowRGB555);
+        final int oG = clipColor(iG, allowRGB555);
+        final int oB = clipColor(iB, allowRGB555);
+        final int oA = ( allowAlpha && 0 < iA ) ? oR : 0 ; // align alpha to red if requested and allowed
+        if( iR != oR || iG != oG || iB != oB || iA != oA ) {
+            final GLCapabilities caps2 = (GLCapabilities) caps.cloneMutable();
+            caps2.setRedBits(oR);
+            caps2.setGreenBits(oG);
+            caps2.setBlueBits(oB);
+            caps2.setAlphaBits(oA);
+            return caps2;            
+        }
+        return caps;
+    }
+    
+    public static int clipColor(final int compIn, final boolean allowRGB555) {
+        final int compOut;
+        if( 5 < compIn || !allowRGB555 ) {
+            compOut = 8; 
+        } else {
+            compOut = 5;
+        }        
+        return compOut;
+    }
+    
+    public static GLCapabilitiesImmutable fixGLProfile(GLCapabilitiesImmutable caps, GLProfile glp)
+    {
+        if( caps.getGLProfile() != glp ) {
+            final GLCapabilities caps2 = (GLCapabilities) caps.cloneMutable();
+            caps2.setGLProfile(glp);
+            return caps2;
+        }
+        return caps;
+    }
 }
diff --git a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
index 7701f20..6d91163 100644
--- a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
@@ -44,8 +44,11 @@ import jogamp.opengl.GLFBODrawableImpl;
 public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implements GLOffscreenAutoDrawable {
   
     /**
-     * @param drawable a valid and already realized {@link GLDrawable}
-     * @param context a valid {@link GLContext}, may not be made current (created) yet.
+     * @param drawable a valid {@link GLDrawable}, may not be {@link GLDrawable#isRealized() realized} yet.
+     * @param context a valid {@link GLContext}, 
+     *                may not have been made current (created) yet,
+     *                may not be associated w/ <code>drawable<code> yet,
+     *                may be <code>null</code> for lazy initialization
      * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
      * @param lock optional upstream lock, may be null
      */
@@ -60,8 +63,11 @@ public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implemen
     
     public static class FBOImpl extends GLOffscreenAutoDrawableImpl implements GLOffscreenAutoDrawable.FBO {      
         /**
-         * @param drawable a valid and already realized {@link GLDrawable}
-         * @param context a valid {@link GLContext}, may not be made current (created) yet.
+         * @param drawable a valid {@link GLDrawable}, may not be {@link GLDrawable#isRealized() realized} yet.
+         * @param context a valid {@link GLContext}, 
+         *                may not have been made current (created) yet,
+         *                may not be associated w/ <code>drawable<code> yet,
+         *                may be <code>null</code> for lazy initialization
          * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
          * @param lock optional upstream lock, may be null
          */
@@ -95,6 +101,16 @@ public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implemen
             windowRepaintOp();
         }
         
+        @Override
+        public final int setNumBuffers(int bufferCount) throws GLException {
+            return ((GLFBODrawableImpl)drawable).setNumBuffers(bufferCount);
+        }
+        
+        @Override
+        public final int getNumBuffers() {
+            return ((GLFBODrawableImpl)drawable).getNumBuffers();
+        }
+        
         /** // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
         @Override
         public DoubleBufferMode getDoubleBufferMode() {
diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
index b438131..b8841d6 100644
--- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
@@ -49,7 +49,6 @@ import com.jogamp.common.util.locks.RecursiveLock;
 
 @SuppressWarnings("deprecation")
 public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
-  private int floatMode;
 
   public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContextImpl pbufferContext) {
     super(pbufferDrawable, pbufferContext, true); // drawable := pbufferDrawable, context := pbufferContext  
@@ -59,36 +58,15 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
   // pbuffer specifics
   //
 
-  @Override
-  public void bindTexture() {
-    // Doesn't make much sense to try to do this on the event dispatch
-    // thread given that it has to be called while the context is current
-    context.bindPbufferToTexture();
-  }
-
-  @Override
-  public void releaseTexture() {
-    // Doesn't make much sense to try to do this on the event dispatch
-    // thread given that it has to be called while the context is current
-    context.releasePbufferFromTexture();
-  }
-
-  @Override
-  public int getFloatingPointMode() {
-    if (floatMode == 0) {
-      throw new GLException("Pbuffer not initialized, or floating-point support not requested");
-    }
-    return floatMode;
-  }
-
   //
   // GLDrawable delegation
   // 
     
   @Override
-  public final void setRealized(boolean realized) {
+  public final void swapBuffers() throws GLException {
+      defaultSwapBuffers();
   }
-
+  
   //
   // GLAutoDrawable completion
   //
@@ -118,27 +96,10 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
     _lock.lock(); // sync: context/drawable could been recreated/destroyed while animating
     try {
         if( null != context ) {
-          helper.invokeGL(drawable, context, defaultDisplayAction, initAction);
+          helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction);
         }
     } finally {
         _lock.unlock();
     }
   }
-
-  @Override
-  public final void swapBuffers() throws GLException {
-      defaultSwapBuffers();
-  }
-  
-  //----------------------------------------------------------------------
-  // Internals only below this point
-  //
-
-  protected final Runnable initAction = new Runnable() {
-    @Override
-    public final void run() {
-        floatMode = context.getFloatingPointMode();
-        defaultInitAction.run();
-    } };
-  
 }
diff --git a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
index 1004f04..cea3ac4 100644
--- a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
+++ b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
@@ -28,96 +28,103 @@
 
 package jogamp.opengl;
 
-import java.util.StringTokenizer;
 import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.VersionNumberString;
 
 /**
  * A class for storing and comparing OpenGL version numbers.
  * This only works for desktop OpenGL at the moment.
  */
-class GLVersionNumber extends VersionNumber {
+public class GLVersionNumber extends VersionNumberString {
 
-    protected boolean valid;
+    private final boolean valid;
 
-    public GLVersionNumber(int majorRev, int minorRev, int subMinorRev) {
-        super(majorRev, minorRev, subMinorRev);
-        valid = true;
+    private GLVersionNumber(int[] val, int strEnd, short state, String versionString, boolean valid) {
+        super(val[0], val[1], val[2], strEnd, state, versionString);
+        this.valid = valid;
     }
-
-    public GLVersionNumber(String versionString) {
-        super();
-        valid = false;
-        try {
-            if (versionString.startsWith("GL_VERSION_")) {
-                StringTokenizer tok = new StringTokenizer(versionString, "_");
-                tok.nextToken(); // GL_
-                tok.nextToken(); // VERSION_
-                if (!tok.hasMoreTokens()) {
-                    val[0] = 0;
-                    return;
-                }
-                val[0] = Integer.valueOf(tok.nextToken()).intValue();
-                if (!tok.hasMoreTokens()) {
-                    val[1] = 0;
-                    return;
-                }
-                val[1] = Integer.valueOf(tok.nextToken()).intValue();
-                if (!tok.hasMoreTokens()) {
-                    val[2] = 0;
-                    return;
-                }
-                val[2] = Integer.valueOf(tok.nextToken()).intValue();
-            } else {
-                int radix = 10;
-                if (versionString.length() > 2) {
-                    if (Character.isDigit(versionString.charAt(0)) && versionString.charAt(1) == '.' && Character.isDigit(versionString.charAt(2))) {
-                        val[0] = Character.digit(versionString.charAt(0), radix);
-                        val[1] = Character.digit(versionString.charAt(2), radix);
-                        // See if there's version-specific information which might
-                        // imply a more recent OpenGL version
-                        StringTokenizer tok = new StringTokenizer(versionString, " ");
-                        if (tok.hasMoreTokens()) {
-                            tok.nextToken();
-                            if (tok.hasMoreTokens()) {
-                                String token = tok.nextToken();
-                                int i = 0;
-                                while (i < token.length() && !Character.isDigit(token.charAt(i))) {
-                                    i++;
-                                }
-                                if (i < token.length() - 2 && Character.isDigit(token.charAt(i)) && token.charAt(i + 1) == '.' && Character.isDigit(token.charAt(i + 2))) {
-                                    int altMajor = Character.digit(token.charAt(i), radix);
-                                    int altMinor = Character.digit(token.charAt(i + 2), radix);
-                                    // Avoid possibly confusing situations by putting some
-                                    // constraints on the upgrades we do to the major and
-                                    // minor versions
-                                    if ((altMajor == val[0] && altMinor > val[1]) || altMajor == val[0] + 1) {
-                                        val[0] = altMajor;
-                                        val[1] = altMinor;
-                                    }
-                                }
-                            }
-                        }
-                    }
+    
+    private static java.util.regex.Pattern getUnderscorePattern() {
+        if( null == _Pattern ) { // volatile dbl-checked-locking OK 
+            synchronized( VersionNumber.class ) {
+                if( null == _Pattern ) {
+                    _Pattern = getVersionNumberPattern("_");
                 }
             }
-            valid = true;
-        } catch (Exception e) {
-            e.printStackTrace();
-            // FIXME: refactor desktop OpenGL dependencies and make this
-            // class work properly for OpenGL ES
-            System.err.println("Info: ExtensionAvailabilityCache: FunctionAvailabilityCache.Version.<init>: " + e);
-            val[0] = 1;
-            val[1] = 0;
-            /*
-            throw (IllegalArgumentException)
-            new IllegalArgumentException(
-            "Illegally formatted version identifier: \"" + versionString + "\"")
-            .initCause(e);
-             */
         }
+        return _Pattern;
+    }
+    private static volatile java.util.regex.Pattern _Pattern = null;
+    
+    public static final GLVersionNumber create(String versionString) {
+        int[] val = new int[] { 0, 0, 0 };
+        int strEnd = 0;
+        short state = 0;
+        boolean valid = false;
+        if (versionString != null && versionString.length() > 0) {
+            try {
+                final java.util.regex.Pattern versionPattern;
+                if (versionString.startsWith("GL_VERSION_")) {
+                    versionPattern = getUnderscorePattern();
+                } else {
+                    versionPattern = VersionNumberString.getDefaultVersionNumberPattern();
+                }
+                final VersionNumberString version = new VersionNumberString(versionString, versionPattern);
+                strEnd = version.endOfStringMatch();
+                val[0] = version.getMajor();
+                val[1] = version.getMinor();
+                state = (short) ( ( version.hasMajor() ? VersionNumber.HAS_MAJOR : (short)0 ) | 
+                                  ( version.hasMinor() ? VersionNumber.HAS_MINOR : (short)0 ) );
+                valid = version.hasMajor() && version.hasMinor(); // Requires at least a defined major and minor version component!
+            } catch (Exception e) {
+                e.printStackTrace();
+                System.err.println("Info: ExtensionAvailabilityCache: FunctionAvailabilityCache.Version.<init>: " + e);
+                val[0] = 1;
+                val[1] = 0;
+            }
+        }    
+        return new GLVersionNumber(val, strEnd, state, versionString, valid);
     }
 
     public final boolean isValid() {
         return valid;
     }
+    
+    /** 
+     * Returns the optional vendor version at the end of the 
+     * <code>GL_VERSION</code> string if exists, otherwise the {@link VersionNumberString#zeroVersion zero version} instance.
+     * <pre>
+     *   2.1 Mesa 7.0.3-rc2 -> 7.0.3 (7.0.3-rc2)
+     *   2.1 Mesa 7.12-devel (git-d6c318e) -> 7.12.0 (7.12-devel)
+     *   4.2.12171 Compatibility Profile Context 9.01.8 -> 9.1.8 (9.01.8)
+     *   4.2.12198 Compatibility Profile Context 12.102.3.0 -> 12.102.3 (12.102.3.0)
+     *   4.3.0 NVIDIA 310.32 -> 310.32 (310.32)
+     * </pre>
+     */
+    public static final VersionNumberString createVendorVersion(String versionString) {
+        if (versionString == null || versionString.length() <= 0) {
+            return null;
+        }
+        
+        // Skip the 1st GL version
+        String str;
+        {
+            final GLVersionNumber glv = create(versionString);
+            str = versionString.substring(glv.endOfStringMatch());
+        }
+        
+        while ( str.length() > 0 ) {
+            final VersionNumberString version = new VersionNumberString(str, getDefaultVersionNumberPattern());
+            final int eosm = version.endOfStringMatch();
+            if( 0 < eosm ) {
+                if( version.hasMajor() && version.hasMinor() ) { // Requires at least a defined major and minor version component!
+                    return version;
+                }
+                str = str.substring( eosm );
+            } else {
+                break; // no match
+            }
+        }
+        return VersionNumberString.zeroVersion;
+    }
 }
diff --git a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java
index f7d59e1..112dfcb 100644
--- a/src/jogl/classes/jogamp/opengl/GLWorkerThread.java
+++ b/src/jogl/classes/jogamp/opengl/GLWorkerThread.java
@@ -219,9 +219,7 @@ public class GLWorkerThread {
     return (Thread.currentThread() == thread);
   }
 
-  protected static String getThreadName() {
-    return Thread.currentThread().getName();
-  }
+  protected static String getThreadName() { return Thread.currentThread().getName(); }
   
   static class WorkerRunnable implements Runnable {
     public void run() {
diff --git a/src/jogl/classes/jogamp/opengl/MemoryObject.java b/src/jogl/classes/jogamp/opengl/MemoryObject.java
index 2927007..df793da 100644
--- a/src/jogl/classes/jogamp/opengl/MemoryObject.java
+++ b/src/jogl/classes/jogamp/opengl/MemoryObject.java
@@ -31,19 +31,21 @@ package jogamp.opengl;
 import java.nio.ByteBuffer;
 import java.util.HashMap;
 
+import com.jogamp.common.util.HashUtil;
+
 /**
  *
  */
 public class MemoryObject {
     private long addr;
     private long size;
-    private int  hash32;
+    private int  hash;
     private ByteBuffer buffer=null;
 
     public MemoryObject(long addr, long size) {
         this.addr = addr;
         this.size = size;
-        this.hash32 = getHash32(addr, size);
+        this.hash = HashUtil.getAddrSizeHash32_EqualDist(addr, size);
     }
 
     public void setBuffer(ByteBuffer buffer) {
@@ -55,54 +57,14 @@ public class MemoryObject {
     }
 
     /**
-     * @return the 32bit hash value generated via {@link #getHash32(long, long)}
+     * @return the 32bit hash value generated via {@link HashUtil#getAddrSizeHash32_EqualDist(long, long)}.
      */
     public int hashCode() {
-        return hash32;
-    }
-
-    /**
-     * Ignores the optional attached <code>ByteBuffer</code> intentionally.<br>
-     * 
-     * @return true of reference is equal or <code>obj</code> is of type <code>MemoryObject</code>
-     *         and <code>addr</code> and <code>size</code> is equal.<br>
-     */
-    public boolean equals(Object obj) {
-        if(this == obj) { return true; }
-        if(obj instanceof MemoryObject) {
-            MemoryObject m = (MemoryObject) obj;
-            return addr == m.addr && size == m.size ;
-        }
-        return false;
-    }
-
-    /**
-     * Generates a 32bit hash value by <code>addr</code> and <code>size</code>.<br>
-     * Ignores the optional attached <code>ByteBuffer</code> intentionally.<br>
-     */
-    public static int getHash32(long addr, long size) {
-        // avoid xor collisions of eg low/high parts
-        // 31 * x == (x << 5) - x
-        int  hash = 31 +              (int)   addr          ; // lo addr
-        hash = ((hash << 5) - hash) + (int) ( addr >>> 32 ) ; // hi addr
-        hash = ((hash << 5) - hash) + (int)   size          ; // lo size
-        hash = ((hash << 5) - hash) + (int) ( size >>> 32 ) ; // hi size
-
         return hash;
     }
 
-    /**
-     * Generates a 64bit hash value by <code>addr</code> and <code>size</code>.<br>
-     * Ignores the optional attached <code>ByteBuffer</code> intentionally.<br>
-     */
-    public static long getHash64(long addr, long size) {
-        // 31 * x == (x << 5) - x
-        final long hash = 31 + addr;
-        return ((hash << 5) - hash) + size;
-    }
-
     public String toString() {
-        return "MemoryObject[addr 0x"+Long.toHexString(addr)+", size 0x"+Long.toHexString(size)+", hash32: 0x"+Integer.toHexString(hash32)+"]";
+        return "MemoryObject[addr 0x"+Long.toHexString(addr)+", size 0x"+Long.toHexString(size)+", hash32: 0x"+Integer.toHexString(hash)+"]";
     }
 
     /**
diff --git a/src/jogl/classes/jogamp/opengl/ProjectFloat.java b/src/jogl/classes/jogamp/opengl/ProjectFloat.java
index 18fe3e7..439ddc7 100644
--- a/src/jogl/classes/jogamp/opengl/ProjectFloat.java
+++ b/src/jogl/classes/jogamp/opengl/ProjectFloat.java
@@ -122,7 +122,7 @@ import java.nio.IntBuffer;
 import javax.media.opengl.fixedfunc.GLMatrixFunc;
 
 import com.jogamp.common.nio.Buffers;
-import com.jogamp.opengl.FloatUtil;
+import com.jogamp.opengl.math.FloatUtil;
 
 /**
  * ProjectFloat.java
diff --git a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
index 0528d30..f454904 100644
--- a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
+++ b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
@@ -33,19 +33,29 @@ import java.util.Iterator;
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.AbstractGraphicsScreen;
 
+import com.jogamp.opengl.GLRendererQuirks;
+
 public class SharedResourceRunner implements Runnable {
     protected static final boolean DEBUG = GLDrawableImpl.DEBUG;
 
     public static interface Resource {
+      boolean isValid();
       AbstractGraphicsDevice getDevice();
       AbstractGraphicsScreen getScreen();
       GLDrawableImpl getDrawable();
       GLContextImpl getContext();
+      GLRendererQuirks getRendererQuirks();
     }
 
     public static interface Implementation {
         /**
          * @param connection for creation a {@link AbstractGraphicsDevice} instance. 
+         * @return <code>true</code> if the device supports all protocols required for the implementation, otherwise <code>false</code>. 
+         */
+        boolean isDeviceSupported(String connection);
+        
+        /**
+         * @param connection for creation a {@link AbstractGraphicsDevice} instance. 
          * @return A new shared resource instance 
          */
         Resource createSharedResource(String connection);
@@ -110,17 +120,17 @@ public class SharedResourceRunner implements Runnable {
         if(null != thread && !thread.isAlive()) {
             // thread was killed unrecognized ..
             if (DEBUG) {
-                System.err.println("SharedResourceRunner.start() - dead-old-thread cleanup - "+Thread.currentThread().getName());
+                System.err.println("SharedResourceRunner.start() - dead-old-thread cleanup - "+getThreadName());
             }
             releaseSharedResources();
             thread = null;
         }        
         if(null == thread) {
             if (DEBUG) {
-                System.err.println("SharedResourceRunner.start() - start new Thread - "+Thread.currentThread().getName());
+                System.err.println("SharedResourceRunner.start() - start new Thread - "+getThreadName());
             }
             resetState();
-            thread = new Thread(this, Thread.currentThread().getName()+"-SharedResourceRunner");
+            thread = new Thread(this, getThreadName()+"-SharedResourceRunner");
             thread.setDaemon(true); // Allow JVM to exit, even if this one is running
             thread.start();
         }
@@ -130,7 +140,7 @@ public class SharedResourceRunner implements Runnable {
     public void stop() {
         if(null != thread) {
             if (DEBUG) {
-                System.err.println("SharedResourceRunner.stop() - "+Thread.currentThread().getName());
+                System.err.println("SharedResourceRunner.stop() - "+getThreadName());
             }
             synchronized (this) {
                 shouldRelease = true;
@@ -155,12 +165,14 @@ public class SharedResourceRunner implements Runnable {
             if (null == sr && !getDeviceTried(connection)) {
                 addDeviceTried(connection);
                 if (DEBUG) {
-                    System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": trying - "+Thread.currentThread().getName());
+                    System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": trying - "+getThreadName());
+                }
+                if ( impl.isDeviceSupported(connection) ) {
+                    doAndWait(connection, null);
+                    sr = impl.mapGet(connection);
                 }
-                doAndWait(connection, null);
-                sr = impl.mapGet(connection);
                 if (DEBUG) {
-                    System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) +" - "+Thread.currentThread().getName());
+                    System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) +" - "+getThreadName());
                 }
             }
         }
@@ -175,11 +187,11 @@ public class SharedResourceRunner implements Runnable {
             if (null != sr) {
                 removeDeviceTried(connection);
                 if (DEBUG) {
-                    System.err.println("SharedResourceRunner.releaseShared() " + connection + ": trying - "+Thread.currentThread().getName());
+                    System.err.println("SharedResourceRunner.releaseShared() " + connection + ": trying - "+getThreadName());
                 }
                 doAndWait(null, connection);
                 if (DEBUG) {
-                    System.err.println("SharedResourceRunner.releaseShared() " + connection + ": done - "+Thread.currentThread().getName());
+                    System.err.println("SharedResourceRunner.releaseShared() " + connection + ": done - "+getThreadName());
                 }
             }
         }
@@ -189,7 +201,7 @@ public class SharedResourceRunner implements Runnable {
     private final void doAndWait(String initConnection, String releaseConnection) {
         // wait until thread becomes ready to init new device,
         // pass the device and release the sync
-        final String threadName = Thread.currentThread().getName();
+        final String threadName = getThreadName();
         if (DEBUG) {
             System.err.println("SharedResourceRunner.doAndWait() START init: " + initConnection + ", release: "+releaseConnection+" - "+threadName);
         }
@@ -222,7 +234,7 @@ public class SharedResourceRunner implements Runnable {
     }
 
     public final void run() {
-        final String threadName = Thread.currentThread().getName();
+        final String threadName = getThreadName();
 
         if (DEBUG) {
             System.err.println("SharedResourceRunner.run(): STARTED - " + threadName);
@@ -241,7 +253,7 @@ public class SharedResourceRunner implements Runnable {
                 } catch (InterruptedException ex) { 
                     shouldRelease = true;
                     if(DEBUG) {
-                        System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+Thread.currentThread().getName());                        
+                        System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+threadName);
                         ex.printStackTrace();
                     }
                 }
@@ -260,9 +272,7 @@ public class SharedResourceRunner implements Runnable {
                         try {
                             sr = impl.createSharedResource(initConnection);
                         } catch (Exception e) {
-                            if(DEBUG) {
-                                e.printStackTrace();
-                            }
+                            e.printStackTrace();
                         }
                         if (null != sr) {
                             impl.mapPut(initConnection, sr);
@@ -313,10 +323,12 @@ public class SharedResourceRunner implements Runnable {
             try {
                 impl.releaseSharedResource(iter.next());
             } catch (Throwable t) {
-                System.err.println("Catched Exception: "+t.getStackTrace()+" - "+Thread.currentThread().getName());
+                System.err.println("Catched Exception on thread "+getThreadName());
                 t.printStackTrace();
             }
         }
         impl.clear();
     }
+
+    protected static String getThreadName() { return Thread.currentThread().getName(); }
 }
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
index 983f111..56f00b3 100644
--- a/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
+++ b/src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java
@@ -44,7 +44,8 @@ import java.awt.EventQueue;
 
 import javax.media.opengl.GLException;
 
-import jogamp.common.awt.AWTEDTExecutor;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+
 import jogamp.opengl.GLWorkerThread;
 import jogamp.opengl.ThreadingImpl;
 import jogamp.opengl.ToolkitThreadingPlugin;
@@ -94,11 +95,7 @@ public class AWTThreadingPlugin implements ToolkitThreadingPlugin {
         // QFT which is not allowed. For now, on X11 platforms,
         // continue to perform this work on the EDT.
         if (wait && Java2D.isOGLPipelineActive() && !ThreadingImpl.isX11()) {
-          if(wait) {
-              Java2D.invokeWithOGLContextCurrent(null, r);
-          } else {
-              
-          }
+          Java2D.invokeWithOGLContextCurrent(null, r);
         } else {
           AWTEDTExecutor.singleton.invoke(wait, r);
         }
diff --git a/src/jogl/classes/jogamp/opengl/awt/Java2D.java b/src/jogl/classes/jogamp/opengl/awt/Java2D.java
index 3dbfefb..edf9e89 100644
--- a/src/jogl/classes/jogamp/opengl/awt/Java2D.java
+++ b/src/jogl/classes/jogamp/opengl/awt/Java2D.java
@@ -69,6 +69,7 @@ public class Java2D {
   private static boolean DEBUG = Debug.debug("Java2D");
   private static boolean isHeadless;
   private static boolean isOGLPipelineActive;
+  private static boolean isOGLPipelineResourceCompatible;
   private static Method invokeWithOGLContextCurrentMethod;
   private static Method isQueueFlusherThreadMethod;
   private static Method getOGLViewportMethod;
@@ -124,19 +125,37 @@ public class Java2D {
             isHeadless = true;
             // Figure out whether the default graphics configuration is an
             // OpenGL graphics configuration
-            GraphicsConfiguration cfg =
-              GraphicsEnvironment.getLocalGraphicsEnvironment().
-              getDefaultScreenDevice().
-              getDefaultConfiguration();
+            final GraphicsConfiguration cfg;
+            final String cfgName;
+            final boolean java2dOGLDisabledByOS = Platform.OS_TYPE == Platform.OSType.MACOS;
+            final boolean java2dOGLDisabledByProp;
+            {
+                boolean enabled = true;
+                final String sVal = System.getProperty("sun.java2d.opengl");
+                if( null != sVal ) {
+                    enabled = Boolean.valueOf(sVal);
+                }
+                java2dOGLDisabledByProp = !enabled;
+            }
+            if( !java2dOGLDisabledByProp && !java2dOGLDisabledByOS ) {
+                cfg = GraphicsEnvironment.getLocalGraphicsEnvironment().
+                        getDefaultScreenDevice().getDefaultConfiguration();
+                cfgName = cfg.getClass().getName();
+            } else {
+                if (DEBUG) {
+                  System.err.println("Java2D support disabled: by Property "+java2dOGLDisabledByProp+", by OS "+java2dOGLDisabledByOS);
+                }                
+                cfg = null;
+                cfgName = "nil";
+            }
             // If we get here, we aren't running in headless mode
             isHeadless = false;
-            String name = cfg.getClass().getName();
             if (DEBUG) {
-              System.err.println("Java2D support: default GraphicsConfiguration = " + name);
+              System.err.println("Java2D support: default GraphicsConfiguration = " + cfgName);
             }
-            isOGLPipelineActive = Platform.OS_TYPE != Platform.OSType.MACOS &&
-                                  (name.startsWith("sun.java2d.opengl"));
-
+            isOGLPipelineActive = cfgName.startsWith("sun.java2d.opengl");
+            isOGLPipelineResourceCompatible = isOGLPipelineActive; 
+            
             if (isOGLPipelineActive) {
               try {
                 // Try to get methods we need to integrate
@@ -152,99 +171,101 @@ public class Java2D {
                                                                      new Class[] {});
                 isQueueFlusherThreadMethod.setAccessible(true);
 
-                getOGLViewportMethod = utils.getDeclaredMethod("getOGLViewport",
-                                                               new Class[] {
-                                                                 Graphics.class,
-                                                                 Integer.TYPE,
-                                                                 Integer.TYPE
-                                                               });
-                getOGLViewportMethod.setAccessible(true);
-
-                getOGLScissorBoxMethod = utils.getDeclaredMethod("getOGLScissorBox",
-                                                                 new Class[] {
-                                                                   Graphics.class
-                                                                 });
-                getOGLScissorBoxMethod.setAccessible(true);
-
-                getOGLSurfaceIdentifierMethod = utils.getDeclaredMethod("getOGLSurfaceIdentifier",
+                if( isOGLPipelineResourceCompatible ) {
+                    getOGLViewportMethod = utils.getDeclaredMethod("getOGLViewport",
+                                                                   new Class[] {
+                                                                     Graphics.class,
+                                                                     Integer.TYPE,
+                                                                     Integer.TYPE
+                                                                   });
+                    getOGLViewportMethod.setAccessible(true);
+    
+                    getOGLScissorBoxMethod = utils.getDeclaredMethod("getOGLScissorBox",
+                                                                     new Class[] {
+                                                                       Graphics.class
+                                                                     });
+                    getOGLScissorBoxMethod.setAccessible(true);
+    
+                    getOGLSurfaceIdentifierMethod = utils.getDeclaredMethod("getOGLSurfaceIdentifier",
+                                                                            new Class[] {
+                                                                              Graphics.class
+                                                                            });
+                    getOGLSurfaceIdentifierMethod.setAccessible(true);
+    
+                    // Try to get additional methods required for proper FBO support
+                    fbObjectSupportInitialized = true;
+                    try {
+                      invokeWithOGLSharedContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLSharedContextCurrent",
+                                                                                        new Class[] {
+                                                                                          GraphicsConfiguration.class,
+                                                                                          Runnable.class
+                                                                                        });
+                      invokeWithOGLSharedContextCurrentMethod.setAccessible(true);
+    
+                      getOGLSurfaceTypeMethod = utils.getDeclaredMethod("getOGLSurfaceType",
                                                                         new Class[] {
                                                                           Graphics.class
                                                                         });
-                getOGLSurfaceIdentifierMethod.setAccessible(true);
-
-                // Try to get additional methods required for proper FBO support
-                fbObjectSupportInitialized = true;
-                try {
-                  invokeWithOGLSharedContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLSharedContextCurrent",
-                                                                                    new Class[] {
-                                                                                      GraphicsConfiguration.class,
-                                                                                      Runnable.class
-                                                                                    });
-                  invokeWithOGLSharedContextCurrentMethod.setAccessible(true);
-
-                  getOGLSurfaceTypeMethod = utils.getDeclaredMethod("getOGLSurfaceType",
-                                                                    new Class[] {
-                                                                      Graphics.class
-                                                                    });
-                  getOGLSurfaceTypeMethod.setAccessible(true);
-                } catch (Exception e) {
-                  fbObjectSupportInitialized = false;
-                  if (DEBUG) {
-                    e.printStackTrace();
-                    System.err.println("Info: Disabling Java2D/JOGL FBO support");
-                  }
-                }
-
-                // Try to get an additional method for FBO support in recent Mustang builds
-                try {
-                  getOGLTextureTypeMethod = utils.getDeclaredMethod("getOGLTextureType",
-                                                                    new Class[] {
-                                                                      Graphics.class
-                                                                    });
-                  getOGLTextureTypeMethod.setAccessible(true);
-                } catch (Exception e) {
-                  if (DEBUG) {
-                    e.printStackTrace();
-                    System.err.println("Info: GL_ARB_texture_rectangle FBO support disabled");
-                  }
-                }
-
-                // Try to set up APIs for enabling the bridge on OS X,
-                // where it isn't possible to create generalized
-                // external GLDrawables
-                Class<?> cglSurfaceData = null;
-                try {
-                  cglSurfaceData = Class.forName("sun.java2d.opengl.CGLSurfaceData");
-                } catch (Exception e) {
-                  if (DEBUG) {
-                    e.printStackTrace();
-                    System.err.println("Info: Unable to find class sun.java2d.opengl.CGLSurfaceData for OS X");
-                  }
-                }
-                if (cglSurfaceData != null) {
-                  // FIXME: for now, assume that FBO support is not enabled on OS X
-                  fbObjectSupportInitialized = false;
-
-                  // We need to find these methods in order to make the bridge work on OS X
-                  createOGLContextOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("createOGLContextOnSurface",
-                                                                                     new Class[] {
-                                                                                       Graphics.class,
-                                                                                       Long.TYPE
-                                                                                     });
-                  createOGLContextOnSurfaceMethod.setAccessible(true);
-
-                  makeOGLContextCurrentOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("makeOGLContextCurrentOnSurface",
-                                                                                          new Class[] {
-                                                                                            Graphics.class,
-                                                                                            Long.TYPE
-                                                                                          });
-                  makeOGLContextCurrentOnSurfaceMethod.setAccessible(true);
-
-                  destroyOGLContextMethod = cglSurfaceData.getDeclaredMethod("destroyOGLContext",
-                                                                             new Class[] {
-                                                                               Long.TYPE
-                                                                             });
-                  destroyOGLContextMethod.setAccessible(true);
+                      getOGLSurfaceTypeMethod.setAccessible(true);
+                    } catch (Exception e) {
+                      fbObjectSupportInitialized = false;
+                      if (DEBUG) {
+                        e.printStackTrace();
+                        System.err.println("Info: Disabling Java2D/JOGL FBO support");
+                      }
+                    }
+    
+                    // Try to get an additional method for FBO support in recent Mustang builds
+                    try {
+                      getOGLTextureTypeMethod = utils.getDeclaredMethod("getOGLTextureType",
+                                                                        new Class[] {
+                                                                          Graphics.class
+                                                                        });
+                      getOGLTextureTypeMethod.setAccessible(true);
+                    } catch (Exception e) {
+                      if (DEBUG) {
+                        e.printStackTrace();
+                        System.err.println("Info: GL_ARB_texture_rectangle FBO support disabled");
+                      }
+                    }
+    
+                    // Try to set up APIs for enabling the bridge on OS X,
+                    // where it isn't possible to create generalized
+                    // external GLDrawables
+                    Class<?> cglSurfaceData = null;
+                    try {
+                      cglSurfaceData = Class.forName("sun.java2d.opengl.CGLSurfaceData");
+                    } catch (Exception e) {
+                      if (DEBUG) {
+                        e.printStackTrace();
+                        System.err.println("Info: Unable to find class sun.java2d.opengl.CGLSurfaceData for OS X");
+                      }
+                    }
+                    if (cglSurfaceData != null) {
+                      // FIXME: for now, assume that FBO support is not enabled on OS X
+                      fbObjectSupportInitialized = false;
+    
+                      // We need to find these methods in order to make the bridge work on OS X
+                      createOGLContextOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("createOGLContextOnSurface",
+                                                                                         new Class[] {
+                                                                                           Graphics.class,
+                                                                                           Long.TYPE
+                                                                                         });
+                      createOGLContextOnSurfaceMethod.setAccessible(true);
+    
+                      makeOGLContextCurrentOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("makeOGLContextCurrentOnSurface",
+                                                                                              new Class[] {
+                                                                                                Graphics.class,
+                                                                                                Long.TYPE
+                                                                                              });
+                      makeOGLContextCurrentOnSurfaceMethod.setAccessible(true);
+    
+                      destroyOGLContextMethod = cglSurfaceData.getDeclaredMethod("destroyOGLContext",
+                                                                                 new Class[] {
+                                                                                   Long.TYPE
+                                                                                 });
+                      destroyOGLContextMethod.setAccessible(true);
+                    }
                 }
               } catch (Exception e) {
                 catched = e;
@@ -252,6 +273,7 @@ public class Java2D {
                   System.err.println("Info: Disabling Java2D/JOGL integration");
                 }
                 isOGLPipelineActive = false;
+                isOGLPipelineResourceCompatible = false;                
               }
             }
           } catch (HeadlessException e) {
@@ -265,7 +287,7 @@ public class Java2D {
             if(null != catched) {
                 catched.printStackTrace();
             }
-            System.err.println("JOGL/Java2D integration " + (isOGLPipelineActive ? "enabled" : "disabled"));
+            System.err.println("JOGL/Java2D OGL Pipeline active " + isOGLPipelineActive + ", resourceCompatible "+isOGLPipelineResourceCompatible);
           }
           return null;
         }
@@ -275,6 +297,10 @@ public class Java2D {
   public static boolean isOGLPipelineActive() {
     return isOGLPipelineActive;
   }
+  
+  public static boolean isOGLPipelineResourceCompatible() {
+    return isOGLPipelineResourceCompatible;
+  }
 
   public static boolean isFBOEnabled() {
     return fbObjectSupportInitialized;
@@ -330,7 +356,7 @@ public class Java2D {
       false if the passed GraphicsConfiguration was not an OpenGL
       GraphicsConfiguration. */
   public static boolean invokeWithOGLSharedContextCurrent(GraphicsConfiguration g, Runnable r) throws GLException {
-    checkActive();
+    checkCompatible();
 
     try {
       AWTUtil.lockToolkit();
@@ -355,7 +381,7 @@ public class Java2D {
   public static Rectangle getOGLViewport(Graphics g,
                                          int componentWidth,
                                          int componentHeight) {
-    checkActive();
+    checkCompatible();
 
     try {
       return (Rectangle) getOGLViewportMethod.invoke(null, new Object[] {g,
@@ -375,7 +401,7 @@ public class Java2D {
       passed to a call to glScissor(). Should only be called from the
       Queue Flusher Thread. */
   public static Rectangle getOGLScissorBox(Graphics g) {
-    checkActive();
+    checkCompatible();
 
     try {
       return (Rectangle) getOGLScissorBoxMethod.invoke(null, new Object[] {g});
@@ -393,7 +419,7 @@ public class Java2D {
       created (and the old ones destroyed). Should only be called from
       the Queue Flusher Thread.*/
   public static Object getOGLSurfaceIdentifier(Graphics g) {
-    checkActive();
+    checkCompatible();
 
     try {
       return getOGLSurfaceIdentifierMethod.invoke(null, new Object[] {g});
@@ -408,7 +434,7 @@ public class Java2D {
       object. This indicates, in particular, whether Java2D is
       currently rendering into a pbuffer or FBO. */
   public static int getOGLSurfaceType(Graphics g) {
-    checkActive();
+    checkCompatible();
 
     try {
       // FIXME: fallback path for pre-b73 (?) Mustang builds -- remove
@@ -429,7 +455,7 @@ public class Java2D {
       object assuming it is rendering to an FBO. Returns either
       GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB. */
   public static int getOGLTextureType(Graphics g) {
-    checkActive();
+    checkCompatible();
 
     if (getOGLTextureTypeMethod == null) {
       return GL.GL_TEXTURE_2D;
@@ -483,7 +509,7 @@ public class Java2D {
       associated with the given Graphics object, sharing textures and
       display lists with the specified (CGLContextObj) share context. */
   public static long createOGLContextOnSurface(Graphics g, long shareCtx) {
-    checkActive();
+    checkCompatible();
 
     try {
       return ((Long) createOGLContextOnSurfaceMethod.invoke(null, new Object[] { g, new Long(shareCtx) })).longValue();
@@ -497,7 +523,7 @@ public class Java2D {
   /** (Mac OS X-specific) Makes the given OpenGL context current on
       the surface associated with the given Graphics object. */
   public static boolean makeOGLContextCurrentOnSurface(Graphics g, long ctx) {
-    checkActive();
+    checkCompatible();
 
     try {
       return ((Boolean) makeOGLContextCurrentOnSurfaceMethod.invoke(null, new Object[] { g, new Long(ctx) })).booleanValue();
@@ -510,7 +536,7 @@ public class Java2D {
 
   /** (Mac OS X-specific) Destroys the given OpenGL context. */
   public static void destroyOGLContext(long ctx) {
-    checkActive();
+    checkCompatible();
 
     try {
       destroyOGLContextMethod.invoke(null, new Object[] { new Long(ctx) });
@@ -527,7 +553,13 @@ public class Java2D {
 
   private static void checkActive() {
     if (!isOGLPipelineActive()) {
-      throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)");
+      throw new GLException("Java2D OpenGL pipeline not active");
+    }
+  }
+  
+  private static void checkCompatible() {
+    if ( !isOGLPipelineResourceCompatible() ) {
+      throw new GLException("Java2D OpenGL pipeline not resource compatible");
     }
   }
 
@@ -562,7 +594,7 @@ public class Java2D {
     // Note 2: the first execution of this method must not be from the
     // Java2D Queue Flusher Thread.
 
-    if (isOGLPipelineActive() &&
+    if (isOGLPipelineResourceCompatible() &&
         isFBOEnabled() &&
         !initializedJ2DFBOShareContext) {
 
diff --git a/src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java b/src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java
deleted file mode 100644
index 4a5b1db..0000000
--- a/src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2006 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.
- * 
- * 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 jogamp.opengl.awt;
-
-import jogamp.opengl.*;
-import java.awt.Graphics;
-
-/** Provides a construct by which the shared GLJPanel code can
- * interact with a few methods in the Mac OS X-specific Java2D/JOGL
- * bridge implementation.
- */
-
-public interface Java2DGLContext {
-  public void setGraphics(Graphics g);
-}
diff --git a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java
index cddd142..3d59d1d 100644
--- a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java
@@ -36,8 +36,8 @@ import jogamp.opengl.*;
  * Implementation of the DynamicLookupHelper for Desktop ES2 (AMD, ..)
  * where EGL and ES2 functions reside within the desktop OpenGL library.
  */
-public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
-    static List<String> glueLibNames;
+public final class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
+    static final List<String> glueLibNames;
     static {
         glueLibNames = new ArrayList<String>();
         glueLibNames.add("jogl_mobile");
@@ -47,16 +47,6 @@ public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleIn
         super();
     }
 
-    /** 
-     * Might be a desktop GL library, and might need to allow symbol access to subsequent libs.
-     * 
-     * This respects old DRI requirements:<br>
-     * <pre>
-     * http://dri.sourceforge.net/doc/DRIuserguide.html
-     * </pre>
-     */
-    public boolean shallLinkGlobal() { return true; }
-    
     public final List<String> getToolGetProcAddressFuncNameList() {
         List<String> res = new ArrayList<String>();
         res.add("eglGetProcAddress");
@@ -71,7 +61,7 @@ public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleIn
         return true;
     }
     
-    public List<List<String>> getToolLibNames() {
+    public final List<List<String>> getToolLibNames() {
         final List<List<String>> libsList = new ArrayList<List<String>>();
         final List<String> libsGL = new ArrayList<String>();
         
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
index 84aeaa9..b54ed65 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
@@ -56,7 +56,7 @@ import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
 import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
 import com.jogamp.opengl.GLRendererQuirks;
 
-public abstract class EGLContext extends GLContextImpl {
+public class EGLContext extends GLContextImpl {
     private boolean eglQueryStringInitialized;
     private boolean eglQueryStringAvailable;
     private EGLExt _eglExt;
@@ -113,9 +113,14 @@ public abstract class EGLContext extends GLContextImpl {
     @Override
     protected void makeCurrentImpl() throws GLException {
         if (EGL.eglGetCurrentContext() != contextHandle) {
-            if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
-                throw new GLException("Error making context 0x" +
-                                      Long.toHexString(contextHandle) + " current: error code 0x" + Integer.toHexString(EGL.eglGetError()));
+            final long dpy = drawable.getNativeSurface().getDisplayHandle();
+            if (!EGL.eglMakeCurrent(dpy, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+                throw new GLException("Error making context " + toHexString(contextHandle) + 
+                                      " current on Thread " + getThreadName() +
+                                      " with display " + toHexString(dpy) +
+                                      ", drawableWrite " + toHexString(drawable.getHandle()) +
+                                      ", drawableRead "+ toHexString(drawableRead.getHandle()) +
+                                      " - Error code " + toHexString(EGL.eglGetError()) + ", " + this);
             }
         }
     }
@@ -123,8 +128,8 @@ public abstract class EGLContext extends GLContextImpl {
     @Override
     protected void releaseImpl() throws GLException {
       if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT)) {
-            throw new GLException("Error freeing OpenGL context 0x" +
-                                  Long.toHexString(contextHandle) + ": error code 0x" + Integer.toHexString(EGL.eglGetError()));
+            throw new GLException("Error freeing OpenGL context " + toHexString(contextHandle) + 
+                                  ": error code " + toHexString(EGL.eglGetError()));
       }
     }
 
@@ -133,8 +138,8 @@ public abstract class EGLContext extends GLContextImpl {
       if (!EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), contextHandle)) {
           final int eglError = EGL.eglGetError();
           if(EGL.EGL_SUCCESS != eglError) { /* oops, Mesa EGL impl. may return false, but has no EGL error */
-              throw new GLException("Error destroying OpenGL context 0x" +
-                                    Long.toHexString(contextHandle) + ": error code 0x" + Integer.toHexString(eglError));
+              throw new GLException("Error destroying OpenGL context " + toHexString(contextHandle) + 
+                                    ": error code " + toHexString(eglError));
           }
       }
     }
@@ -167,7 +172,7 @@ public abstract class EGLContext extends GLContextImpl {
         try {
             // might be unavailable on EGL < 1.2
             if(!EGL.eglBindAPI(EGL.EGL_OPENGL_ES_API)) {
-                throw new GLException("Catched: eglBindAPI to ES failed , error 0x"+Integer.toHexString(EGL.eglGetError()));
+                throw new GLException("Catched: eglBindAPI to ES failed , error "+toHexString(EGL.eglGetError()));
             }
         } catch (GLException glex) {
             if (DEBUG) {
@@ -214,7 +219,7 @@ public abstract class EGLContext extends GLContextImpl {
             throw new GLException("Error making context " +
                                   toHexString(contextHandle) + " current: error code " + toHexString(EGL.eglGetError()));
         }
-        setGLFunctionAvailability(true, glProfile.usesNativeGLES2() ? 2 : 1, 0, CTX_PROFILE_ES);
+        setGLFunctionAvailability(true, glProfile.usesNativeGLES2() ? 2 : 1, 0, CTX_PROFILE_ES, false);
         return true;
     }
 
@@ -254,8 +259,7 @@ public abstract class EGLContext extends GLContextImpl {
     protected final StringBuilder getPlatformExtensionsStringImpl() {
         StringBuilder sb = new StringBuilder();
         if (!eglQueryStringInitialized) {
-          eglQueryStringAvailable =
-            getDrawableImpl().getGLDynamicLookupHelper().dynamicLookupFunction("eglQueryString") != 0;
+          eglQueryStringAvailable = getDrawableImpl().getGLDynamicLookupHelper().isFunctionAvailable("eglQueryString");
           eglQueryStringInitialized = true;
         }
         if (eglQueryStringAvailable) {
@@ -281,7 +285,7 @@ public abstract class EGLContext extends GLContextImpl {
     //
     
     /* pp */ void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) {
-        mapStaticGLVersion(device, ctxMajorVersion, ctxMinorVersion, ctxOptions);
+        mapStaticGLVersion(device, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
     }
     /* pp */ int getContextOptions() { return ctxOptions; }    
     /* pp */ static void mapStaticGLESVersion(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps) {
@@ -344,14 +348,4 @@ public abstract class EGLContext extends GLContextImpl {
     public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
         throw new GLException("Should not call this");
     }
-
-    @Override
-    public boolean offscreenImageNeedsVerticalFlip() {
-        throw new GLException("Should not call this");
-    }
-
-    @Override
-    public int getOffscreenContextPixelDataType() {
-        throw new GLException("Should not call this");
-    }
 }
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
index 1f6f49f..f2efb04 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
@@ -38,7 +38,7 @@ import javax.media.opengl.GLException;
 
 import jogamp.opengl.Debug;
 
-import com.jogamp.common.util.LongIntHashMap;
+import com.jogamp.common.util.LongObjectHashMap;
 import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
 
 /** 
@@ -54,11 +54,26 @@ import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
 public class EGLDisplayUtil {
     protected static final boolean DEBUG = Debug.debug("EGLDisplayUtil");
     
-    static LongIntHashMap eglDisplayCounter;
+    private static class DpyCounter {
+        final long eglDisplay;
+        final Throwable createdStack;
+        int refCount;
+        
+        private DpyCounter(long eglDisplay) {
+            this.eglDisplay = eglDisplay;
+            this.refCount = 0;
+            this.createdStack = DEBUG ? new Throwable() : null;
+        }
+        
+        public String toString() {
+            return "EGLDisplay[0x"+Long.toHexString(eglDisplay)+": refCnt "+refCount+"]";
+        }
+    }
+    static final LongObjectHashMap eglDisplayCounter;
     
     static {
-        eglDisplayCounter = new LongIntHashMap();
-        eglDisplayCounter.setKeyNotFoundValue(0);
+        eglDisplayCounter = new LongObjectHashMap();
+        eglDisplayCounter.setKeyNotFoundValue(null);
     }
 
     /** 
@@ -80,9 +95,13 @@ public class EGLDisplayUtil {
     public static void dumpOpenDisplayConnections() {
         System.err.println("EGLDisplayUtil: Open EGL Display Connections: "+eglDisplayCounter.size());
         int i=0;
-        for(Iterator<LongIntHashMap.Entry> iter = eglDisplayCounter.iterator(); iter.hasNext(); i++) {
-            final LongIntHashMap.Entry e = iter.next();
-            System.err.println("EGLDisplayUtil: Open["+i+"]: 0x"+Long.toHexString(e.key)+": refCnt "+e.value);
+        for(Iterator<LongObjectHashMap.Entry> iter = eglDisplayCounter.iterator(); iter.hasNext(); i++) {
+            final LongObjectHashMap.Entry e = iter.next();
+            final DpyCounter v = (DpyCounter) e.value;
+            System.err.println("EGLDisplayUtil: Open["+i+"]: 0x"+Long.toHexString(e.key)+": "+v);
+            if(null != v.createdStack) {
+                v.createdStack.printStackTrace();
+            }
         }
     }
     
@@ -108,18 +127,32 @@ public class EGLDisplayUtil {
         if( EGL.EGL_NO_DISPLAY == eglDisplay) {
             return false;
         }
-        final boolean res;    
-        final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init
+        final int refCnt;
+        final DpyCounter d;
+        {
+            DpyCounter _d = (DpyCounter) eglDisplayCounter.get(eglDisplay);
+            if(null == _d) {
+                _d = new DpyCounter(eglDisplay);
+                refCnt = 1; // 1st init
+            } else {
+                refCnt = _d.refCount + 1;
+            }
+            d = _d;
+        }
+        final boolean res;
         if(1==refCnt) { // only initialize once
             res = EGL.eglInitialize(eglDisplay, major, minor);
         } else {
             res = true;
-        }        
-        if(res) { // map if successfully initialized, only  
-            eglDisplayCounter.put(eglDisplay, refCnt);
+        }
+        if(res) { // update refCount and map if successfully initialized, only
+            d.refCount = refCnt;
+            if(1 == refCnt) {
+                eglDisplayCounter.put(eglDisplay, d);
+            }
         }
         if(DEBUG) {
-            System.err.println("EGLDisplayUtil.eglInitialize2("+EGLContext.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res);
+            System.err.println("EGLDisplayUtil.eglInitialize("+EGLContext.toHexString(eglDisplay)+" ...): #"+refCnt+", "+d+" = "+res);
             // Thread.dumpStack();
         }
         return res;
@@ -186,13 +219,24 @@ public class EGLDisplayUtil {
             return false;
         }
         final boolean res;    
-        final int refCnt = eglDisplayCounter.get(eglDisplay) - 1; // 1 - 1 = 0 -> final terminate
-        if(0==refCnt) { // no terminate if still in use or already terminated
+        final int refCnt;
+        final DpyCounter d;
+        {
+            DpyCounter _d = (DpyCounter) eglDisplayCounter.get(eglDisplay);
+            if(null == _d) {
+                _d = null;
+                refCnt = -1; // n/a
+            } else {
+                refCnt = _d.refCount - 1; // 1 - 1 = 0 -> final terminate
+            }
+            d = _d;
+        }
+        if( 0 == refCnt ) { // no terminate if still in use or already terminated
             res = EGL.eglTerminate(eglDisplay);
             eglDisplayCounter.remove(eglDisplay);
         } else {
             if(0 < refCnt) { // no negative refCount
-                eglDisplayCounter.put(eglDisplay, refCnt);
+                d.refCount = refCnt;
             } 
             res = true;
         }
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
index 167eebf..2edf261 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
@@ -100,10 +100,10 @@ public abstract class EGLDrawable extends GLDrawableImpl {
     }
 
     @Override
-    protected final void updateHandle() {
+    protected final void createHandle() {
         final EGLWrappedSurface eglws = (EGLWrappedSurface) surface;
         if(DEBUG) {
-            System.err.println(getThreadName() + ": updateHandle of "+eglws);
+            System.err.println(getThreadName() + ": createHandle of "+eglws);
         }        
         if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
             if( EGL.EGL_NO_SURFACE != eglws.getSurfaceHandle() ) {
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index ad305ab..79d1fad 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -67,12 +67,13 @@ import javax.media.opengl.GLProfile;
 
 import jogamp.nativewindow.WrappedSurface;
 import jogamp.opengl.Debug;
+import jogamp.opengl.GLContextImpl;
 import jogamp.opengl.GLDrawableFactoryImpl;
 import jogamp.opengl.GLDrawableImpl;
 import jogamp.opengl.GLDynamicLookupHelper;
 import jogamp.opengl.GLGraphicsConfigurationUtil;
+import jogamp.opengl.SharedResourceRunner;
 
-import com.jogamp.common.JogampRuntimeException;
 import com.jogamp.common.nio.Buffers;
 import com.jogamp.common.nio.PointerBuffer;
 import com.jogamp.common.os.Platform;
@@ -90,9 +91,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
 
     private static final boolean isANGLE(GLDynamicLookupHelper dl) {
         if(Platform.OSType.WINDOWS == Platform.OS_TYPE) {
-            final boolean r = 0 != dl.dynamicLookupFunction("eglQuerySurfacePointerANGLE") ||
-                              0 != dl.dynamicLookupFunction("glBlitFramebufferANGLE") ||
-                              0 != dl.dynamicLookupFunction("glRenderbufferStorageMultisampleANGLE");
+            final boolean r = dl.isFunctionAvailable("eglQuerySurfacePointerANGLE") ||
+                              dl.isFunctionAvailable("glBlitFramebufferANGLE") ||
+                              dl.isFunctionAvailable("glRenderbufferStorageMultisampleANGLE");
             return r;
         } else {
             return false;
@@ -100,9 +101,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
     }
 
     private static final boolean includesES1(GLDynamicLookupHelper dl) {
-        return 0 != dl.dynamicLookupFunction("glLoadIdentity") &&
-               0 != dl.dynamicLookupFunction("glEnableClientState") &&
-               0 != dl.dynamicLookupFunction("glColorPointer");
+        return dl.isFunctionAvailable("glLoadIdentity") &&
+               dl.isFunctionAvailable("glEnableClientState") &&
+               dl.isFunctionAvailable("glColorPointer");
     }
     
     public EGLDrawableFactory() {
@@ -114,9 +115,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
 
         // Check for other underlying stuff ..
         if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true)) {
+            hasX11 = true;
             try {
                 ReflectionUtil.createInstance("jogamp.opengl.x11.glx.X11GLXGraphicsConfigurationFactory", EGLDrawableFactory.class.getClassLoader());
-            } catch (JogampRuntimeException jre) { /* n/a .. */ }
+            } catch (Exception jre) { /* n/a .. */ }
         }
 
         // FIXME: Probably need to move EGL from a static model
@@ -251,8 +253,8 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
                 String key = keyI.next();
                 SharedResource sr = sharedMap.get(key);
                 System.err.println("EGLDrawableFactory.map["+i+"] "+key+" -> "+sr.getDevice()+", "+
-                                   "es1 [avail "+sr.wasES1ContextAvailable()+", pbuffer "+sr.hasES1PBuffer()+", quirks "+sr.getGLRendererQuirksES1()+", ctp "+EGLContext.getGLVersion(1, 0, sr.getCtpES1(), null)+"], "+
-                                   "es2 [avail "+sr.wasES2ContextAvailable()+", pbuffer "+sr.hasES2PBuffer()+", quirks "+sr.getGLRendererQuirksES1()+", ctp "+EGLContext.getGLVersion(2, 0, sr.getCtpES2(), null)+"]");
+                                   "es1 [avail "+sr.wasES1ContextCreated+", pbuffer "+sr.hasPBufferES1+", quirks "+sr.rendererQuirksES1+", ctp "+EGLContext.getGLVersion(1, 0, sr.ctpES1, null)+"], "+
+                                   "es2 [avail "+sr.wasES2ContextCreated+", pbuffer "+sr.hasPBufferES2+", quirks "+sr.rendererQuirksES2+", ctp "+EGLContext.getGLVersion(2, 0, sr.ctpES2, null)+"]");
             }
             ;
         }
@@ -263,8 +265,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
     private EGLGraphicsDevice defaultDevice = null;
     private SharedResource defaultSharedResource = null;
     private boolean isANGLE = false;
+    private boolean hasX11 = false;
 
-    static class SharedResource {
+    static class SharedResource implements SharedResourceRunner.Resource {
       private final EGLGraphicsDevice device;
       // private final EGLContext contextES1;
       // private final EGLContext contextES2;
@@ -292,17 +295,31 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
           this.hasPBufferES1= hasPBufferES1;
           this.hasPBufferES2= hasPBufferES2;
       }
-      final EGLGraphicsDevice getDevice() { return device; }
+      @Override
+      public final boolean isValid() {
+          return wasES1ContextCreated || wasES2ContextCreated;
+      }
+      @Override
+      public final EGLGraphicsDevice getDevice() { return device; }
       // final EGLContext getContextES1() { return contextES1; }
       // final EGLContext getContextES2() { return contextES2; }
-      final GLRendererQuirks getGLRendererQuirksES1() { return rendererQuirksES1; }
-      final GLRendererQuirks getGLRendererQuirksES2() { return rendererQuirksES2; }
-      final int getCtpES1() { return ctpES1; }
-      final int getCtpES2() { return ctpES2; }
-      final boolean wasES1ContextAvailable() { return wasES1ContextCreated; }
-      final boolean wasES2ContextAvailable() { return wasES2ContextCreated; }
-      final boolean hasES1PBuffer() { return hasPBufferES1; }
-      final boolean hasES2PBuffer() { return hasPBufferES2; }
+      
+      @Override
+      public AbstractGraphicsScreen getScreen() {
+          return null;
+      }
+      @Override
+      public GLDrawableImpl getDrawable() {
+          return null;
+      }
+      @Override
+      public GLContextImpl getContext() {
+          return null;
+      }
+      @Override
+      public GLRendererQuirks getRendererQuirks() {
+          return null != rendererQuirksES2 ? rendererQuirksES2 : rendererQuirksES1 ;      
+      }
     }
 
     @Override
@@ -457,7 +474,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
             }
         } catch (Throwable t) {
             if(DEBUG) {
-                System.err.println("Catched Exception:");
+                System.err.println("Catched Exception on thread "+getThreadName()); 
                 t.printStackTrace();
             }
             success = false;
@@ -503,7 +520,8 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
         }        
     }
     
-    /* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) {
+    @Override
+    protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice adevice) {
         if(null == sharedMap) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper
             return null;
         }
@@ -569,6 +587,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
             // avoid exception due to double 'set' - carefull exception of the rule. 
             EGLContext.setAvailableGLVersionsSet(adevice);
         }
+        if( hasX11 ) {
+            handleDontCloseX11DisplayQuirk(rendererQuirksES1[0]);
+            handleDontCloseX11DisplayQuirk(rendererQuirksES2[0]);
+        }
         final SharedResource sr = new SharedResource(defaultDevice, madeCurrentES1, hasPBufferES1[0], rendererQuirksES1[0], ctpES1[0],
                                                                     madeCurrentES2, hasPBufferES2[0], rendererQuirksES2[0], ctpES2[0]);
         
@@ -583,52 +605,19 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
         }
         return sr;
     }
-
-    @Override
-    protected final Thread getSharedResourceThread() {
-        return null;
-    }
-
-    @Override
-    protected final boolean createSharedResource(AbstractGraphicsDevice device) {
-        try {
-            SharedResource sr = getOrCreateEGLSharedResource(device);
-            if(null!=sr) {
-                return sr.wasES1ContextAvailable() || sr.wasES2ContextAvailable();
-            }
-        } catch (GLException gle) {
-            if(DEBUG) {
-                System.err.println("Catched Exception while EGL Shared Resource initialization");
-                gle.printStackTrace();
-            }
-        }
-        return false;
-    }
-
-    @Override
-    protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
-        return null; // FIXME: n/a ..
-    }
     
-    @Override
-    public GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device) {
-        SharedResource sr = getOrCreateEGLSharedResource(device);
-        if(null!=sr) {
-            return null != sr.getGLRendererQuirksES2() ? sr.getGLRendererQuirksES2() : sr.getGLRendererQuirksES1() ; 
+    private void handleDontCloseX11DisplayQuirk(GLRendererQuirks quirks) {
+        if( null != quirks && quirks.exist( GLRendererQuirks.DontCloseX11Display ) ) {
+            jogamp.nativewindow.x11.X11Util.markAllDisplaysUnclosable();
         }
-        return null;
     }
-    
+
     @Override
-    protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
-        SharedResource sr = getOrCreateEGLSharedResource(device);
-        if(null!=sr) {
-            return sr.getDevice();
-        }
+    protected final Thread getSharedResourceThread() {
         return null;
     }
 
-    public boolean isANGLE() {
+    public final boolean isANGLE() {
         return isANGLE;
     }
 
@@ -659,8 +648,6 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
         return new EGLOnscreenDrawable(this, EGLWrappedSurface.get(target));
     }
     
-    static String getThreadName() { return Thread.currentThread().getName(); }
-
     @Override
     protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) {
         if (target == null) {
@@ -770,15 +757,4 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
     protected GLDrawable createExternalGLDrawableImpl() {
         throw new GLException("Not yet implemented");
     }
-
-    @Override
-    public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
-        return false;
-    }
-
-    @Override
-    public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
-        throws GLException {
-        throw new GLException("Unimplemented on this platform");
-    }
 }
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java
index fe9d757..9f4a4d2 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java
@@ -29,6 +29,7 @@
 package jogamp.opengl.egl;
 
 import com.jogamp.common.os.AndroidVersion;
+import com.jogamp.common.os.Platform;
 
 import java.util.*;
 
@@ -41,7 +42,7 @@ import jogamp.opengl.*;
  * Currently two implementations exist, one for ES1 and one for ES2.
  */
 public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
-    static List<String> glueLibNames;
+    static final List<String> glueLibNames;
     static {
         glueLibNames = new ArrayList<String>();
         glueLibNames.add("jogl_mobile");
@@ -52,19 +53,12 @@ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundle
     }
 
     /** 
-     * Might be a desktop GL library, and might need to allow symbol access to subsequent libs.
-     * 
-     * This respects old DRI requirements:<br>
-     * <pre>
-     * http://dri.sourceforge.net/doc/DRIuserguide.html
-     * </pre>
+     * Returns <code>true</code> on <code>Android</code>,
+     * and <code>false</code> otherwise.
      */
     @Override
-    public boolean shallLinkGlobal() { return true; }
-    
-    @Override
-    public boolean shallLookupGlobal() {
-        if ( AndroidVersion.isAvailable ) {
+    public final boolean shallLookupGlobal() {
+        if ( Platform.OSType.ANDROID == Platform.OS_TYPE ) {
             // Android requires global symbol lookup
             return true;
         }
@@ -94,7 +88,7 @@ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundle
         }
     }
     
-    protected List<String> getEGLLibNamesList() {
+    protected final List<String> getEGLLibNamesList() {
         List<String> eglLibNames = new ArrayList<String>();
         
         // this is the default EGL lib name, according to the spec 
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java
index 0a373eb..dd3d6fa 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java
@@ -30,12 +30,12 @@ package jogamp.opengl.egl;
 
 import java.util.*;
 
-public class EGLES1DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
+public final class EGLES1DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
     protected EGLES1DynamicLibraryBundleInfo() {
         super();
     }
 
-    public List<List<String>> getToolLibNames() {
+    public final List<List<String>> getToolLibNames() {
         final List<List<String>> libsList = new ArrayList<List<String>>();
         {
             final List<String> libsGL = new ArrayList<String>();
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java
index d4ee852..d83acdb 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java
@@ -30,12 +30,12 @@ package jogamp.opengl.egl;
 
 import java.util.*;
 
-public class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
+public final class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo {
     protected EGLES2DynamicLibraryBundleInfo() {
         super();
     }
 
-    public List<List<String>> getToolLibNames() {
+    public final List<List<String>> getToolLibNames() {
         final List<List<String>> libsList = new ArrayList<List<String>>();
         {
             final List<String> libsGL = new ArrayList<String>();
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java
index 84bd705..4685e8b 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java
@@ -36,43 +36,20 @@
 package jogamp.opengl.egl;
 
 import javax.media.opengl.*;
+
 import jogamp.opengl.*;
 import javax.media.nativewindow.*;
 
 public class EGLExternalContext extends EGLContext {
-    private GLContext lastContext;
 
     public EGLExternalContext(AbstractGraphicsScreen screen) {
         super(null, null);
         GLContextShareSet.contextCreated(this);
-        setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES);
+        setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES, false);
         getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
     }
 
     @Override
-    public int makeCurrent() throws GLException {
-        // Save last context if necessary to allow external GLContexts to
-        // talk to other GLContexts created by this library
-        GLContext cur = getCurrent();
-        if (cur != null && cur != this) {
-            lastContext = cur;
-            setCurrent(null);
-        }
-        return super.makeCurrent();
-    }
-
-    @Override
-    public void release() throws GLException {
-        super.release();
-        setCurrent(lastContext);
-        lastContext = null;
-    }
-
-    @Override
-    protected void makeCurrentImpl() throws GLException {
-    }
-
-    @Override
     protected void releaseImpl() throws GLException {
     }
 
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
index 71dfe1d..b1ffe60 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
@@ -72,7 +72,14 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
         this.chooser = chooser;
     }
 
-    public static EGLGraphicsConfiguration create(GLCapabilitiesImmutable capsRequested, AbstractGraphicsScreen absScreen, int cfgID) {
+    /**
+     * @param capsRequested
+     * @param absScreen
+     * @param eglConfigID {@link EGL#EGL_CONFIG_ID} for which the config is being created for.
+     * @return
+     * @throws GLException if invalid EGL display. 
+     */
+    public static EGLGraphicsConfiguration create(GLCapabilitiesImmutable capsRequested, AbstractGraphicsScreen absScreen, int eglConfigID) {
         final AbstractGraphicsDevice absDevice = absScreen.getDevice();
         if(null==absDevice || !(absDevice instanceof EGLGraphicsDevice)) {
             throw new GLException("GraphicsDevice must be a valid EGLGraphicsDevice");
@@ -81,7 +88,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
         if (dpy == EGL.EGL_NO_DISPLAY) {
             throw new GLException("Invalid EGL display: "+absDevice);
         }
-        final long cfg = EGLConfigId2EGLConfig(dpy, cfgID);
+        final long cfg = EGLConfigId2EGLConfig(dpy, eglConfigID);
         if(0 < cfg) {
             final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsRequested);
             final EGLGLCapabilities caps = EGLConfig2Capabilities((EGLGraphicsDevice)absDevice, capsRequested.getGLProfile(), cfg, winattrmask, false);
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
index f638ef8..b44e085 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
@@ -181,7 +181,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
     }
 
     protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(EGLDrawableFactory factory, AbstractGraphicsDevice device) {
-        EGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateEGLSharedResource(device);
+        EGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
         if(null == sharedResource) {
             throw new GLException("Shared resource for device n/a: "+device);
         }
@@ -411,8 +411,13 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
         if( VisualIDHolder.VID_UNDEFINED != nativeVisualID ) {
             List<GLCapabilitiesImmutable> removedCaps = new ArrayList<GLCapabilitiesImmutable>();
             for(int i=0; i<availableCaps.size(); ) {
-                VisualIDHolder vidh = (VisualIDHolder) availableCaps.get(i);
-                if(vidh.getVisualID(VIDType.NATIVE) != nativeVisualID) {
+                final GLCapabilitiesImmutable aCap = availableCaps.get(i);
+                if(aCap.getVisualID(VIDType.NATIVE) != nativeVisualID) {
+                    if(DEBUG) { System.err.println("Remove["+i+"] (mismatch VisualID): "+aCap); }
+                    removedCaps.add(availableCaps.remove(i));
+                } if( 0 == aCap.getDepthBits() && 0 < capsChosen.getDepthBits() ) {
+                    // Hack for HiSilicon/Vivante/Immersion.16 Renderer ..
+                    if(DEBUG) { System.err.println("Remove["+i+"] (mismatch depth-bits): "+aCap); }
                     removedCaps.add(availableCaps.remove(i));
                 } else {
                     i++;
@@ -425,6 +430,9 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
                 }
             } else if(DEBUG) {
                 System.err.println("EGLGraphicsConfiguration.eglChooseConfig: post filter nativeVisualID "+toHexString(nativeVisualID)+" got configs: "+availableCaps.size());
+                for(int i=0; i<availableCaps.size(); i++) {
+                    System.err.println(i+": "+availableCaps.get(i));
+                }
             }
         }
 
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java
deleted file mode 100644
index 325ad61..0000000
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.egl;
-
-import javax.media.opengl.*;
-
-public class EGLOnscreenContext extends EGLContext {
-    public EGLOnscreenContext(EGLOnscreenDrawable drawable, GLContext shareWith) {
-        super(drawable, shareWith);
-    }
-}
-
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
index 6440cf1..19084ba 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
@@ -50,7 +50,7 @@ public class EGLOnscreenDrawable extends EGLDrawable {
 
     @Override
     public GLContext createContext(GLContext shareWith) {
-        return new EGLOnscreenContext(this, shareWith);
+        return new EGLContext(this, shareWith);
     }
 
     @Override
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java
deleted file mode 100644
index bb9eeb8..0000000
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.egl;
-
-import javax.media.opengl.*;
-
-public class EGLPbufferContext extends EGLContext {
-    public EGLPbufferContext(EGLPbufferDrawable drawable, GLContext shareWith) {
-        super(drawable, shareWith);
-    }
-
-    @Override
-    public int getFloatingPointMode() {
-        return 0; // FIXME ??
-    }
-}
-
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
index eb7e320..45e39f5 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
@@ -41,7 +41,6 @@
 package jogamp.opengl.egl;
 
 import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.MutableSurface;
 import javax.media.opengl.GLContext;
 
 public class EGLPbufferDrawable extends EGLDrawable {
@@ -58,7 +57,7 @@ public class EGLPbufferDrawable extends EGLDrawable {
 
     @Override
     public GLContext createContext(GLContext shareWith) {
-        return new EGLPbufferContext(this, shareWith);
+        return new EGLContext(this, shareWith);
     }
 }
 
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
index 342c4c4..8dea10d 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
@@ -13,6 +13,13 @@ import javax.media.opengl.GLException;
 
 import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
 
+/**
+ * <pre>
+ * EGLWrappedSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a
+ *     EGLUpstreamSurfaceHook [ is_a -> UpstreamSurfaceHook.MutableSize -> UpstreamSurfaceHook ] has_a
+ *        NativeSurface (i.e. native X11 surface)
+ * </pre>
+ */
 public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
     protected static final boolean DEBUG = EGLDrawableFactory.DEBUG;
     private final NativeSurface upstreamSurface;
@@ -47,7 +54,7 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
     public final void create(ProxySurface surface) {
         final String dbgPrefix;
         if(DEBUG) {
-            dbgPrefix = getThreadName() + ": EGLUpstreamSurfaceHook.create("+surface.getClass().getSimpleName()+"): "; 
+            dbgPrefix = getThreadName() + ": EGLUpstreamSurfaceHook.create( up "+upstreamSurface.getClass().getSimpleName()+" -> this "+surface.getClass().getSimpleName()+" ): ";
             System.err.println(dbgPrefix+this);            
         } else {
             dbgPrefix = null;
@@ -76,24 +83,51 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
         
         boolean isEGLSurfaceValid = true; // assume yes
         
-        final AbstractGraphicsConfiguration aConfig = upstreamSurface.getGraphicsConfiguration();        
-        final AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice();
-        
         final EGLGraphicsDevice eglDevice;
-        if( aDevice instanceof EGLGraphicsDevice ) {
-            eglDevice = (EGLGraphicsDevice) aDevice;
+        final AbstractGraphicsConfiguration aConfig;
+        {
+            final AbstractGraphicsConfiguration surfaceConfig = surface.getGraphicsConfiguration();
+            final AbstractGraphicsDevice surfaceDevice = null != surfaceConfig ? surfaceConfig.getScreen().getDevice() : null;
+            if(DEBUG) {
+                System.err.println(dbgPrefix+"SurfaceDevice: "+surfaceDevice.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(surfaceDevice.hashCode())+", "+surfaceDevice);
+                System.err.println(dbgPrefix+"SurfaceConfig: "+surfaceConfig.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(surfaceConfig.hashCode())+", "+surfaceConfig);
+            }
+    
+            final AbstractGraphicsConfiguration upstreamConfig = upstreamSurface.getGraphicsConfiguration();        
+            final AbstractGraphicsDevice upstreamDevice = upstreamConfig.getScreen().getDevice();
             if(DEBUG) {
-                System.err.println(dbgPrefix+"Reusing eglDevice: "+eglDevice);
+                System.err.println(dbgPrefix+"UpstreamDevice: "+upstreamDevice.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(upstreamDevice.hashCode())+", "+upstreamDevice);
+                System.err.println(dbgPrefix+"UpstreamConfig: "+upstreamConfig.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(upstreamConfig.hashCode())+", "+upstreamConfig);
             }
-            if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
-                eglDevice.open();
+            
+            if( surfaceDevice instanceof EGLGraphicsDevice ) {
+                eglDevice = (EGLGraphicsDevice) surfaceDevice;
+                aConfig = surfaceConfig;
+                if(DEBUG) {
+                    System.err.println(dbgPrefix+"Reusing this eglDevice: "+eglDevice+", using this config "+aConfig.getClass().getSimpleName()+" "+aConfig);
+                }
+                if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
+                    eglDevice.open();
+                    isEGLSurfaceValid = false;
+                    surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+                }
+            } else if( upstreamDevice instanceof EGLGraphicsDevice ) {
+                eglDevice = (EGLGraphicsDevice) upstreamDevice;
+                aConfig = upstreamConfig;
+                if(DEBUG) {
+                    System.err.println(dbgPrefix+"Reusing upstream eglDevice: "+eglDevice+", using upstream config "+aConfig.getClass().getSimpleName()+" "+aConfig);
+                }
+                if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
+                    eglDevice.open();
+                    isEGLSurfaceValid = false;
+                    surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+                }
+            } else {
+                eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface);
+                aConfig = upstreamConfig;
                 isEGLSurfaceValid = false;
                 surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
             }
-        } else {
-            eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface);
-            isEGLSurfaceValid = false;
-            surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );                
         }
         
         final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java
index b363033..f816151 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java
@@ -4,6 +4,13 @@ import javax.media.nativewindow.NativeSurface;
 
 import jogamp.nativewindow.WrappedSurface;
 
+/**
+ * <pre>
+ * EGLWrappedSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a
+ *     EGLUpstreamSurfaceHook [ is_a -> UpstreamSurfaceHook.MutableSize -> UpstreamSurfaceHook ] has_a
+ *        NativeSurface (i.e. native X11 surface)
+ * </pre>
+ */
 public class EGLWrappedSurface extends WrappedSurface {
 
     public static EGLWrappedSurface get(NativeSurface surface) {
@@ -20,6 +27,7 @@ public class EGLWrappedSurface extends WrappedSurface {
         }
     }
 
+    @Override
     public final NativeSurface getUpstreamSurface() { 
         return ((EGLUpstreamSurfaceHook)super.getUpstreamSurfaceHook()).getUpstreamSurface(); 
     }    
diff --git a/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java b/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java
index 62ff3aa..7cd7da5 100644
--- a/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java
+++ b/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java
@@ -120,6 +120,7 @@ import javax.media.opengl.glu.GLU;
 import javax.media.opengl.glu.GLUquadric;
 
 import com.jogamp.opengl.util.ImmModeSink;
+import com.jogamp.opengl.util.glsl.ShaderState;
 
 /**
  * GLUquadricImpl.java
@@ -140,22 +141,26 @@ public class GLUquadricImpl implements GLUquadric {
   private boolean immModeSinkImmediate;
   public int normalType;
   public GL gl;
+  public ShaderState shaderState;
+  public int shaderProgram;
 
   public static final boolean USE_NORM = true;
   public static final boolean USE_TEXT = false;
 
   private ImmModeSink immModeSink=null;
 
-  public GLUquadricImpl(GL gl, boolean useGLSL) {
+  public GLUquadricImpl(GL gl, boolean useGLSL, ShaderState st, int shaderProgram) {
     this.gl=gl;
     this.useGLSL = useGLSL;
-    drawStyle = GLU.GLU_FILL;
-    orientation = GLU.GLU_OUTSIDE;
-    textureFlag = false;
-    normals = GLU.GLU_SMOOTH;
-    normalType = gl.isGLES1()?GL.GL_BYTE:GL.GL_FLOAT;
-    immModeSinkImmediate=true;
-    immModeSinkEnabled=!gl.isGL2();
+    this.drawStyle = GLU.GLU_FILL;
+    this.orientation = GLU.GLU_OUTSIDE;
+    this.textureFlag = false;
+    this.normals = GLU.GLU_SMOOTH;
+    this.normalType = gl.isGLES1()?GL.GL_BYTE:GL.GL_FLOAT;
+    this.immModeSinkImmediate=true;
+    this.immModeSinkEnabled=!gl.isGL2();
+    this.shaderState = st;
+    this.shaderProgram = shaderProgram;
     replaceImmModeSink();
   }
 
@@ -191,12 +196,21 @@ public class GLUquadricImpl implements GLUquadric {
 
     ImmModeSink res = immModeSink;
     if(useGLSL) {
-        immModeSink = ImmModeSink.createGLSL (32, 
-                                              3, GL.GL_FLOAT,             // vertex 
-                                              0, GL.GL_FLOAT,             // color
-                                              USE_NORM?3:0, normalType,   // normal
-                                              USE_TEXT?2:0, GL.GL_FLOAT,  // texCoords
-                                              GL.GL_STATIC_DRAW);
+        if(null != shaderState) {
+            immModeSink = ImmModeSink.createGLSL (32, 
+                                                  3, GL.GL_FLOAT,             // vertex 
+                                                  0, GL.GL_FLOAT,             // color
+                                                  USE_NORM?3:0, normalType,   // normal
+                                                  USE_TEXT?2:0, GL.GL_FLOAT,  // texCoords
+                                                  GL.GL_STATIC_DRAW, shaderState);
+        } else {
+            immModeSink = ImmModeSink.createGLSL (32, 
+                                                  3, GL.GL_FLOAT,             // vertex 
+                                                  0, GL.GL_FLOAT,             // color
+                                                  USE_NORM?3:0, normalType,   // normal
+                                                  USE_TEXT?2:0, GL.GL_FLOAT,  // texCoords
+                                                  GL.GL_STATIC_DRAW, shaderProgram);            
+        }
     } else {
         immModeSink = ImmModeSink.createFixed(32,
                                               3, GL.GL_FLOAT,             // vertex
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index 360b745..6b086ce 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -71,22 +71,24 @@ import com.jogamp.common.nio.Buffers;
 import com.jogamp.common.nio.PointerBuffer;
 import com.jogamp.common.os.Platform;
 import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.locks.RecursiveLock;
 import com.jogamp.gluegen.runtime.ProcAddressTable;
 import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
 import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
 import com.jogamp.opengl.util.PMVMatrix;
 import com.jogamp.opengl.util.glsl.ShaderCode;
 import com.jogamp.opengl.util.glsl.ShaderProgram;
 
-public abstract class MacOSXCGLContext extends GLContextImpl
-{
+public class MacOSXCGLContext extends GLContextImpl
+{  
   // Abstract interface for implementation of this context (either
   // NSOpenGL-based or CGL-based)
   protected interface GLBackendImpl {
         boolean isNSContext();
         long create(long share, int ctp, int major, int minor);
         boolean destroy(long ctx);
-        boolean contextRealized(boolean realized);
+        void associateDrawable(boolean bound);
         boolean copyImpl(long src, int mask);
         boolean makeCurrent(long ctx);
         boolean release(long ctx);
@@ -147,8 +149,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl
                                               "../../shader", "../../shader/bin", shaderBasename, true);
       final ShaderCode fp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MacOSXCGLContext.class, 
                                               "../../shader", "../../shader/bin", shaderBasename, true);
-      vp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
-      fp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+      vp.defaultShaderCustomization(gl, true, true);
+      fp.defaultShaderCustomization(gl, true, true);
       sp.add(vp);
       sp.add(fp);
       if(!sp.link(gl, System.err)) {
@@ -163,7 +165,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
       pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
       pmvMatrix.glLoadIdentity();       
       final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
-      pmvMatrixUniform.setLocation( gl.glGetUniformLocation( sp.program(), pmvMatrixUniform.getName() ) );
+      pmvMatrixUniform.setLocation(gl, sp.program());
       gl.glUniform(pmvMatrixUniform);
 
       sp.useProgram(gl, false);
@@ -182,6 +184,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
   // CGL extension functions.
   private CGLExtProcAddressTable cglExtProcAddressTable;
 
+  private long updateHandle = 0;
+  private int lastWidth, lastHeight;
+  
   protected MacOSXCGLContext(GLDrawableImpl drawable,
                    GLContext shareWith) {
     super(drawable, shareWith);
@@ -278,9 +283,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
 
     MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
     GLCapabilitiesImmutable capabilitiesChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
-    if (capabilitiesChosen.getPbufferFloatingPointBuffers() && !isTigerOrLater) {
-       throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later");
-    }
     GLProfile glp = capabilitiesChosen.getGLProfile();
     if(glp.isGLES1() || glp.isGLES2() || glp.isGL4() || glp.isGL3() && !isLionOrLater) {
         throw new GLException("OpenGL profile not supported on MacOSX "+Platform.getOSVersionNumber()+": "+glp);
@@ -309,6 +311,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
     if (!impl.makeCurrent(contextHandle)) {
       throw new GLException("Error making Context current: "+this);
     }
+    drawableUpdatedNotify();
   }
 
   @Override
@@ -320,23 +323,75 @@ public abstract class MacOSXCGLContext extends GLContextImpl
 
   @Override
   protected void destroyImpl() throws GLException {
+    releaseUpdateHandle();
     if(!impl.destroy(contextHandle)) {
         throw new GLException("Error destroying OpenGL Context: "+this);
     }
   }
   
+  private final long getUpdateHandle() {
+    if( 0 == updateHandle ) {
+        lastWidth = -1;
+        lastHeight = -1;
+        if( isCreated() && drawable.getChosenGLCapabilities().isOnscreen() && isNSContext() ) {
+            final boolean incompleteView;
+            final NativeSurface surface = drawable.getNativeSurface();
+            if( surface instanceof ProxySurface ) {
+              incompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
+            } else {
+              incompleteView = false;
+            }
+            if(!incompleteView) {        
+                updateHandle = CGL.updateContextRegister(contextHandle, drawable.getHandle());
+                if(0 == updateHandle) {
+                    throw new InternalError("XXX2");
+                }
+            }
+        }
+    }
+    return updateHandle;
+  }
+  
+  private final void releaseUpdateHandle() {
+    if ( 0 != updateHandle ) {
+        CGL.updateContextUnregister(updateHandle);
+        updateHandle = 0;
+    }      
+  }
+  
+  @Override
+  protected void drawableUpdatedNotify() throws GLException {
+    if( drawable.getChosenGLCapabilities().isOnscreen() ) {
+        final long _updateHandle = getUpdateHandle();
+        final int w = drawable.getWidth();
+        final int h = drawable.getHeight();
+        final boolean updateContext = ( 0!=_updateHandle && CGL.updateContextNeedsUpdate(_updateHandle) ) ||
+                                      w != lastWidth || h != lastHeight;
+        if(updateContext) {
+            lastWidth = w;
+            lastHeight = h;
+            if (contextHandle == 0) {
+              throw new GLException("Context not created");
+            }
+            CGL.updateContext(contextHandle);
+        }
+    }
+  }
+  
   @Override
-  protected void contextRealized(boolean realized) {
+  protected void associateDrawable(boolean bound) {
       // context stuff depends on drawable stuff
-      if(realized) {
-          super.contextRealized(true);   // 1) init drawable stuff
-          impl.contextRealized(true);    // 2) init context stuff
+      if(bound) {
+          super.associateDrawable(true);   // 1) init drawable stuff
+          impl.associateDrawable(true);    // 2) init context stuff
+          getUpdateHandle();
       } else {
-          impl.contextRealized(false);   // 1) free context stuff
-          super.contextRealized(false);  // 2) free drawable stuff
+          releaseUpdateHandle();
+          impl.associateDrawable(false);   // 1) free context stuff
+          super.associateDrawable(false);  // 2) free drawable stuff
       }
   }
-
+  
   /* pp */ void detachPBuffer() {
       impl.detachPBuffer();
   }
@@ -413,20 +468,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
     return super.isExtensionAvailable(glExtensionName);
   }
 
-  @Override
-  public int getOffscreenContextPixelDataType() {
-    throw new GLException("Should not call this");
-  }
-
-  public int getOffscreenContextReadBuffer() {
-    throw new GLException("Should not call this");
-  }
-
-  @Override
-  public boolean offscreenImageNeedsVerticalFlip() {
-    throw new GLException("Should not call this");
-  }
-
   // Support for "mode switching" as described in MacOSXCGLDrawable
   public void setOpenGLMode(GLBackendType mode) {
       if (mode == openGLMode) {
@@ -474,10 +515,12 @@ public abstract class MacOSXCGLContext extends GLContextImpl
   // NSOpenGLContext-based implementation
   class NSOpenGLImpl implements GLBackendImpl {
       private OffscreenLayerSurface backingLayerHost = null;
-      private long nsOpenGLLayer = 0;
-      private long nsOpenGLLayerPFmt = 0;
-      private float screenVSyncTimeout; // microSec
-      private int vsyncTimeout;    // microSec - for nsOpenGLLayer mode
+      /** lifecycle:  [create - destroy] */
+      private long pixelFormat = 0;
+      /** microSec - defaults to 1/60s */
+      private int screenVSyncTimeout = 16666;
+      /** microSec - for nsOpenGLLayer mode - defaults to 1/60s + 1ms */
+      private volatile int vsyncTimeout = 16666 + 1000;
       private int lastWidth=0, lastHeight=0; // allowing to detect size change
       private boolean needsSetContextPBuffer = false;
       private ShaderProgram gl3ShaderProgram = null;
@@ -485,78 +528,98 @@ public abstract class MacOSXCGLContext extends GLContextImpl
       @Override
       public boolean isNSContext() { return true; }
 
-      @Override
-      public long create(long share, int ctp, int major, int minor) {
-          long ctx = 0;
-          final NativeSurface surface = drawable.getNativeSurface();        
-          final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration();
-          final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+      
+      /** Only returns a valid NSView. If !NSView, return null and mark either pbuffer and FBO. */
+      private long getNSViewHandle(boolean[] isPBuffer, boolean[] isFBO) {
           final long nsViewHandle;
-          final boolean isPBuffer;
-          final boolean isFBO;
           if(drawable instanceof GLFBODrawableImpl) {
               nsViewHandle = 0;
-              isPBuffer = false;
-              isFBO = true;
-              if(DEBUG) {
-                  System.err.println("NS create GLFBODrawableImpl drawable: isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
-              }
-          } else if(drawable instanceof MacOSXCGLDrawable) {
-              // we allow null here! (special pbuffer case)
-              nsViewHandle = ((MacOSXCGLDrawable)MacOSXCGLContext.this.drawable).getNSViewHandle();
-              isPBuffer = CGL.isNSOpenGLPixelBuffer(drawable.getHandle());
-              isFBO = false;
+              isPBuffer[0] = false;
+              isFBO[0] = true;
               if(DEBUG) {
-                  System.err.println("NS create MacOSXCGLDrawable drawable handle isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
+                  System.err.println("NS viewHandle.1: GLFBODrawableImpl drawable: isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
               }
           } else {
-              // we only allow a valid NSView here
               final long drawableHandle = drawable.getHandle();
               final boolean isNSView = OSXUtil.isNSView(drawableHandle);
               final boolean isNSWindow = OSXUtil.isNSWindow(drawableHandle);
-              isPBuffer = CGL.isNSOpenGLPixelBuffer(drawableHandle);
-              isFBO = false;
+              isPBuffer[0] = CGL.isNSOpenGLPixelBuffer(drawableHandle);
+              isFBO[0] = false;
 
-              if(DEBUG) {
-                  System.err.println("NS create Anonymous drawable handle "+toHexString(drawableHandle)+": isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
-              }
               if( isNSView ) {
                   nsViewHandle = drawableHandle;
               } else if( isNSWindow ) {
                   nsViewHandle = OSXUtil.GetNSView(drawableHandle);
-              } else if( isPBuffer ) {
+              } else if( isPBuffer[0] ) {
                   nsViewHandle = 0;
               } else {
-                  throw new RuntimeException("Anonymous drawable instance's handle neither NSView, NSWindow nor PBuffer: "+toHexString(drawableHandle)+", "+drawable.getClass().getName()+",\n\t"+drawable);
+                  throw new RuntimeException("Drawable's handle neither NSView, NSWindow nor PBuffer: drawableHandle "+toHexString(drawableHandle)+", isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO[0]+", isPBuffer "+isPBuffer[0]+", "+drawable.getClass().getName()+",\n\t"+drawable);
+              }
+              if(DEBUG) {
+                  System.err.println("NS viewHandle.2: drawableHandle "+toHexString(drawableHandle)+" -> nsViewHandle "+toHexString(nsViewHandle)+": isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO[0]+", isPBuffer "+isPBuffer[0]+", "+drawable.getClass().getName()+",\n\t"+drawable);
               }
           }
-          needsSetContextPBuffer = isPBuffer;
-          backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
+          needsSetContextPBuffer = isPBuffer[0];
+          return nsViewHandle;
+      }
+      
+      @Override
+      public long create(long share, int ctp, int major, int minor) {
+          long ctx = 0;
+          final NativeSurface surface = drawable.getNativeSurface();        
+          final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration();
+          final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+          final long nsViewHandle;
+          final boolean isPBuffer;
+          final boolean isFBO;
+          {
+              boolean[] _isPBuffer = { false };
+              boolean[] _isFBO = { false };
+              nsViewHandle = getNSViewHandle(_isPBuffer, _isFBO);
+              isPBuffer = _isPBuffer[0];
+              isFBO = _isFBO[0];
+          }
+          final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
 
           boolean incompleteView = null != backingLayerHost;
           if( !incompleteView && surface instanceof ProxySurface ) {
               incompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
           }
-          long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps, ctp, major, minor);
+          {
+              final GLCapabilitiesImmutable targetCaps;
+              if( isFBO ) {
+                  // Use minimum GLCapabilities for the target surface w/ same profile
+                  targetCaps = new GLCapabilities( chosenCaps.getGLProfile() );
+              } else {
+                  targetCaps = chosenCaps;
+              }
+              pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(targetCaps, ctp, major, minor);
+          }
           if (pixelFormat == 0) {
               if(DEBUG) {
                   System.err.println("Unable to allocate pixel format with requested GLCapabilities: "+chosenCaps);
               }
               return 0;
           }
-          GLCapabilities fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat);
-          if( !fixedCaps.isPBuffer() && isPBuffer ) {
-              throw new InternalError("handle is PBuffer, fixedCaps not: "+drawable);
+          final GLCapabilitiesImmutable fixedCaps;
+          if( isFBO ) {
+              // pixelformat of target doesn't affect caps w/ FBO
+              fixedCaps = chosenCaps;
+          } else {
+              final GLCapabilities _fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat);
+              if( !_fixedCaps.isPBuffer() && isPBuffer ) {
+                  throw new InternalError("handle is PBuffer, fixedCaps not: "+drawable);
+              }
+              // determine on-/offscreen caps, since pformat is ambiguous 
+              _fixedCaps.setPBuffer( isPBuffer ); // exclusive
+              _fixedCaps.setBitmap( false );      // n/a in our OSX impl.
+              _fixedCaps.setOnscreen( !isFBO && !isPBuffer );
+              fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(_fixedCaps, chosenCaps.isBackgroundOpaque());
           }
-          { // determine on-/offscreen caps, since pformat is ambiguous 
-              fixedCaps.setFBO( isFBO );         // exclusive 
-              fixedCaps.setPBuffer( isPBuffer ); // exclusive
-              fixedCaps.setBitmap( false );      // n/a in our OSX impl.
-              fixedCaps.setOnscreen( !isFBO && !isPBuffer );
+          final int sRefreshRate = OSXUtil.GetScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex());
+          if( 0 < sRefreshRate ) {
+              screenVSyncTimeout = 1000000 / sRefreshRate;
           }
-          fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque());
-          int sRefreshRate = OSXUtil.GetScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex());
-          screenVSyncTimeout = 1000000f / sRefreshRate;
           if(DEBUG) {
               System.err.println("NS create OSX>=lion "+isLionOrLater);
               System.err.println("NS create incompleteView: "+incompleteView);
@@ -573,61 +636,191 @@ public abstract class MacOSXCGLContext extends GLContextImpl
               // Thread.dumpStack();
           }
           config.setChosenCapabilities(fixedCaps);
-          /**
-          if(null != backingLayerHost) {
-              backingLayerHost.setChosenCapabilities(fixedCaps);
-          }  */                  
           
-          try {
-              final IntBuffer viewNotReady = Buffers.newDirectIntBuffer(1);
-              // Try to allocate a context with this
-              ctx = CGL.createContext(share,
-                      nsViewHandle, incompleteView,
-                      pixelFormat,
-                      chosenCaps.isBackgroundOpaque(),
-                      viewNotReady);
-              if (0 == ctx) {
-                  if(DEBUG) {
-                      System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady.get(0)));
-                  }
-                  return 0;
+          final IntBuffer viewNotReady = Buffers.newDirectIntBuffer(1);
+          // Try to allocate a context with this
+          ctx = CGL.createContext(share, nsViewHandle, incompleteView,
+                  pixelFormat, chosenCaps.isBackgroundOpaque(), viewNotReady);
+          if (0 == ctx) {
+              if(DEBUG) {
+                  System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady.get(0)));
               }
+              return 0;
+          }
 
-              if(null != backingLayerHost) {
-                  nsOpenGLLayerPFmt = pixelFormat;
-                  pixelFormat = 0;
-              }
-              
-              if (chosenCaps.isOnscreen() && !chosenCaps.isBackgroundOpaque()) {
-                  // Set the context opacity
-                  CGL.setContextOpacity(ctx, 0);
-              }
-          } finally {
-              if(0!=pixelFormat) {
-                  CGL.deletePixelFormat(pixelFormat);
-                  pixelFormat = 0;
-              }
+          if (chosenCaps.isOnscreen() && !chosenCaps.isBackgroundOpaque()) {
+              // Set the context opacity
+              CGL.setContextOpacity(ctx, 0);
           }
           return ctx;
       }
 
       @Override
       public boolean destroy(long ctx) {
+          if(0!=pixelFormat) {
+              CGL.deletePixelFormat(pixelFormat);
+              pixelFormat = 0;
+          }
           return CGL.deleteContext(ctx, true);
       }
 
+      /**
+       * NSOpenGLLayer creation and it's attachment is performed on the main-thread w/o [infinite] blocking.
+       * <p>
+       * Since NSOpenGLLayer creation requires this context for it's shared context creation,
+       * this method attempts to acquire the surface and context lock with {@link #screenVSyncTimeout}/2 maximum wait time.
+       * If the surface and context lock could not be acquired, this runnable is being re-queued for later execution. 
+       * </p>
+       * <p>
+       * Hence this method blocks the main-thread only for a short period of time.
+       * </p>
+       */                  
+      class AttachGLLayerCmd implements Runnable {
+          final OffscreenLayerSurface ols;
+          final long ctx;
+          final int shaderProgram;
+          final long pfmt;
+          final long pbuffer;
+          final int texID;
+          final boolean isOpaque;
+          final int width;
+          final int height;
+          /** Synchronized by instance's monitor */
+          long nsOpenGLLayer;
+          /** Synchronized by instance's monitor */
+          boolean valid;
+          
+          AttachGLLayerCmd(OffscreenLayerSurface ols, long ctx, int shaderProgram, long pfmt, long pbuffer, int texID, boolean isOpaque, int width, int height) {
+              this.ols = ols;
+              this.ctx = ctx;
+              this.shaderProgram = shaderProgram;
+              this.pfmt = pfmt;
+              this.pbuffer = pbuffer;
+              this.texID = texID;
+              this.isOpaque = isOpaque;
+              this.width = width;
+              this.height = height;
+              this.valid = false;
+              this.nsOpenGLLayer = 0;
+          }
+          
+          public final String contentToString() {
+              return "valid "+valid+", size "+width+"x"+height+", ctx "+toHexString(ctx)+", opaque "+isOpaque+", texID "+texID+", pbuffer "+toHexString(pbuffer)+", nsOpenGLLayer "+toHexString(nsOpenGLLayer);
+          }
+          
+          @Override
+          public final String toString() {
+              return "AttachGLLayerCmd["+contentToString()+"]";
+          }
+          
+          @Override
+          public void run() {
+              synchronized(this) {
+                  if( !valid ) {
+                      try {
+                          final int maxwait = screenVSyncTimeout/2000; // TO 1/2 of current screen-vsync in [ms]
+                          final RecursiveLock surfaceLock = ols.getLock(); 
+                          if( surfaceLock.tryLock( maxwait ) ) {
+                              try {
+                                  if( MacOSXCGLContext.this.lock.tryLock( maxwait ) ) {
+                                      try {
+                                          nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, shaderProgram, pfmt, pbuffer, texID, isOpaque, width, height);
+                                          ols.attachSurfaceLayer(nsOpenGLLayer);
+                                          final int currentInterval = MacOSXCGLContext.this.getSwapInterval();
+                                          final int interval = 0 <= currentInterval ? currentInterval : 1;
+                                          setSwapIntervalImpl(nsOpenGLLayer, interval); // enabled per default in layered surface
+                                          valid = true;
+                                          if (DEBUG) {
+                                              System.err.println("NSOpenGLLayer.Attach: OK, layer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(pbuffer)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", drawableHandle "+toHexString(drawable.getHandle())+" - "+getThreadName());
+                                          }
+                                      } finally {
+                                          MacOSXCGLContext.this.lock.unlock();
+                                      }
+                                  }
+                              } finally {
+                                  surfaceLock.unlock();
+                              }
+                          }
+                      } catch (InterruptedException e) {
+                          e.printStackTrace();
+                      }
+                      if( !valid ) {
+                          // could not acquire lock, re-queue
+                          if (DEBUG) {
+                              System.err.println("NSOpenGLLayer.Attach: Re-Queue, drawableHandle "+toHexString(drawable.getHandle())+" - "+getThreadName());
+                          }
+                          OSXUtil.RunLater(this, 1);
+                      }
+                  }
+              }
+          }
+      }
+      AttachGLLayerCmd attachGLLayerCmd = null;
+      
+      class DetachGLLayerCmd implements Runnable {
+        final AttachGLLayerCmd cmd;
+        
+        DetachGLLayerCmd(AttachGLLayerCmd cmd) {
+            this.cmd = cmd;
+        }
+        
+        @Override
+        public final String toString() {
+            return "DetachGLLayerCmd["+cmd.contentToString()+"]";
+        }
+        
+        @Override
+        public void run() {
+            synchronized( cmd ) {
+                if( cmd.valid ) {
+                    // still having a valid OLS attached to surface (parent OLS could have been removed)
+                    try {
+                        final OffscreenLayerSurface ols = cmd.ols;
+                        final long l = ols.getAttachedSurfaceLayer();
+                        if( 0 != l ) {
+                            ols.detachSurfaceLayer();
+                        }
+                    } catch(Throwable t) {
+                        System.err.println("Catched Exception on thread "+getThreadName()); 
+                        t.printStackTrace();
+                    }
+                    CGL.releaseNSOpenGLLayer(cmd.nsOpenGLLayer);
+                    if(DEBUG) {
+                        System.err.println("NSOpenGLLayer.Detach: OK, layer "+toHexString(cmd.nsOpenGLLayer)+" - "+getThreadName());
+                    }
+                    cmd.nsOpenGLLayer = 0;
+                    cmd.valid = false;
+                } else if(DEBUG) {
+                    System.err.println("NSOpenGLLayer.Detach: Skipped "+toHexString(cmd.nsOpenGLLayer)+" - "+getThreadName());
+                }
+            }
+        }          
+      }
+      
       @Override
-      public boolean contextRealized(boolean realized) {
-          if( realized ) {
+      public void associateDrawable(boolean bound) {
+          backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(drawable.getNativeSurface(), true);
+          
+          if(DEBUG) {
+              System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable: "+bound+", ctx "+toHexString(contextHandle)+
+                                 ", hasBackingLayerHost "+(null!=backingLayerHost)+", attachGLLayerCmd "+attachGLLayerCmd);
+              // Thread.dumpStack();
+          }          
+          
+          if( bound ) {              
               if( null != backingLayerHost ) {
+                  final GLCapabilitiesImmutable chosenCaps;
+                  final long ctx;
+                  final int texID;
+                  final long pbufferHandle;
+                  final int gl3ShaderProgramName;
+                  
                   //
                   // handled layered surface
                   //
-                  final GLCapabilitiesImmutable chosenCaps = drawable.getChosenGLCapabilities();
-                  final long ctx = MacOSXCGLContext.this.getHandle();
-                  final int texID;
+                  chosenCaps = drawable.getChosenGLCapabilities();
+                  ctx = MacOSXCGLContext.this.getHandle();
                   final long drawableHandle = drawable.getHandle();
-                  final long pbufferHandle;
                   if(drawable instanceof GLFBODrawableImpl) {
                       final GLFBODrawableImpl fbod = (GLFBODrawableImpl)drawable;
                       texID = fbod.getTextureBuffer(GL.GL_FRONT).getName();
@@ -651,7 +844,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
                   if(0>=lastWidth || 0>=lastHeight || !drawable.isRealized()) {
                       throw new GLException("Drawable not realized yet or invalid texture size, texSize "+lastWidth+"x"+lastHeight+", "+drawable);
                   }
-                  final int gl3ShaderProgramName;
                   if( MacOSXCGLContext.this.isGL3core() ) {
                       if( null == gl3ShaderProgram) {
                           gl3ShaderProgram = createCALayerShader(MacOSXCGLContext.this.gl.getGL3());
@@ -659,42 +851,53 @@ public abstract class MacOSXCGLContext extends GLContextImpl
                       gl3ShaderProgramName = gl3ShaderProgram.program();
                   } else {
                       gl3ShaderProgramName = 0;
-                  }
-                  nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, gl3ShaderProgramName, nsOpenGLLayerPFmt, pbufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight);
-                  if (DEBUG) {
-                      System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(pbufferHandle)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", "+drawable);
-                  }
-                  backingLayerHost.attachSurfaceLayer(nsOpenGLLayer);
-                  setSwapInterval(1); // enabled per default in layered surface                
-              } else {
+                  }                                     
+                   
+                  // All CALayer lifecycle ops are deferred on main-thread
+                  attachGLLayerCmd = new AttachGLLayerCmd( 
+                          backingLayerHost, ctx, gl3ShaderProgramName, pixelFormat, pbufferHandle, texID, 
+                          chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight );
+                  if(DEBUG) {
+                      System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable(true): "+attachGLLayerCmd);
+                  }                            
+                  OSXUtil.RunOnMainThread(false, attachGLLayerCmd);
+              } else { // -> null == backingLayerHost                  
                   lastWidth = drawable.getWidth();
                   lastHeight = drawable.getHeight();                  
+                  boolean[] isPBuffer = { false };
+                  boolean[] isFBO = { false };
+                  CGL.setContextView(contextHandle, getNSViewHandle(isPBuffer, isFBO));
               }
-          } else {
-              if( 0 != nsOpenGLLayer ) {
-                  final NativeSurface surface = drawable.getNativeSurface();
-                  if (DEBUG) {
-                      System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", "+drawable);
+          } else { // -> !bound
+              if( null != backingLayerHost ) {
+                  final AttachGLLayerCmd cmd = attachGLLayerCmd;
+                  attachGLLayerCmd = null;
+                  if( null == cmd ) {
+                      throw new GLException("Null attachGLLayerCmd: "+drawable);
                   }
-                  final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
-                  if(null != ols && ols.isSurfaceLayerAttached()) {
-                      // still having a valid OLS attached to surface (parent OLS could have been removed)
-                      ols.detachSurfaceLayer();
+                  if( 0 != cmd.pbuffer ) {
+                      CGL.setContextPBuffer(contextHandle, 0);
                   }
-                  CGL.releaseNSOpenGLLayer(nsOpenGLLayer);
-                  if( null != gl3ShaderProgram ) {
-                      gl3ShaderProgram.destroy(MacOSXCGLContext.this.gl.getGL3());
-                      gl3ShaderProgram = null;
+                  synchronized(cmd) {
+                      if( !cmd.valid ) {
+                          cmd.valid = true; // skip pending creation
+                      } else {
+                          // All CALayer lifecycle ops are deferred on main-thread
+                          final DetachGLLayerCmd dCmd = new DetachGLLayerCmd(cmd);
+                          if(DEBUG) {
+                              System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable(false): "+dCmd);
+                          }                            
+                          OSXUtil.RunOnMainThread(false, dCmd);
+                          if( null != gl3ShaderProgram ) {
+                              gl3ShaderProgram.destroy(MacOSXCGLContext.this.gl.getGL3());
+                              gl3ShaderProgram = null;
+                          }
+                      }
                   }
-                  nsOpenGLLayer = 0;
-              }
-              if(0 != nsOpenGLLayerPFmt) {
-                  CGL.deletePixelFormat(nsOpenGLLayerPFmt);
-                  nsOpenGLLayerPFmt = 0;
               }
+              CGL.clearDrawable(contextHandle);
+              backingLayerHost = null;
           }
-          backingLayerHost = null;
-          return true;
       }
 
       private final void validatePBufferConfig(long ctx) {
@@ -736,7 +939,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
           if(0 == cglCtx) {
               throw new InternalError("Null CGLContext for: "+this);
           }
-          int err = CGL.CGLLockContext(cglCtx);
+          final int err = CGL.CGLLockContext(cglCtx);
           if(CGL.kCGLNoError == err) {
               validatePBufferConfig(ctx); // required to handle pbuffer change ASAP
               return CGL.makeCurrentContext(ctx);
@@ -749,7 +952,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
       @Override
       public boolean release(long ctx) {
           try {
-              gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze
+              if( hasRendererQuirk(GLRendererQuirks.GLFlushBeforeRelease) && null != MacOSXCGLContext.this.getGLProcAddressTable() ) {
+                  gl.glFlush();
+              }
           } catch (GLException gle) {
               if(DEBUG) {
                   System.err.println("MacOSXCGLContext.NSOpenGLImpl.release: INFO: glFlush() catched exception:");
@@ -777,62 +982,133 @@ public abstract class MacOSXCGLContext extends GLContextImpl
       
       @Override
       public boolean setSwapInterval(int interval) {
-          if(0 != nsOpenGLLayer) {
-              CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval);
-              vsyncTimeout = interval * (int)screenVSyncTimeout + 1000; // +1ms
-              if(DEBUG) { System.err.println("NS setSwapInterval: "+vsyncTimeout+" micros"); }
+          final AttachGLLayerCmd cmd = attachGLLayerCmd;
+          if(null != cmd) {
+              synchronized(cmd) {
+                  if( cmd.valid && 0 != cmd.nsOpenGLLayer) {
+                      setSwapIntervalImpl(cmd.nsOpenGLLayer, interval);
+                      return true;
+                  }
+              }
           }
-          CGL.setSwapInterval(contextHandle, interval);
+          setSwapIntervalImpl(0, interval);
           return true;
       }
 
+      private void setSwapIntervalImpl(final long l, int interval) {
+          if( 0 != l ) {
+              CGL.setNSOpenGLLayerSwapInterval(l, interval);
+              if( 0 < interval ) {
+                  vsyncTimeout = interval * screenVSyncTimeout + 1000; // +1ms
+              } else {
+                  vsyncTimeout = 1 * screenVSyncTimeout + 1000; // +1ms
+              }
+              if(DEBUG) { System.err.println("NS setSwapInterval: "+interval+" -> "+vsyncTimeout+" micros"); }
+          }
+          if(DEBUG) { System.err.println("CGL setSwapInterval: "+interval); }
+          CGL.setSwapInterval(contextHandle, interval);
+      }
+      
       private int skipSync=0;
+      /** TODO: Remove after discussion
+      private boolean perfIterReset = false;
+      private int perfIter = 0;
+      private long waitGLS = 0;
+      private long finishGLS = 0;
+      private long frameXS = 0;
+      private long lastFrameStart = 0;
+      */
       
       @Override
       public boolean swapBuffers() {
-          final boolean res;
-          if( 0 != nsOpenGLLayer ) {
-              if( validateDrawableSizeConfig(contextHandle) ) {
-                  // skip wait-for-vsync for a few frames if size has changed,
-                  // allowing to update the texture IDs ASAP.
-                  skipSync = 10;
-              }
-              
-              final int texID;
-              final boolean valid;
-              final boolean isFBO = drawable instanceof GLFBODrawableImpl;
-              if( isFBO ){
-                  texID = ((GLFBODrawableImpl)drawable).getTextureBuffer(GL.GL_FRONT).getName();
-                  valid = 0 != texID;
-              } else {
-                  texID = 0;
-                  valid = 0 != drawable.getHandle();
-              }
-              if(valid) {
-                  if(0 == skipSync) {
-                      // If v-sync is disabled, frames will be drawn as quickly as possible
-                      // w/o delay but in sync w/ CALayer. Otherwise wait until next swap interval (v-sync).
-                      CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, vsyncTimeout);
-                  } else {
-                      skipSync--;
-                  }
-                  res = CGL.flushBuffer(contextHandle);
-                  if(res) {
-                      if(isFBO) {
-                          // trigger CALayer to update incl. possible surface change (texture)
-                          CGL.setNSOpenGLLayerNeedsDisplayFBO(nsOpenGLLayer, texID);                          
+          final AttachGLLayerCmd cmd = attachGLLayerCmd;
+          if(null != cmd) {
+              synchronized(cmd) {
+                  if( cmd.valid && 0 != cmd.nsOpenGLLayer) {
+                      if( validateDrawableSizeConfig(contextHandle) ) {
+                          // skip wait-for-vsync for a few frames if size has changed,
+                          // allowing to update the texture IDs ASAP.
+                          skipSync = 10;
+                      }
+                      
+                      final boolean res;
+                      final int texID;
+                      final boolean valid;
+                      final boolean isFBO = drawable instanceof GLFBODrawableImpl;
+                      if( isFBO ){
+                          texID = ((GLFBODrawableImpl)drawable).getTextureBuffer(GL.GL_FRONT).getName();
+                          valid = 0 != texID;
+                      } else {
+                          texID = 0;
+                          valid = 0 != drawable.getHandle();
+                      }
+                      if(valid) {
+                          res = CGL.flushBuffer(contextHandle);
+                          if(res) {
+                              if(0 == skipSync) {
+                                  /** TODO: Remove after discussion
+                                  perfIter++;
+                                  if( !perfIterReset && 100 == perfIter ) {
+                                      perfIterReset = true;
+                                      perfIter = 1;
+                                      waitGLS = 0;
+                                      finishGLS = 0;
+                                      frameXS = 0;
+                                  }
+                                  final long lastFramePeriod0 = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+                                  gl.glFinish(); // Require to finish previous GL rendering to give CALayer proper result
+                                  final long lastFramePeriod1 = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+                                  
+                                  // If v-sync is disabled, frames will be drawn as quickly as possible w/o delay, 
+                                  // while still synchronizing w/ CALayer.
+                                  // If v-sync is enabled wait until next swap interval (v-sync).
+                                  CGL.waitUntilNSOpenGLLayerIsReady(cmd.nsOpenGLLayer, vsyncTimeout);
+                                  final long lastFramePeriodX = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+                                  
+                                  final long finishGL = lastFramePeriod1 - lastFramePeriod0;
+                                  final long waitGL = lastFramePeriodX - lastFramePeriod1;
+                                  finishGLS += finishGL;
+                                  waitGLS += waitGL;
+                                  frameXS += lastFramePeriodX;
+                                  
+                                  System.err.println("XXX["+perfIter+"] TO "+vsyncTimeout/1000+" ms, "+
+                                                     "lFrame0 "+lastFramePeriod0/1000+" ms, "+
+                                                     "lFrameX "+lastFramePeriodX/1000+" / "+frameXS/1000+" ~"+(frameXS/perfIter)/1000.0+" ms, "+
+                                                     "finishGL "+finishGL/1000+" / "+finishGLS/1000+" ~"+(finishGLS/perfIter)/1000.0+" ms, "+
+                                                     "waitGL "+waitGL/1000+" / "+waitGLS/1000+" ~"+(waitGLS/perfIter)/1000.0+" ms");
+                                  */
+                                  //
+                                  // Required(?) to finish previous GL rendering to give CALayer proper result,
+                                  // i.e. synchronize both threads each w/ their GLContext sharing same resources.
+                                  //
+                                  // FIXME: IMHO this synchronization should be implicitly performed via 'CGL.flushBuffer(contextHandle)' above,
+                                  // in case this will be determined a driver bug - use a QUIRK entry in GLRendererQuirks!
+                                  gl.glFinish();
+                                  
+                                  // If v-sync is disabled, frames will be drawn as quickly as possible w/o delay, 
+                                  // while still synchronizing w/ CALayer.
+                                  // If v-sync is enabled wait until next swap interval (v-sync).
+                                  CGL.waitUntilNSOpenGLLayerIsReady(cmd.nsOpenGLLayer, vsyncTimeout);
+                              } else {
+                                  skipSync--;
+                              }
+                              if(isFBO) {
+                                  // trigger CALayer to update incl. possible surface change (texture)
+                                  CGL.setNSOpenGLLayerNeedsDisplayFBO(cmd.nsOpenGLLayer, texID);
+                              } else {
+                                  // trigger CALayer to update incl. possible surface change (new pbuffer handle)
+                                  CGL.setNSOpenGLLayerNeedsDisplayPBuffer(cmd.nsOpenGLLayer, drawable.getHandle());                          
+                              }
+                              // lastFrameStart = TimeUnit.NANOSECONDS.toMicros(System.nanoTime());
+                          }
                       } else {
-                          // trigger CALayer to update incl. possible surface change (new pbuffer handle)
-                          CGL.setNSOpenGLLayerNeedsDisplayPBuffer(nsOpenGLLayer, drawable.getHandle());                          
+                          res = true;
                       }
+                      return res;
                   }
-              } else {
-                  res = true;
               }
-          } else {
-              res = CGL.flushBuffer(contextHandle);
           }
-          return res;
+          return CGL.flushBuffer(contextHandle);
       }
 
   }
@@ -895,8 +1171,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
       }
 
       @Override
-      public boolean contextRealized(boolean realized) {
-          return true;
+      public void associateDrawable(boolean bound) {
       }
 
       @Override
@@ -924,7 +1199,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
       @Override
       public boolean release(long ctx) {
           try {
-              gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze
+              if( hasRendererQuirk(GLRendererQuirks.GLFlushBeforeRelease) && null != MacOSXCGLContext.this.getGLProcAddressTable() ) {
+                  gl.glFlush();
+              }
           } catch (GLException gle) {
               if(DEBUG) {
                   System.err.println("MacOSXCGLContext.CGLImpl.release: INFO: glFlush() catched exception:");
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
index cc727c8..910158d 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
@@ -106,10 +106,6 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
   protected void setRealizedImpl() {
   }
   
-  protected long getNSViewHandle() {
-      return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0;
-  }
-
   @Override
   protected void associateContext(GLContext ctx, boolean bound) {
     // NOTE: we need to keep track of the created contexts in order to
@@ -117,7 +113,8 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
     // OpenGL window interface
     synchronized (createdContexts) {
         if(bound) {
-            createdContexts.add(new WeakReference<MacOSXCGLContext>((MacOSXCGLContext)ctx));
+            final MacOSXCGLContext osxCtx = (MacOSXCGLContext)ctx;
+            createdContexts.add(new WeakReference<MacOSXCGLContext>(osxCtx));
         } else {
             for(int i=0; i<createdContexts.size(); ) {
                 final WeakReference<MacOSXCGLContext> ref = createdContexts.get(i); 
@@ -155,10 +152,6 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
     return getFactoryImpl().getGLDynamicLookupHelper(0);
   }
 
-  protected static String getThreadName() {
-    return Thread.currentThread().getName();
-  }
-
   // Support for "mode switching" as described in MacOSXCGLDrawable
   public void setOpenGLMode(GLBackendType mode) {
       if (mode == openGLMode) {
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index ae2082d..c9402b3 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -64,12 +64,13 @@ import javax.media.opengl.GLProfile;
 import jogamp.nativewindow.WrappedSurface;
 import jogamp.nativewindow.macosx.OSXDummyUpstreamSurfaceHook;
 import jogamp.opengl.DesktopGLDynamicLookupHelper;
+import jogamp.opengl.GLContextImpl;
 import jogamp.opengl.GLDrawableFactoryImpl;
 import jogamp.opengl.GLDrawableImpl;
 import jogamp.opengl.GLDynamicLookupHelper;
 import jogamp.opengl.GLGraphicsConfigurationUtil;
+import jogamp.opengl.SharedResourceRunner;
 
-import com.jogamp.common.JogampRuntimeException;
 import com.jogamp.common.nio.Buffers;
 import com.jogamp.common.util.ReflectionUtil;
 import com.jogamp.nativewindow.MutableGraphicsConfiguration;
@@ -112,7 +113,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
             try {
               ReflectionUtil.callStaticMethod("jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLGraphicsConfigurationFactory",
                                               "registerFactory", null, null, getClass().getClassLoader());
-            } catch (JogampRuntimeException jre) { /* n/a .. */ }
+            } catch (Exception jre) { /* n/a .. */ }
         }
 
         sharedMap = new HashMap<String, SharedResource>();
@@ -147,35 +148,54 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
   private HashMap<String, SharedResource> sharedMap = new HashMap<String, SharedResource>();
   private MacOSXGraphicsDevice defaultDevice;
 
-  static class SharedResource {
+  static class SharedResource implements SharedResourceRunner.Resource {
       // private MacOSXCGLDrawable drawable;
       // private MacOSXCGLContext context;
       private GLRendererQuirks glRendererQuirks;
       MacOSXGraphicsDevice device;
-      boolean wasContextCreated;
+      boolean valid;
       boolean hasNPOTTextures;
       boolean hasRECTTextures;
       boolean hasAppleFloatPixels;
 
-      SharedResource(MacOSXGraphicsDevice device, boolean wasContextCreated,
+      SharedResource(MacOSXGraphicsDevice device, boolean valid,
                      boolean hasNPOTTextures, boolean hasRECTTextures, boolean hasAppletFloatPixels
                      /* MacOSXCGLDrawable draw, MacOSXCGLContext ctx */, GLRendererQuirks glRendererQuirks) {
           // drawable = draw;
           // this.context = ctx;
           this.glRendererQuirks = glRendererQuirks;
           this.device = device;
-          this.wasContextCreated = wasContextCreated;
+          this.valid = valid;
           this.hasNPOTTextures = hasNPOTTextures;
           this.hasRECTTextures = hasRECTTextures;
           this.hasAppleFloatPixels = hasAppletFloatPixels;
       }
-      final MacOSXGraphicsDevice getDevice() { return device; }
+      @Override
+      public final boolean isValid() {
+          return valid;
+      }
+      @Override
+      public final MacOSXGraphicsDevice getDevice() { return device; }
       // final MacOSXCGLContext getContext() { return context; }
-      final GLRendererQuirks getGLRendererQuirks() { return glRendererQuirks; }
-      final boolean wasContextAvailable() { return wasContextCreated; }
       final boolean isNPOTTextureAvailable() { return hasNPOTTextures; }
       final boolean isRECTTextureAvailable() { return hasRECTTextures; }
       final boolean isAppleFloatPixelsAvailable() { return hasAppleFloatPixels; }
+      @Override
+      public final AbstractGraphicsScreen getScreen() {
+          return null;
+      }
+      @Override
+      public final GLDrawableImpl getDrawable() {
+          return null;
+      }
+      @Override
+      public GLContextImpl getContext() {
+          return null;
+      }
+      @Override
+      public GLRendererQuirks getRendererQuirks() {
+          return glRendererQuirks;      
+      }
   }
 
   @Override
@@ -209,7 +229,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
       }
   }
 
-  /* package */ SharedResource getOrCreateOSXSharedResource(AbstractGraphicsDevice adevice) {
+  protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice adevice) {
     final String connection = adevice.getConnection();
     SharedResource sr;
     synchronized(sharedMap) {
@@ -219,7 +239,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
         addDeviceTried(connection);
         final MacOSXGraphicsDevice sharedDevice = new MacOSXGraphicsDevice(adevice.getUnitID());
         GLRendererQuirks glRendererQuirks = null;
-        boolean madeCurrent = false;
+        boolean isValid = false;
         boolean hasNPOTTextures = false;
         boolean hasRECTTextures = false;
         boolean hasAppleFloatPixels = false;
@@ -239,8 +259,8 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
             
             try {
                 sharedContext.makeCurrent(); // could cause exception
-                madeCurrent = sharedContext.isCurrent();
-                if(madeCurrent) {
+                isValid = sharedContext.isCurrent();
+                if(isValid) {
                     GL gl = sharedContext.getGL();
                     hasNPOTTextures = gl.isNPOTTextureAvailable();
                     hasRECTTextures = gl.isExtensionAvailable(GLExtensions.EXT_texture_rectangle);
@@ -264,14 +284,14 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
             }
             sharedDrawable.setRealized(false);
         }
-        sr = new SharedResource(sharedDevice, madeCurrent, hasNPOTTextures, hasRECTTextures, hasAppleFloatPixels, glRendererQuirks);
+        sr = new SharedResource(sharedDevice, isValid, hasNPOTTextures, hasRECTTextures, hasAppleFloatPixels, glRendererQuirks);
         synchronized(sharedMap) {
             sharedMap.put(connection, sr);
         }
         removeDeviceTried(connection);
         if (DEBUG) {
             System.err.println("MacOSXCGLDrawableFactory.createShared: device:  " + sharedDevice);
-            System.err.println("MacOSXCGLDrawableFactory.createShared: context: madeCurrent " + madeCurrent + ", NPOT "+hasNPOTTextures+
+            System.err.println("MacOSXCGLDrawableFactory.createShared: context: madeCurrent " + isValid + ", NPOT "+hasNPOTTextures+
                                ", RECT "+hasRECTTextures+", FloatPixels "+hasAppleFloatPixels+", "+glRendererQuirks);
         }
     }
@@ -284,46 +304,6 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
   }
 
   @Override
-  protected final boolean createSharedResource(AbstractGraphicsDevice device) {
-    try {
-        SharedResource sr = getOrCreateOSXSharedResource(device);
-        if(null!=sr) {
-            return sr.wasContextAvailable();
-        }
-    } catch (GLException gle) {
-        if(DEBUG) {
-            System.err.println("Catched Exception while MaxOSXCGL Shared Resource initialization:");
-            gle.printStackTrace();
-        }
-    }
-    return false;
-  }
-
-  @Override
-  protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
-      // FIXME: no more available
-      return null;
-  }
-
-  @Override
-  public GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device) {
-      SharedResource sr = getOrCreateOSXSharedResource(device);
-      if(null!=sr) {
-          return sr.getGLRendererQuirks(); 
-      }
-      return null;
-  }
-  
-  @Override
-  protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
-      SharedResource sr = getOrCreateOSXSharedResource(device);
-      if(null!=sr) {
-          return sr.getDevice();
-      }
-      return null;
-  }
-
-  @Override
   protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
       return MacOSXCGLGraphicsConfiguration.getAvailableCapabilities(this, device);
   }
@@ -406,17 +386,6 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
     throw new GLException("Not yet implemented");
   }
 
-  @Override
-  public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
-    return false;
-  }
-
-  @Override
-  public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
-    throws GLException {
-    throw new GLException("not supported in non AWT enviroment");
-  }
-
   //------------------------------------------------------
   // Gamma-related functionality
   //
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
index 03ec94d..f8c874a 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
@@ -31,13 +31,13 @@ package jogamp.opengl.macosx.cgl;
 import jogamp.opengl.*;
 import java.util.*;
 
-public class MacOSXCGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo  {
+public final class MacOSXCGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo  {
     protected MacOSXCGLDynamicLibraryBundleInfo() {
         super();
     }
 
     @Override
-    public List<List<String>> getToolLibNames() {
+    public final List<List<String>> getToolLibNames() {
         final List<List<String>> libsList = new ArrayList<List<String>>();
         final List<String> libsGL = new ArrayList<String>();
         libsGL.add("/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib");
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
index fa8e8d4..5eb11c6 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
@@ -64,7 +64,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
     }
 
     protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(MacOSXCGLDrawableFactory factory, AbstractGraphicsDevice device) {
-        MacOSXCGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateOSXSharedResource(device);
+        MacOSXCGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
         if(null == sharedResource) {
             throw new GLException("Shared resource for device n/a: "+device);
         }
@@ -104,7 +104,8 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
                 break;
                   
               case CGL.kCGLPFAColorFloat:
-                ivalues.put(idx, ( !caps.isOnscreen() && caps.isPBuffer() && caps.getPbufferFloatingPointBuffers() ) ? 1 : 0);
+                // ivalues.put(idx, ( !caps.isOnscreen() && caps.isPBuffer() && caps.getPbufferFloatingPointBuffers() ) ? 1 : 0);
+                  ivalues.put(idx, 0);
                 break;
 
               case CGL.NSOpenGLPFAPixelBuffer:
@@ -176,12 +177,13 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
           attrs.put(i++, CGL.kCGLPFAOpenGLProfile); 
           attrs.put(i++, MacOSXCGLContext.GLProfile2CGLOGLProfileValue(ctp, major, minor));
       }
+      /**
       if(!caps.isOnscreen() && caps.isPBuffer()) {
         attrs.put(i++, CGL.kCGLPFAPBuffer);
         if (caps.getPbufferFloatingPointBuffers()) {
           attrs.put(i++, CGL.kCGLPFAColorFloat);
         }
-      }
+      } */
       if (caps.getDoubleBuffered()) {
         attrs.put(i++, CGL.kCGLPFADoubleBuffer);
       }
@@ -284,7 +286,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
                 break;
                 
               case CGL.kCGLPFAColorFloat:
-                caps.setPbufferFloatingPointBuffers(ivalue != 0);
+                // caps.setPbufferFloatingPointBuffers(ivalue != 0);
                 break;
 
               case CGL.NSOpenGLPFAPixelBuffer:
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
index 65ed5fc..d23d8a7 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
@@ -57,14 +57,13 @@ import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType;
 
 
 public class MacOSXExternalCGLContext extends MacOSXCGLContext {
-  private GLContext lastContext;
 
   private MacOSXExternalCGLContext(Drawable drawable, boolean isNSContext, long handle) {
     super(drawable, null);
     setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL );
     this.contextHandle = handle;
     GLContextShareSet.contextCreated(this);
-    setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT);
+    setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false);
     getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
   }
 
@@ -123,25 +122,6 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext {
   }
 
   @Override
-  public int makeCurrent() throws GLException {
-    // Save last context if necessary to allow external GLContexts to
-    // talk to other GLContexts created by this library
-    GLContext cur = getCurrent();
-    if (cur != null && cur != this) {
-      lastContext = cur;
-      setCurrent(null);
-    }
-    return super.makeCurrent();
-  }
-
-  @Override
-  public void release() throws GLException {
-    super.release();
-    setCurrent(lastContext);
-    lastContext = null;
-  }
-
-  @Override
   protected void makeCurrentImpl() throws GLException {
   }
 
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
deleted file mode 100644
index 7b13ce2..0000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2003 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.
- *
- * 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 jogamp.opengl.macosx.cgl;
-
-import javax.media.opengl.*;
-
-public class MacOSXOffscreenCGLContext extends MacOSXPbufferCGLContext
-{
-  public MacOSXOffscreenCGLContext(MacOSXPbufferCGLDrawable drawable,
-                                  GLContext shareWith) {
-    super(drawable, shareWith);
-  }
-
-  @Override
-  public int getOffscreenContextPixelDataType() {
-    GL gl = getGL();
-    return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
-  }
-
-  @Override
-  public int getOffscreenContextReadBuffer() {
-    return GL.GL_FRONT;
-  }
-
-  @Override
-  public boolean offscreenImageNeedsVerticalFlip() {
-    return true;
-  }
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java
index 4f90055..446a834 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java
@@ -53,6 +53,6 @@ public class MacOSXOffscreenCGLDrawable extends MacOSXPbufferCGLDrawable {
 
   @Override
   public GLContext createContext(GLContext shareWith) {
-    return new MacOSXOffscreenCGLContext(this, shareWith);
+    return new MacOSXCGLContext(this, shareWith);
   }
 }
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
deleted file mode 100644
index 447d18f..0000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2003 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.
- *
- * 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 jogamp.opengl.macosx.cgl;
-
-import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.ProxySurface;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
-
-import jogamp.opengl.GLContextImpl;
-
-public class MacOSXOnscreenCGLContext extends MacOSXCGLContext {
-
-  public MacOSXOnscreenCGLContext(MacOSXOnscreenCGLDrawable drawable,
-                                 GLContext shareWith) {
-    super(drawable, shareWith);
-  }
-
-  @Override
-  protected void makeCurrentImpl() throws GLException {
-      super.makeCurrentImpl();
-      drawableUpdatedNotify();
-  }
-
-  @Override
-  protected void drawableUpdatedNotify() throws GLException {
-    final int w = drawable.getWidth();
-    final int h = drawable.getHeight();    
-    final boolean updateContext = ( 0!=updateHandle && CGL.updateContextNeedsUpdate(updateHandle) ) ||
-                                  w != lastWidth || h != lastHeight;
-    if(updateContext) {
-        lastWidth = w;
-        lastHeight = h;
-        if (contextHandle == 0) {
-          throw new GLException("Context not created");
-        }
-        CGL.updateContext(contextHandle);
-    }
-  }
-
-  @Override
-  protected boolean createImpl(GLContextImpl sharedWith) {
-    boolean res = super.createImpl(sharedWith);
-    lastWidth = -1;
-    lastHeight = -1;
-    if(res && isNSContext()) {
-        if(0 != updateHandle) {
-            throw new InternalError("XXX1");
-        }
-        final boolean incompleteView;
-        final NativeSurface surface = drawable.getNativeSurface();
-        if( surface instanceof ProxySurface ) {
-          incompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
-        } else {
-          incompleteView = false;
-        }
-        if(!incompleteView) {        
-            updateHandle = CGL.updateContextRegister(contextHandle, drawable.getHandle());
-            if(0 == updateHandle) {
-                throw new InternalError("XXX2");
-            }
-        }
-    }
-    return res;
-  }
-
-  @Override
-  protected void destroyImpl() throws GLException {
-    if ( 0 != updateHandle ) {
-        CGL.updateContextUnregister(updateHandle);
-        updateHandle = 0;
-    }
-    super.destroyImpl();
-  }
-
-  private long updateHandle = 0;
-  private int lastWidth, lastHeight;
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java
index ec96280..c6f0c13 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java
@@ -52,7 +52,7 @@ public class MacOSXOnscreenCGLDrawable extends MacOSXCGLDrawable {
 
   @Override
   public GLContext createContext(GLContext shareWith) {
-    return new MacOSXOnscreenCGLContext(this, shareWith);
+    return new MacOSXCGLContext(this, shareWith);
   }
 
 }
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java
deleted file mode 100644
index 7e2d8cf..0000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.
- */
-
-package jogamp.opengl.macosx.cgl;
-
-import javax.media.opengl.GL;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLPbuffer;
-
-import jogamp.opengl.GLContextImpl;
-
- at SuppressWarnings("deprecation")
-public class MacOSXPbufferCGLContext extends MacOSXCGLContext {
-
-  // State for render-to-texture and render-to-texture-rectangle support
-  private int texture;       // actual texture object
-
-  public MacOSXPbufferCGLContext(MacOSXPbufferCGLDrawable drawable,
-                                GLContext shareWith) {
-    super(drawable, shareWith);
-  }
-
-  @Override
-  public void bindPbufferToTexture() {
-    GL gl = getGL();
-    gl.glBindTexture(((MacOSXPbufferCGLDrawable)drawable).getTextureTarget(), texture);
-    // FIXME: not clear whether this is really necessary, but since
-    // the API docs seem to imply it is and since it doesn't seem to
-    // impact performance, leaving it in
-    CGL.setContextTextureImageToPBuffer(contextHandle, drawable.getHandle(), GL.GL_FRONT);
-  }
-
-  @Override
-  public void releasePbufferFromTexture() {
-  }
-
-  @Override
-  protected boolean createImpl(GLContextImpl shareWith) {
-    boolean res = super.createImpl(shareWith);
-    if(res) {
-      // Initialize render-to-texture support if requested
-      final GL gl = getGL();
-      final MacOSXPbufferCGLDrawable osxPDrawable = (MacOSXPbufferCGLDrawable)drawable;
-      final int textureTarget = osxPDrawable.getTextureTarget();
-
-      int[] tmp = new int[1];
-      gl.glGenTextures(1, tmp, 0);
-      texture = tmp[0];
-      gl.glBindTexture(textureTarget, texture);
-      gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
-      gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
-      gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
-      gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
-      gl.glTexImage2D(textureTarget, 0, GL.GL_RGB, osxPDrawable.getTextureWidth(), osxPDrawable.getTextureHeight(),
-                      0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, null);
-      gl.glCopyTexSubImage2D(textureTarget, 0, 0, 0, 0, 0, drawable.getWidth(), drawable.getHeight());
-    }
-    return res;
-  }
-
-  @Override
-  public int getFloatingPointMode() {
-    return GLPbuffer.APPLE_FLOAT;
-  }
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
index 668e463..4e791cb 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
@@ -47,7 +47,6 @@ import javax.media.nativewindow.NativeSurface;
 import javax.media.nativewindow.MutableSurface;
 import javax.media.opengl.GL;
 import javax.media.opengl.GL2;
-import javax.media.opengl.GL2GL3;
 import javax.media.opengl.GLCapabilitiesImmutable;
 import javax.media.opengl.GLContext;
 import javax.media.opengl.GLDrawableFactory;
@@ -89,15 +88,9 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
 
   @Override
   public GLContext createContext(GLContext shareWith) {
-    return new MacOSXPbufferCGLContext(this, shareWith);
+    return new MacOSXCGLContext(this, shareWith);
   }
   
-  @Override
-  protected long getNSViewHandle() {
-    // pbuffer handle is NSOpenGLPixelBuffer
-    return 0;
-  }
-
   protected int getTextureTarget() { return pBufferTexTarget;  }
   protected int getTextureWidth() { return pBufferTexWidth; }
   protected int getTextureHeight() { return pBufferTexHeight; }
@@ -128,10 +121,10 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
     final DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ms.getGraphicsConfiguration();
     final GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities();
     final GLProfile glProfile = capabilities.getGLProfile();
-    MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateOSXSharedResource(config.getScreen().getDevice());
+    MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateSharedResourceImpl(config.getScreen().getDevice());
 
     if (DEBUG) {
-        System.out.println("Pbuffer config: " + config);
+        System.out.println(getThreadName()+": Pbuffer config: " + config);
         if(null != sr) {
             System.out.println("Pbuffer NPOT Texure  avail: "+sr.isNPOTTextureAvailable());
             System.out.println("Pbuffer RECT Texture avail: "+sr.isRECTTextureAvailable());
@@ -140,12 +133,8 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
         }
     }
 
-    if ( capabilities.getPbufferRenderToTextureRectangle() && null!=sr && sr.isRECTTextureAvailable() ) {
-      pBufferTexTarget = GL2GL3.GL_TEXTURE_RECTANGLE;
-    } else {
-      pBufferTexTarget = GL.GL_TEXTURE_2D;
-    }
-    if ( GL2GL3.GL_TEXTURE_RECTANGLE == pBufferTexTarget || ( null!=sr && sr.isNPOTTextureAvailable() ) ) {
+    pBufferTexTarget = GL.GL_TEXTURE_2D;
+    if ( null!=sr && sr.isNPOTTextureAvailable() ) {
       pBufferTexWidth = getWidth();
       pBufferTexHeight = getHeight();
     } else {
@@ -153,18 +142,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
       pBufferTexHeight = GLBuffers.getNextPowerOf2(getHeight());
     }
 
-    int internalFormat = GL.GL_RGBA;
-    if (capabilities.getPbufferFloatingPointBuffers()) {
-      if(!glProfile.isGL2GL3() || null==sr || sr.isAppleFloatPixelsAvailable()) {
-          throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available");
-      }
-      switch (capabilities.getRedBits()) {
-        case 16: internalFormat = GL2.GL_RGBA_FLOAT16_APPLE; break;
-        case 32: internalFormat = GL2.GL_RGBA_FLOAT32_APPLE; break;
-        default: throw new GLException("Invalid floating-point bit depth (only 16 and 32 supported)");
-      }
-    }
-
+    final int internalFormat = GL.GL_RGBA;
     final long pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight());
     if(DEBUG) {
         System.err.println("MacOSXPbufferCGLDrawable tex: target "+toHexString(pBufferTexTarget)+
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java
deleted file mode 100644
index fe60710..0000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2003 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.
- * 
- * 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 jogamp.opengl.macosx.cgl.awt;
-
-import javax.media.nativewindow.*;
-import javax.media.opengl.*;
-import jogamp.opengl.macosx.cgl.*;
-
-public class MacOSXAWTCGLDrawableFactory extends MacOSXCGLDrawableFactory {
-
-  public MacOSXAWTCGLDrawableFactory() {
-    super();
-  }
-
-  public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
-    return true;
-  }
-
-  public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
-    throws GLException {
-    return new MacOSXJava2DCGLContext(shareWith);
-  }
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java
deleted file mode 100644
index f41400d..0000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2006 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.
- * 
- * 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 jogamp.opengl.macosx.cgl.awt;
-
-import java.awt.Graphics;
-
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
-
-import jogamp.opengl.GLContextImpl;
-import jogamp.opengl.awt.Java2D;
-import jogamp.opengl.awt.Java2DGLContext;
-import jogamp.opengl.macosx.cgl.MacOSXCGLContext;
-import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType;
-
-
-/** MacOSXCGLContext implementation supporting the Java2D/JOGL bridge
- * on Mac OS X. The external GLDrawable mechanism does not work on Mac
- * OS X due to how drawables and contexts are operated upon on this
- * platform, so it is necessary to supply an alternative means to
- * create, make current, and destroy contexts on the Java2D "drawable"
- * on the Mac platform.
- */
-
-public class MacOSXJava2DCGLContext extends MacOSXCGLContext implements Java2DGLContext {
-  private Graphics graphics;
-
-  // FIXME: ignoring context sharing for the time being; will need to
-  // rethink this in particular if using FBOs to implement the
-  // Java2D/OpenGL pipeline on Mac OS X
-
-  MacOSXJava2DCGLContext(GLContext shareWith) {
-    super(null, shareWith);
-  }
-
-  public void setGraphics(Graphics g) {
-    this.graphics = g;
-  }
-
-  protected void makeCurrentImpl() throws GLException {
-    if (!Java2D.makeOGLContextCurrentOnSurface(graphics, contextHandle)) {
-      throw new GLException("Error making context current");
-    }            
-  }
-
-  protected boolean createImpl(GLContextImpl shareWith) {
-    long share = createImplPreset(shareWith);
-    
-    long ctx = Java2D.createOGLContextOnSurface(graphics, share);
-    if (ctx == 0) {
-      if(DEBUG) { 
-          System.err.println("Error creating current: "+this);
-      }
-      return false;
-    }
-    if (!Java2D.makeOGLContextCurrentOnSurface(graphics, contextHandle)) {
-      Java2D.destroyOGLContext(ctx);
-      if(DEBUG) { 
-          System.err.println("Error making created context current: "+this);
-      }
-      return false;
-    }
-    setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
-    contextHandle = ctx;
-    return true;
-  }
-
-  protected void releaseImpl() throws GLException {
-    // FIXME: would need another primitive in the Java2D class in
-    // order to implement this; hopefully should not matter for
-    // correctness
-  }
-
-  protected void destroyImpl() throws GLException {
-      Java2D.destroyOGLContext(contextHandle);
-  }
-
-  public void setOpenGLMode(GLBackendType mode) {
-    if (mode != GLBackendType.CGL) {
-      throw new GLException("OpenGL mode switching not supported for Java2D GLContexts");
-    }
-    super.setOpenGLMode(mode);
-  }
-}
diff --git a/src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java b/src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java
new file mode 100644
index 0000000..69223d0
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/openal/av/ALDummyUsage.java
@@ -0,0 +1,19 @@
+package jogamp.opengl.openal.av;
+
+import jogamp.opengl.util.av.impl.FFMPEGMediaPlayer;
+
+import com.jogamp.openal.AL;
+import com.jogamp.openal.JoalVersion;
+
+/** 
+ * Demo JOAL usage w/ av dependency, i.e. FFMPEGMediaPlayer ..
+ */
+public class ALDummyUsage {
+    static AL al;
+    static FFMPEGMediaPlayer.PixelFormat pfmt;
+    
+    public static void main(String args[]) {
+        System.err.println("JOGL> Hello JOAL");
+        System.err.println("JOAL: "+JoalVersion.getInstance().toString());
+    }
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java
index a6314a2..1a4ca34 100644
--- a/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java
+++ b/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java
@@ -31,9 +31,9 @@ package jogamp.opengl.util;
 import javax.media.opengl.*;
 
 /**
- * Handles consistency of buffer data and array state.
- * Implementations shall consider buffer types (VBO, ..), interleaved, etc.
- * They also need to consider array state types, i.e. fixed function or GLSL.
+ * Handles consistency of buffer data and array state.<br/>
+ * Implementations shall consider buffer types (VBO, ..), interleaved, etc.<br/>
+ * They also need to consider array state types, i.e. fixed function or GLSL.<br/>
  */
 public interface GLArrayHandler {
 
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
index 32c8635..2d40fe4 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
@@ -28,6 +28,8 @@
  
 package jogamp.opengl.util.av.impl;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -53,10 +55,10 @@ import com.jogamp.common.util.RunnableExecutor;
  *          Tue Feb 28 12:07:53 2012 322537478b63c6bc01e640643550ff539864d790 minor  1 ->  2
  */
 class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
-    private static List<String> glueLibNames = new ArrayList<String>(); // none
+    private static final List<String> glueLibNames = new ArrayList<String>(); // none
     
     private static final int symbolCount = 31;
-    private static String[] symbolNames = {
+    private static final String[] symbolNames = {
          "avcodec_version",
          "avformat_version",
 /* 3 */  "avutil_version",
@@ -97,7 +99,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
     };
     
     // alternate symbol names
-    private static String[][] altSymbolNames = {
+    private static final String[][] altSymbolNames = {
         { "avcodec_open",          "avcodec_open2" },              // old, 53.6.0
         { "avcodec_decode_audio3", "avcodec_decode_audio4" },      // old, 53.25.0
         { "av_close_input_file",   "avformat_close_input" },       // old, 53.17.0
@@ -105,7 +107,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
     };
     
     // optional symbol names
-    private static String[] optionalSymbolNames = {
+    private static final String[] optionalSymbolNames = {
          "avformat_free_context",     // 52.96.0   (opt)
          "avformat_network_init",     // 53.13.0   (opt)
          "avformat_network_deinit",   // 53.13.0   (opt)
@@ -131,8 +133,11 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
     
     static boolean initSingleton() { return ready; }
     
-    private static boolean initSymbols() {
-        final DynamicLibraryBundle dl = new DynamicLibraryBundle(new FFMPEGDynamicLibraryBundleInfo());
+    private static final boolean initSymbols() {
+        final DynamicLibraryBundle dl = AccessController.doPrivileged(new PrivilegedAction<DynamicLibraryBundle>() {
+                                          public DynamicLibraryBundle run() {
+                                              return new DynamicLibraryBundle(new FFMPEGDynamicLibraryBundleInfo());
+                                          } } );
         final boolean avutilLoaded = dl.isToolLibLoaded(0); 
         final boolean avformatLoaded = dl.isToolLibLoaded(1);
         final boolean avcodecLoaded = dl.isToolLibLoaded(2);
@@ -166,9 +171,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
         }
         
         // lookup
-        for(int i = 0; i<symbolCount; i++) {
-            symbolAddr[i] = dl.dynamicLookupFunction(symbolNames[i]);
-        }        
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            public Object run() {
+                for(int i = 0; i<symbolCount; i++) {
+                    symbolAddr[i] = dl.dynamicLookupFunction(symbolNames[i]);
+                }
+                return null;
+            } } );
         
         // validate results
         for(int i = 0; i<symbolCount; i++) {
@@ -206,10 +215,18 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
     }
 
     @Override
-    public boolean shallLinkGlobal() { return true; }
+    public final boolean shallLinkGlobal() { return true; }
 
+    /**
+     * {@inheritDoc}
+     * <p>
+     * Returns <code>true</code>.
+     * </p>
+     */ 
     @Override
-    public boolean shallLookupGlobal() { return true; }
+    public final boolean shallLookupGlobal() {
+        return true; 
+    }
     
     @Override
     public final List<String> getGlueLibNames() {
@@ -217,7 +234,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
     }
 
     @Override
-    public List<List<String>> getToolLibNames() {
+    public final List<List<String>> getToolLibNames() {
         List<List<String>> libsList = new ArrayList<List<String>>();
 
         final List<String> avutil = new ArrayList<String>();
@@ -274,12 +291,12 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo  {
     }
 
     @Override
-    public boolean useToolGetProcAdressFirst(String funcName) {
+    public final boolean useToolGetProcAdressFirst(String funcName) {
         return false;
     }
 
     @Override
-    public RunnableExecutor getLibLoaderExecutor() {
+    public final RunnableExecutor getLibLoaderExecutor() {
         return DynamicLibraryBundle.getDefaultRunnableExecutor();
     }    
     
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
index 4be2bcb..a417896 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
@@ -31,6 +31,8 @@ package jogamp.opengl.util.av.impl;
 import java.io.IOException;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 import javax.media.opengl.GL;
 import javax.media.opengl.GL2ES2;
@@ -43,9 +45,6 @@ import com.jogamp.opengl.util.texture.Texture;
 import com.jogamp.opengl.util.texture.TextureSequence;
 
 import jogamp.opengl.GLContextImpl;
-import jogamp.opengl.es1.GLES1ProcAddressTable;
-import jogamp.opengl.es2.GLES2ProcAddressTable;
-import jogamp.opengl.gl4.GL4bcProcAddressTable;
 import jogamp.opengl.util.av.EGLMediaPlayerImpl;
 
 /***
@@ -201,18 +200,30 @@ public class FFMPEGMediaPlayer extends EGLMediaPlayerImpl {
         }        
         setTextureFormat(tif, tf);
         setTextureType(GL.GL_UNSIGNED_BYTE);
-        GLContextImpl ctx = (GLContextImpl)gl.getContext();
-        ProcAddressTable pt = ctx.getGLProcAddressTable();
-        if(pt instanceof GLES2ProcAddressTable) {
-            procAddrGLTexSubImage2D = ((GLES2ProcAddressTable)pt)._addressof_glTexSubImage2D;
-        } else if(pt instanceof GLES1ProcAddressTable) {
-            procAddrGLTexSubImage2D = ((GLES1ProcAddressTable)pt)._addressof_glTexSubImage2D;
-        } else if(pt instanceof GL4bcProcAddressTable) {
-            procAddrGLTexSubImage2D = ((GL4bcProcAddressTable)pt)._addressof_glTexSubImage2D;
-        } else {
-            throw new InternalError("Unknown ProcAddressTable: "+pt.getClass().getName()+" of "+ctx.getClass().getName());
+        final GLContextImpl ctx = (GLContextImpl)gl.getContext();
+        final ProcAddressTable pt = ctx.getGLProcAddressTable();
+        procAddrGLTexSubImage2D = getAddressFor(pt, "glTexSubImage2D");
+        if( 0 == procAddrGLTexSubImage2D ) {
+            throw new InternalError("glTexSubImage2D n/a in ProcAddressTable: "+pt.getClass().getName()+" of "+ctx.getGLVersion());
         }
     }
+    
+    /**
+     * Catches IllegalArgumentException and returns 0 if functionName is n/a,
+     * otherwise the ProcAddressTable's field value. 
+     */
+    private final long getAddressFor(final ProcAddressTable table, final String functionName) {
+        return AccessController.doPrivileged(new PrivilegedAction<Long>() {
+            public Long run() {
+                try {
+                    return Long.valueOf( table.getAddressFor(functionName) );
+                } catch (IllegalArgumentException iae) { 
+                    return Long.valueOf(0);
+                }
+            }
+        } ).longValue();
+    }
+    
     private void updateAttributes2(int pixFmt, int planes, int bitsPerPixel, int bytesPerPixelPerPlane,
                                    int lSz0, int lSz1, int lSz2,
                                    int tWd0, int tWd1, int tWd2) {
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java
index 79bed90..3c468f3 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java
@@ -44,8 +44,8 @@ import com.jogamp.opengl.util.glsl.ShaderState;
  * Used for 1:1 GLSL arrays, i.e. where the buffer data 
  * represents this array only. 
  */
-public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandler {
-    
+public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandler {    
+  
   public GLSLArrayHandler(GLArrayDataEditable ad) {
     super(ad);
   }
@@ -60,8 +60,14 @@ public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandle
   
   public final void enableState(GL gl, boolean enable, Object ext) {
     final GL2ES2 glsl = gl.getGL2ES2();
-    final ShaderState st = (ShaderState) ext;    
-    
+    if( null != ext ) {
+        enableShaderState(glsl, enable, (ShaderState)ext);
+    } else {
+        enableSimple(glsl, enable);
+    }
+  }
+  
+  private final void enableShaderState(GL2ES2 glsl, boolean enable, ShaderState st) {
     if(enable) {
         /*
          * This would be the non optimized code path:
@@ -108,5 +114,57 @@ public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandle
         st.disableVertexAttribArray(glsl, ad);
     }
   }
+  
+  private final void enableSimple(GL2ES2 glsl, boolean enable) {
+    final int location = ad.getLocation();
+    if( 0 > location ) {
+        return;
+    }
+    if(enable) {
+        /*
+         * This would be the non optimized code path:
+         * 
+        if(ad.isVBO()) {
+            glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
+            if(!ad.isVBOWritten()) {
+                if(null!=buffer) {
+                    glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage());
+                }
+                ad.setVBOWritten(true);
+            }
+        }
+        st.vertexAttribPointer(glsl, ad);
+        */
+        final Buffer buffer = ad.getBuffer();
+        if(ad.isVBO()) {
+            // bind and refresh the VBO / vertex-attr only if necessary
+            if(!ad.isVBOWritten()) {
+                glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
+                if(null!=buffer) {
+                    glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage());
+                }
+                ad.setVBOWritten(true);
+                glsl.glVertexAttribPointer(ad);
+                glsl.glBindBuffer(ad.getVBOTarget(), 0);
+            } else {
+                // didn't experience a performance hit on this query ..
+                // (using ShaderState's location query above to validate the location)
+                final int[] qi = new int[1];
+                glsl.glGetVertexAttribiv(location, GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0);
+                if(ad.getVBOName() != qi[0]) {
+                    glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName());
+                    glsl.glVertexAttribPointer(ad);
+                    glsl.glBindBuffer(ad.getVBOTarget(), 0);
+                }
+            }
+        } else if(null!=buffer) {
+            glsl.glVertexAttribPointer(ad);
+        }
+
+        glsl.glEnableVertexAttribArray(location);
+    } else {
+        glsl.glDisableVertexAttribArray(location);
+    }
+  }
 }
 
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java
index c5beb7d..855406d 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java
@@ -53,9 +53,13 @@ public class GLSLArrayHandlerFlat implements GLArrayHandlerFlat {
     
   public final void syncData(GL gl, Object ext) {
     final GL2ES2 glsl = gl.getGL2ES2();
-    final ShaderState st = (ShaderState) ext;
-
-    st.vertexAttribPointer(glsl, ad);
+    if( null != ext ) {
+        ((ShaderState)ext).vertexAttribPointer(glsl, ad);
+    } else {
+        if( 0 <= ad.getLocation() ) {
+            glsl.glVertexAttribPointer(ad);
+        }
+    }
     /**
      * Due to probable application VBO switching, this might not make any sense ..
      * 
@@ -75,13 +79,22 @@ public class GLSLArrayHandlerFlat implements GLArrayHandlerFlat {
 
   public final void enableState(GL gl, boolean enable, Object ext) {
     final GL2ES2 glsl = gl.getGL2ES2();
-    final ShaderState st = (ShaderState) ext;
-    
-    if(enable) {
-        st.enableVertexAttribArray(glsl, ad);
+    if( null != ext ) {
+        final ShaderState st = (ShaderState)ext;
+        if(enable) {
+            st.enableVertexAttribArray(glsl, ad);
+        } else {
+            st.disableVertexAttribArray(glsl, ad);
+        }
     } else {
-        st.disableVertexAttribArray(glsl, ad);
+        final int location = ad.getLocation();
+        if( 0 <= location ) {
+            if(enable) {
+                glsl.glEnableVertexAttribArray(location);
+            } else {
+                glsl.glDisableVertexAttribArray(location);
+            }
+        }        
     }
   }  
 }
-
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java
index f36693e..c2048d6 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java
@@ -72,7 +72,7 @@ public class GLSLArrayHandlerInterleaved extends GLVBOArrayHandler implements GL
             throw new InternalError("Interleaved handle is not VBO: "+ad);
         }
         bindBuffer(gl, true);
-        // sub data will decide weather to update the vertex attrib pointer
+        // sub data will decide whether to update the vertex attrib pointer
         syncSubData(gl, ext);
         bindBuffer(gl, false);
     }
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
new file mode 100644
index 0000000..eaf8dc3
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
@@ -0,0 +1,195 @@
+/**
+ * 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 jogamp.opengl.util.glsl;
+
+import java.nio.FloatBuffer;
+
+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 javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLArrayData;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+public class GLSLTextureRaster  {
+    private final boolean textureVertFlipped;
+    private final int textureUnit;
+    
+    private ShaderProgram sp;
+    private PMVMatrix pmvMatrix;
+    private GLUniformData pmvMatrixUniform;
+    private GLUniformData activeTexUniform;
+    private GLArrayDataServer interleavedVBO;
+        
+    public GLSLTextureRaster(int textureUnit, boolean textureVertFlipped) {
+        this.textureVertFlipped = textureVertFlipped;
+        this.textureUnit = textureUnit;
+    }
+    
+    public int getTextureUnit() { return textureUnit; }
+
+    static final String shaderBasename = "texture01_xxx";
+    static final String shaderSrcPath = "../../shader";
+    static final String shaderBinPath = "../../shader/bin";
+    
+    public void init(GL2ES2 gl) {
+        // Create & Compile the shader objects
+        final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), 
+                                                  shaderSrcPath, shaderBinPath, shaderBasename, true);
+        final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), 
+                                                  shaderSrcPath, shaderBinPath, shaderBasename, true);
+        rsVp.defaultShaderCustomization(gl, true, true);
+        rsFp.defaultShaderCustomization(gl, true, true);
+        
+        // Create & Link the shader program
+        sp = new ShaderProgram();
+        sp.add(rsVp);
+        sp.add(rsFp);
+        if(!sp.link(gl, System.err)) {
+            throw new GLException("Couldn't link program: "+sp);
+        }
+        sp.useProgram(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
+        if( pmvMatrixUniform.setLocation(gl, sp.program()) < 0 ) {
+            throw new GLException("Couldn't locate "+pmvMatrixUniform+" in shader: "+sp);
+        }
+        gl.glUniform(pmvMatrixUniform);
+
+        activeTexUniform = new GLUniformData("mgl_Texture0", textureUnit);
+        if( activeTexUniform.setLocation(gl, sp.program()) < 0 ) {
+            throw new GLException("Couldn't locate "+activeTexUniform+" in shader: "+sp);
+        }
+        gl.glUniform(activeTexUniform);
+
+        final float[] s_quadTexCoords;
+        if( textureVertFlipped ) {
+            s_quadTexCoords = s_quadTexCoords01;
+        } else {
+            s_quadTexCoords = s_quadTexCoords00;
+        }
+        
+        interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+2, GL.GL_FLOAT, false, 2*4, GL.GL_STATIC_DRAW);
+        {        
+            final GLArrayData vArrayData = interleavedVBO.addGLSLSubArray("mgl_Vertex",        3, GL.GL_ARRAY_BUFFER);
+            if( vArrayData.setLocation(gl, sp.program()) < 0 ) {
+                throw new GLException("Couldn't locate "+vArrayData+" in shader: "+sp);
+            }
+            final GLArrayData tArrayData = interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
+            if( tArrayData.setLocation(gl, sp.program()) < 0 ) {
+                throw new GLException("Couldn't locate "+tArrayData+" in shader: "+sp);
+            }
+            final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();            
+            for(int i=0; i<4; i++) {
+                ib.put(s_quadVertices,  i*3, 3);
+                ib.put(s_quadTexCoords, i*2, 2);
+            }                        
+        }
+        interleavedVBO.seal(gl, true);
+        interleavedVBO.enableBuffer(gl, false);
+                
+        sp.useProgram(gl, false);
+    }
+
+    public void reshape(GL2ES2 gl, int x, int y, int width, int height) {
+        if(null != sp) {
+            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();
+            
+            sp.useProgram(gl, true);
+            gl.glUniform(pmvMatrixUniform);
+            sp.useProgram(gl, false);
+        }        
+    }
+
+    public void dispose(GL2ES2 gl) {
+        if(null != pmvMatrixUniform) {
+            pmvMatrixUniform = null;
+        }
+        if(null != pmvMatrix) {
+            pmvMatrix.destroy();
+            pmvMatrix=null;
+        }
+        if(null != interleavedVBO) {
+            interleavedVBO.destroy(gl);
+            interleavedVBO=null;
+        }
+        if(null != sp) {
+            sp.destroy(gl);
+            sp=null;
+        }
+    }
+
+    public void display(GL2ES2 gl) {
+        if(null != sp) {    
+            sp.useProgram(gl, true);               
+            interleavedVBO.enableBuffer(gl, true);
+            
+            gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+            
+            interleavedVBO.enableBuffer(gl, false);        
+            sp.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_quadTexCoords00 = { 
+        0f, 0f, // LB
+        1f, 0f, // RB
+        0f, 1f, // LT   
+        1f, 1f  // RT
+    };
+    private static final float[] s_quadTexCoords01 = { 
+        0f, 1f, // LB
+        1f, 1f, // RB
+        0f, 0f, // LT   
+        1f, 0f  // RT
+    };    
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
index cc58f23..f4f20ac 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
@@ -943,8 +943,8 @@ public class FixedFuncPipeline {
     private static final String constMaxTextures8 = "#define MAX_TEXTURE_UNITS 8\n";
     
     private final void customizeShader(GL2ES2 gl, ShaderCode vp, ShaderCode fp, String maxTextureDefine) {
-        int rsVpPos = vp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
-        int rsFpPos = fp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);        
+        int rsVpPos = vp.defaultShaderCustomization(gl, true, true);
+        int rsFpPos = fp.defaultShaderCustomization(gl, true, true);        
         vp.insertShaderSource(0, rsVpPos, maxTextureDefine);
         fp.insertShaderSource(0, rsFpPos, maxTextureDefine); 
     }
diff --git a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
new file mode 100644
index 0000000..833771d
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
@@ -0,0 +1,1542 @@
+/**
+ * Original JavaScript code from <https://github.com/notmasteryet/jpgjs/blob/master/jpg.js>,
+ * ported to Java for JogAmp Community.
+ * 
+ * Enhancements:
+ *  * InputStream instead of memory buffer
+ *  * User provided memory handler
+ *  * Fixed JPEG Component ID/Index mapping 
+ *  * Color space conversion (YCCK, CMYK -> RGB)
+ *  * More error tolerant
+ * 
+ * *****************
+ * 
+ * Copyright 2011 notmasteryet
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *  
+ * *****************
+ *  
+ * 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 jogamp.opengl.util.jpeg;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import jogamp.opengl.Debug;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureData.ColorSpace;
+
+/**
+ * 
+ * <ul>
+ *   <li> The JPEG specification can be found in the ITU CCITT Recommendation T.81
+ *        (www.w3.org/Graphics/JPEG/itu-t81.pdf) </li>
+ *   <li> The JFIF specification can be found in the JPEG File Interchange Format
+ *        (www.w3.org/Graphics/JPEG/jfif3.pdf)</li>
+ *   <li> The Adobe Application-Specific JPEG markers in the Supporting the DCT Filters
+ *        in PostScript Level 2, Technical Note #5116
+ *        (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)</li>
+ *   <li> http://halicery.com/jpeg/huffman.html </li>
+ *   <li> https://en.wikipedia.org/wiki/Jpg#Syntax_and_structure </li>
+ *   <li> http://www.cs.sfu.ca/CourseCentral/365/mark/material/notes/Chap4/Chap4.2/Chap4.2.html </li>
+ *   <li> https://github.com/notmasteryet/jpgjs/blob/master/jpg.js </li>
+ * </ul>
+ */
+public class JPEGDecoder {
+    private static final boolean DEBUG = Debug.debug("JPEGImage");
+    private static final boolean DEBUG_IN = false;
+
+    /** Allows user to hook a {@link ColorSink} to another toolkit to produce {@link TextureData}. */ 
+    public static interface ColorSink {
+        /**
+         * @param width
+         * @param height
+         * @param sourceCS the color-space of the decoded JPEG
+         * @param sourceComponents number of components used for the given source color-space
+         * @return Either {@link TextureData.ColorSpace#RGB} or {@link TextureData.ColorSpace#YCbCr}. {@link TextureData.ColorSpace#YCCK} and {@link TextureData.ColorSpace#CMYK} will throw an exception! 
+         * @throws RuntimeException
+         */
+        public TextureData.ColorSpace allocate(int width, int height, TextureData.ColorSpace sourceCS, int sourceComponents) throws RuntimeException;
+        public void store2(int x, int y, byte c1, byte c2);
+        public void storeRGB(int x, int y, byte r, byte g, byte b);
+        public void storeYCbCr(int x, int y, byte Y, byte Cb, byte Cr);        
+    }
+    
+    public static class JFIF {
+        final VersionNumber version;
+        final int densityUnits;
+        final int xDensity;
+        final int yDensity;
+        final int thumbWidth;
+        final int thumbHeight;
+        final byte[] thumbData;
+
+        private JFIF(final byte data[]) {
+            version = new VersionNumber(data[5], data[6], 0);
+            densityUnits = data[7];
+            xDensity = (data[8] << 8) | data[9];
+            yDensity = (data[10] << 8) | data[11];
+            thumbWidth = data[12];
+            thumbHeight = data[13];
+            if( 0 < thumbWidth && 0 < thumbHeight ) {
+                final int len = 14 + 3 * thumbWidth * thumbHeight;
+                thumbData = new byte[len];
+                System.arraycopy(data, 14, thumbData, 0, len);
+            } else {
+                thumbData = null;
+            }
+        }
+
+        public static final JFIF get(final byte[] data) throws RuntimeException {
+            if ( data[0] == (byte)0x4A && data[1] == (byte)0x46 && data[2] == (byte)0x49 &&
+                 data[3] == (byte)0x46 && data[4] == (byte)0x0) { // 'JFIF\x00'
+                final JFIF r = new JFIF(data);
+                return r;
+            } else {
+                return null;
+            }
+        }        
+
+        public final String toString() {
+            return "JFIF[ver "+version+", density[units "+densityUnits+", "+xDensity+"x"+yDensity+"], thumb "+thumbWidth+"x"+thumbHeight+"]";
+        }        
+    }
+
+    public static class Adobe {
+        final short version;
+        final short flags0;
+        final short flags1;
+        final short colorCode;
+        final ColorSpace colorSpace;
+        
+        private Adobe(final byte[] data) {
+            version = data[6];
+            flags0 = (short) ( (data[7] << 8) | data[8]  ) ;
+            flags1 = (short) ( (data[9] << 8) | data[10] ) ;
+            colorCode = data[11];
+            switch( colorCode ) {
+                case 2: colorSpace = ColorSpace.YCCK; break;
+                case 1: colorSpace = ColorSpace.YCbCr; break;
+                default: colorSpace = ColorSpace.CMYK; break;
+            }
+        }
+        public static final Adobe get(final byte[] data) throws RuntimeException {
+            if (data[0] == (byte)0x41 && data[1] == (byte)0x64 && data[2] == (byte)0x6F &&
+                data[3] == (byte)0x62 && data[4] == (byte)0x65 && data[5] == (byte)0) { // 'Adobe\x00'
+                final Adobe r = new Adobe(data);
+                return r;
+            } else {
+                return null;
+            }
+        }
+        public final String toString() {
+            return "Adobe[ver "+version+", flags["+toHexString(flags0)+", "+toHexString(flags1)+"], colorSpace/Code "+colorSpace+"/"+toHexString(colorCode)+"]";
+        }        
+    }
+    /** TODO */
+    public static class EXIF {
+        private EXIF(final byte data[]) {
+        }
+
+        public static final EXIF get(final byte[] data) throws RuntimeException {
+            if ( data[0] == (byte)0x45 && data[1] == (byte)0x78 && data[2] == (byte)0x69 &&
+                 data[3] == (byte)0x66 && data[4] == (byte)0x0) { // 'Exif\x00'
+                final EXIF r = new EXIF(data);
+                return r;
+            } else {
+                return null;
+            }
+        }        
+        public final String toString() {
+            return "EXIF[]";
+        }        
+    }
+
+    @SuppressWarnings("serial")
+    public static class CodecException extends RuntimeException {
+        CodecException(String message) {
+            super(message);
+        }
+    }
+    @SuppressWarnings("serial")
+    public static class MarkerException extends CodecException {
+        final int marker;
+        MarkerException(int marker, String message) {
+            super(message+" - Marker "+toHexString(marker));
+            this.marker = marker;
+        }
+        public int getMarker() { return marker; }
+    }
+        
+    /** Start of Image */
+    private static final int M_SOI   = 0xFFD8;
+    /** End of Image */
+    private static final int M_EOI   = 0xFFD9;
+    /** Start of Frame - Baseline DCT */
+    private static final int M_SOF0  = 0xFFC0;
+    /** Start of Frame - Extended sequential DCT */
+    // private static final int M_SOF1  = 0xFFC1;
+    /** Start of Frame - Progressive DCT */
+    private static final int M_SOF2  = 0xFFC2;
+    /** DHT (Define Huffman Tables) */
+    private static final int M_DHT   = 0xFFC4;
+    // private static final int M_DAC   = 0xFFCC;
+    /** SOS (Start of Scan) */
+    private static final int M_SOS   = 0xFFDA;
+    /** DQT (Define Quantization Tables) */
+    private static final int M_QTT   = 0xFFDB;
+    /** DRI (Define Restart Interval) */
+    private static final int M_DRI   = 0xFFDD;
+    /** APP0 (Application Specific) - JFIF Header */
+    private static final int M_APP00 = 0xFFE0;
+    /** APP1 (Application Specific) - Exif Header */
+    private static final int M_APP01 = 0xFFE1;
+    /** APP2 (Application Specific) */
+    private static final int M_APP02 = 0xFFE2;
+    /** APP3 (Application Specific) */
+    private static final int M_APP03 = 0xFFE3;
+    /** APP4 (Application Specific) */
+    private static final int M_APP04 = 0xFFE4;
+    /** APP5 (Application Specific) */
+    private static final int M_APP05 = 0xFFE5;
+    /** APP6 (Application Specific) */
+    private static final int M_APP06 = 0xFFE6;
+    /** APP7 (Application Specific) */
+    private static final int M_APP07 = 0xFFE7;
+    /** APP8 (Application Specific) */
+    private static final int M_APP08 = 0xFFE8;
+    /** APP9 (Application Specific) */
+    private static final int M_APP09 = 0xFFE9;
+    /** APP10 (Application Specific) */
+    private static final int M_APP10 = 0xFFEA;
+    /** APP11 (Application Specific) */
+    private static final int M_APP11 = 0xFFEB;
+    /** APP12 (Application Specific) */
+    private static final int M_APP12 = 0xFFEC;
+    /** APP13 (Application Specific) */
+    private static final int M_APP13 = 0xFFED;
+    /** APP14 (Application Specific) - ADOBE Header */
+    private static final int M_APP14 = 0xFFEE;
+    /** APP15 (Application Specific) */
+    private static final int M_APP15 = 0xFFEF;
+
+    /** Annotation / Comment */
+    private static final int M_ANO   = 0xFFFE;    
+    
+    static final int[] dctZigZag = new int[] {
+        0,
+        1,  8,
+        16,  9,  2,
+        3, 10, 17, 24,
+        32, 25, 18, 11, 4,
+        5, 12, 19, 26, 33, 40,
+        48, 41, 34, 27, 20, 13,  6,
+        7, 14, 21, 28, 35, 42, 49, 56,
+        57, 50, 43, 36, 29, 22, 15,
+        23, 30, 37, 44, 51, 58,
+        59, 52, 45, 38, 31,
+        39, 46, 53, 60,
+        61, 54, 47,
+        55, 62,
+        63
+    };
+
+    static final int dctCos1  =   4017;   // cos(pi/16)
+    static final int dctSin1  =    799;   // sin(pi/16)
+    static final int dctCos3  =   3406;   // cos(3*pi/16)
+    static final int dctSin3  =   2276;   // sin(3*pi/16)
+    static final int dctCos6  =   1567;   // cos(6*pi/16)
+    static final int dctSin6  =   3784;   // sin(6*pi/16)
+    static final int dctSqrt2 =   5793;   // sqrt(2)
+    static final int dctSqrt1d2 = 2896;   // sqrt(2) / 2
+
+    static class Frame {
+        final boolean progressive;
+        final int precision;
+        final int scanLines;
+        final int samplesPerLine;
+        private final ArrayHashSet<Integer> compIDs;
+        private final ComponentIn[] comps;
+        private final int compCount;
+        /** quantization tables */
+        final int[][] qtt;
+        int maxCompID;
+        int maxH;
+        int maxV;
+        int mcusPerLine;
+        int mcusPerColumn;
+
+        Frame(boolean progressive, int precision, int scanLines, int samplesPerLine, int componentsCount, int[][] qtt) {
+            this.progressive = progressive;
+            this.precision = precision;
+            this.scanLines = scanLines;
+            this.samplesPerLine = samplesPerLine;
+            compIDs = new ArrayHashSet<Integer>(componentsCount);
+            comps = new ComponentIn[componentsCount];
+            this.compCount = componentsCount;
+            this.qtt = qtt;
+        }
+
+        private final void checkBounds(int idx) {
+            if( 0 > idx || idx >= compCount ) {
+                throw new CodecException("Idx out of bounds "+idx+", "+this);
+            }            
+        }
+        public final void validateComponents() {
+            for(int i=0; i<compCount; i++) {
+                final ComponentIn c = comps[i];
+                if( null == c ) {
+                    throw new CodecException("Component["+i+"] null");
+                }
+                if( null == this.qtt[c.qttIdx] ) {
+                    throw new CodecException("Component["+i+"].qttIdx -> null QTT");
+                }
+            }
+        }
+
+        public final int getCompCount() { return compCount; }
+        public final int getMaxCompID() { return maxCompID; }
+
+        public final void putOrdered(int compID, ComponentIn component) {
+            if( maxCompID < compID ) {
+                maxCompID = compID;
+            }
+            final int idx = compIDs.size();
+            checkBounds(idx);
+            compIDs.add(compID);
+            comps[idx] = component;
+        }
+        public final ComponentIn getCompByIndex(int i) {
+            checkBounds(i);
+            return comps[i];
+        }
+        public final ComponentIn getCompByID(int componentID) {
+            return getCompByIndex( compIDs.indexOf(componentID) );
+        }
+        public final int getCompID(int idx) {
+            return compIDs.get(idx);
+        }
+        public final boolean hasCompID(int componentID) {
+            return compIDs.contains(componentID);
+        }
+        public final String toString() {
+            return "Frame[progressive "+progressive+", precision "+precision+", scanLines "+scanLines+", samplesPerLine "+samplesPerLine+
+                    ", components[count "+compCount+", maxID "+maxCompID+", componentIDs "+compIDs+", comps "+Arrays.asList(comps)+"]]";
+        }
+    }
+
+    /** The JPEG encoded components */
+    class ComponentIn {
+        final int h, v;
+        /** index to frame.qtt[] */
+        final int qttIdx;
+        int blocksPerColumn;
+        int blocksPerColumnForMcu;
+        int blocksPerLine;
+        int blocksPerLineForMcu;
+        /** [blocksPerColumnForMcu][blocksPerLineForMcu][64]; */
+        int[][][] blocks; 
+        int pred;
+        BinObj huffmanTableAC;
+        BinObj huffmanTableDC;
+
+        ComponentIn(int h, int v, int qttIdx) {
+            this.h = h;
+            this.v = v;
+            this.qttIdx = qttIdx;
+        }
+
+        public final void allocateBlocks(int blocksPerColumn, int blocksPerColumnForMcu, int blocksPerLine, int blocksPerLineForMcu) {
+            this.blocksPerColumn = blocksPerColumn;
+            this.blocksPerColumnForMcu = blocksPerColumnForMcu;
+            this.blocksPerLine = blocksPerLine;
+            this.blocksPerLineForMcu = blocksPerLineForMcu;
+            this.blocks = new int[blocksPerColumnForMcu][blocksPerLineForMcu][64];
+        }
+        public final int[] getBlock(int row, int col) {
+            if( row >= blocksPerColumnForMcu || col >= blocksPerLineForMcu ) {
+                throw new CodecException("Out of bounds given ["+row+"]["+col+"] - "+this);
+            }
+            return blocks[row][col];            
+        }
+        
+        public final String toString() {
+            return "CompIn[h "+h+", v "+v+", qttIdx "+qttIdx+", blocks["+blocksPerColumn+", mcu "+blocksPerColumnForMcu+"]["+blocksPerLine+", mcu "+blocksPerLineForMcu+"][64]]";
+        }
+    }
+
+    /** The decoded components */
+    class ComponentOut {
+        private final ArrayList<byte[]> lines; 
+        final float scaleX;
+        final float scaleY;
+
+        ComponentOut(ArrayList<byte[]> lines, float scaleX, float scaleY) {
+            this.lines = lines;
+            this.scaleX = scaleX;
+            this.scaleY = scaleY;
+        }
+        
+        /** Safely returning a line, if index exceeds number of lines, last line is returned. */
+        public final byte[] getLine(int i) {
+            final int sz = lines.size();
+            return lines.get( i < sz ? i : sz - 1);
+        }
+        
+        public final String toString() {
+            return "CompOut[lines "+lines.size()+", scale "+scaleX+"x"+scaleY+"]";
+        }
+    }
+
+    public String toString() {
+        final String jfifS = null != jfif ? jfif.toString() : "JFIF nil";
+        final String exifS = null != exif ? exif.toString() : "Exif nil";
+        final String adobeS = null != adobe ? adobe.toString() : "Adobe nil";
+        final String compOuts = null != components ? Arrays.asList(components).toString() : "nil";
+        return "JPEG[size "+width+"x"+height+", compOut "+compOuts+", "+jfifS+", "+exifS+", "+adobeS+"]";
+    }
+
+    private BufferedInputStream istream;
+    private int _ipos = 0;
+    private int _iposSave = 0;
+    
+    private int width = 0;
+    private int height = 0;
+    private JFIF jfif = null;
+    private EXIF exif = null;
+    private Adobe adobe = null;
+    private ComponentOut[] components = null;
+
+    public final JFIF getJFIFHeader() { return jfif; }
+    public final EXIF getEXIFHeader() { return exif; }
+    public final Adobe getAdobeHeader() { return adobe; }
+    public final int getWidth() { return width; }
+    public final int getHeight() { return height; }
+
+    private final void resetInput(InputStream is) {
+        if( is instanceof BufferedInputStream ) { 
+            istream = (BufferedInputStream) is;
+        } else {
+            istream = new BufferedInputStream(is);
+        }
+        _ipos = 0;
+    }
+    
+    private final void markStream(int readLimit) {
+        istream.mark(readLimit);
+        _iposSave = _ipos;
+    }
+    private final void rewindStream() throws IOException {
+        if(DEBUG_IN) { System.err.println("JPG.rewindStream: "+_ipos+" -> "+_iposSave); }
+        istream.reset();
+        _ipos = _iposSave;
+        _iposSave = 0;
+    }
+    private final int readUint8() throws IOException {
+        final int r = istream.read();
+        if( -1 < r ) {
+            if(DEBUG_IN) { System.err.println("u8["+_ipos+"]: "+toHexString(r)); }
+            _ipos++;
+        } else if(DEBUG_IN) { 
+            System.err.println("u8["+_ipos+"]: EOS");
+        }
+        return r;
+    }
+
+    private final int readUint16() throws IOException {
+        final int hi = istream.read();
+        if( -1 < hi ) {
+            _ipos++;
+            final int lo = istream.read();
+            if( -1 < lo ) {
+                _ipos++;
+                final int r = hi << 8 | lo ;
+                if(DEBUG_IN) { System.err.println("u16["+(_ipos-2)+"]: "+toHexString(r)); }
+                return r;
+            }
+        }
+        if(DEBUG_IN) { System.err.println("u16["+_ipos+"]: EOS"); }
+        return -1;
+    }
+
+    private final int readNumber() throws IOException {
+        final int len=readUint16();
+        if(len!=4){
+            throw new CodecException("ERROR: Define number format error [Len!=4, but "+len+"]");
+        }
+        return readUint16();
+    }
+
+    private final byte[] readDataBlock() throws IOException {
+        int count=0, i=0;
+        final int len=readUint16();   count+=2;
+        byte[] data = new byte[len-2];
+        while(count<len){
+            data[i++] = (byte)readUint8(); count++;
+        }
+        if(DEBUG_IN) { System.err.println("JPEG.readDataBlock: net-len "+(len-2)+", "+this); dumpData(data, 0, len-2); }
+        return data;
+    }       
+    static final void dumpData(byte[] data, int offset, int len) {
+        for(int i=0; i<len; ) {
+            System.err.print(i%8+": ");
+            for(int j=0; j<8 && i<len; j++, i++) {
+                System.err.println(toHexString(0x000000FF & data[offset+i])+", ");
+            }
+            System.err.println("");
+        }        
+    }                
+
+    public synchronized void clear(InputStream inputStream) {
+        resetInput(inputStream);
+        width = 0;
+        height = 0;
+        jfif = null;
+        exif = null;
+        adobe = null;        
+        components = null;        
+    }
+    public synchronized JPEGDecoder parse(final InputStream inputStream) throws IOException {        
+        clear(inputStream);
+        
+        final int[][] quantizationTables = new int[0x0F][]; // 4 bits
+        final BinObj[] huffmanTablesAC = new BinObj[0x0F]; // Huffman table spec - 4 bits
+        final BinObj[] huffmanTablesDC = new BinObj[0x0F]; // Huffman table spec - 4 bits
+        // final ArrayList<Frame> frames = new ArrayList<Frame>(); // JAU: max 1-frame
+        
+        Frame frame = null;
+        int resetInterval = 0;
+        int fileMarker = readUint16();
+        if ( fileMarker != M_SOI ) {
+            throw new CodecException("SOI not found, but has marker "+toHexString(fileMarker));
+        }
+
+        fileMarker = readUint16();
+        while (fileMarker != M_EOI) {
+            if(DEBUG) { System.err.println("JPG.parse got marker "+toHexString(fileMarker)); }
+            switch(fileMarker) {
+            case M_APP00:
+            case M_APP01:
+            case M_APP02:
+            case M_APP03:
+            case M_APP04:
+            case M_APP05:
+            case M_APP06:
+            case M_APP07:
+            case M_APP08:
+            case M_APP09:
+            case M_APP10:
+            case M_APP11:
+            case M_APP12:
+            case M_APP13:
+            case M_APP14:
+            case M_APP15:
+            case M_ANO: {
+                final byte[] appData = readDataBlock();
+
+                if ( fileMarker == M_APP00 ) {
+                    jfif = JFIF.get( appData );
+                }
+                if ( fileMarker == M_APP01 ) {
+                    exif = EXIF.get(appData);
+                }
+                if (fileMarker == M_APP14) {
+                    adobe = Adobe.get(appData);
+                }
+                fileMarker = 0; // consumed and get-next
+            }
+            break;
+
+            case M_QTT: {
+                int count = 0;
+                final int quantizationTablesLength = readUint16(); count+=2;
+                while( count < quantizationTablesLength ) {
+                    final int quantizationTableSpec = readUint8(); count++;
+                    final int precisionID = quantizationTableSpec >> 4;
+                    final int tableIdx = quantizationTableSpec & 0x0F;
+                    final int[] tableData = new int[64];
+                    if ( precisionID == 0 ) { // 8 bit values
+                        for (int j = 0; j < 64; j++) {
+                            final int z = dctZigZag[j];
+                            tableData[z] = readUint8(); count++;
+                        }
+                    } else if ( precisionID == 1) { //16 bit
+                        for (int j = 0; j < 64; j++) {
+                            final int z = dctZigZag[j];
+                            tableData[z] = readUint16(); count+=2;
+                        }
+                    } else {
+                        throw new CodecException("DQT: invalid table precision "+precisionID+", quantizationTableSpec "+quantizationTableSpec+", idx "+tableIdx);
+                    }
+                    quantizationTables[tableIdx] = tableData;
+                    if( DEBUG ) {
+                        System.err.println("JPEG.parse.QTT["+tableIdx+"]: spec "+quantizationTableSpec+", precision "+precisionID+", data "+count+"/"+quantizationTablesLength);
+                    }                    
+                }
+                if(count!=quantizationTablesLength){
+                    throw new CodecException("ERROR: QTT format error [count!=Length]: "+count+"/"+quantizationTablesLength);
+                }
+                fileMarker = 0; // consumed and get-next
+            }
+            break;
+
+            case M_SOF0:
+            case M_SOF2: {
+                if( null != frame ) { // JAU: max 1-frame
+                    throw new CodecException("only single frame JPEGs supported");
+                }
+                int count = 0;
+                final int sofLen = readUint16(); count+=2; // header length;
+                final int componentsCount;
+                {
+                    final boolean progressive = (fileMarker == M_SOF2);
+                    final int precision = readUint8(); count++;
+                    final int scanLines = readUint16(); count+=2;
+                    final int samplesPerLine = readUint16(); count+=2;
+                    componentsCount = readUint8(); count++;
+                    frame = new Frame(progressive, precision, scanLines, samplesPerLine, componentsCount, quantizationTables);
+                    width = frame.samplesPerLine;
+                    height = frame.scanLines;
+                }
+                for (int i = 0; i < componentsCount; i++) {
+                    final int componentId = readUint8(); count++;
+                    final int temp = readUint8(); count++;
+                    final int h = temp >> 4;
+                    final int v = temp & 0x0F;
+                    final int qttIdx = readUint8(); count++;
+                    final ComponentIn compIn = new ComponentIn(h, v, qttIdx);
+                    frame.putOrdered(componentId, compIn);
+                }
+                if(count!=sofLen){
+                    throw new CodecException("ERROR: SOF format error [count!=Length]");
+                }
+                prepareComponents(frame);
+                // frames.add(frame); // JAU: max 1-frame
+                if(DEBUG) { System.err.println("JPG.parse.SOF[02]: Got frame "+frame); }
+                fileMarker = 0; // consumed and get-next
+            }
+            break;
+
+            case M_DHT: { 
+                int count = 0;
+                final int huffmanLength = readUint16(); count+=2;
+                int i=count, codeLengthTotal = 0;
+                while( i < huffmanLength ) {
+                    final int huffmanTableSpec = readUint8(); count++;
+                    final int[] codeLengths = new int[16];
+                    int codeLengthSum = 0;
+                    for (int j = 0; j < 16; j++) {
+                        codeLengthSum += (codeLengths[j] = readUint8()); count++;
+                    }
+                    final byte[] huffmanValues = new byte[codeLengthSum];
+                    for (int j = 0; j < codeLengthSum; j++) {
+                        huffmanValues[j] = (byte)readUint8(); count++;
+                    }
+                    codeLengthTotal += codeLengthSum; 
+                    i += 17 + codeLengthSum;
+                    final BinObj[] table = ( huffmanTableSpec >> 4 ) == 0 ? huffmanTablesDC : huffmanTablesAC;
+                    table[huffmanTableSpec & 0x0F] = buildHuffmanTable(codeLengths, huffmanValues);
+                }
+                if(count!=huffmanLength || i!=count){
+                    throw new CodecException("ERROR: Huffman table format error [count!=Length]");
+                }
+                if(DEBUG) { System.err.println("JPG.parse.DHT: Got Huffman CodeLengthTotal "+codeLengthTotal); }
+                fileMarker = 0; // consumed and get-next
+            }
+            break;
+
+            case M_DRI:
+                resetInterval = readNumber();
+                if(DEBUG) { System.err.println("JPG.parse.DRI: Got Reset Interval "+resetInterval); }
+                fileMarker = 0; // consumed and get-next
+                break;
+
+            case M_SOS: {
+                int count = 0;
+                final int sosLen = readUint16(); count+=2;
+                final int selectorsCount = readUint8(); count++;
+                ArrayList<ComponentIn> components = new ArrayList<ComponentIn>();
+                if(DEBUG) { System.err.println("JPG.parse.SOS: selectorCount [0.."+(selectorsCount-1)+"]: "+frame); }                                
+                for (int i = 0; i < selectorsCount; i++) {
+                    final int compID = readUint8(); count++;
+                    final ComponentIn component = frame.getCompByID(compID);
+                    final int tableSpec = readUint8(); count++;
+                    component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
+                    component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
+                    components.add(component);
+                }
+                final int spectralStart = readUint8(); count++;
+                final int spectralEnd = readUint8(); count++;
+                final int successiveApproximation = readUint8(); count++;
+                if(count!=sosLen){
+                    throw new CodecException("ERROR: scan header format error [count!=Length]");
+                }
+                fileMarker = decoder.decodeScan(frame, components, resetInterval,
+                                                spectralStart, spectralEnd,
+                                                successiveApproximation >> 4, successiveApproximation & 15);
+                if(DEBUG) { System.err.println("JPG.parse.SOS.decode result "+toHexString(fileMarker)); }
+            }
+            break;
+            default:
+                /**
+                if (data[offset - 3] == 0xFF &&
+                data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) {
+                    // could be incorrect encoding -- last 0xFF byte of the previous
+                    // block was eaten by the encoder
+                    offset -= 3;
+                    break;
+                } */
+                throw new CodecException("unknown JPEG marker " + toHexString(fileMarker));
+            }
+            if( 0 == fileMarker ) {
+                fileMarker = readUint16();
+            }
+        }
+        if(DEBUG) { System.err.println("JPG.parse.2: End of parsing input "+this); }
+        /** // JAU: max 1-frame
+        if ( frames.size() != 1 ) {
+            throw new CodecException("only single frame JPEGs supported "+this);
+        } */
+        if( null == frame ) {
+            throw new CodecException("no single frame found in stream "+this);
+        }
+        frame.validateComponents();
+
+        final int compCount = frame.getCompCount();
+        this.components = new ComponentOut[compCount];
+        for (int i = 0; i < compCount; i++) {
+            final ComponentIn component = frame.getCompByIndex(i);
+            // System.err.println("JPG.parse.buildComponentData["+i+"]: "+component); // JAU
+            // System.err.println("JPG.parse.buildComponentData["+i+"]: "+frame); // JAU
+            this.components[i] = new ComponentOut( output.buildComponentData(frame, component), 
+                                                   (float)component.h / (float)frame.maxH, 
+                                                   (float)component.v / (float)frame.maxV );
+        }
+        if(DEBUG) { System.err.println("JPG.parse.X: End of processing input "+this); }
+        return this;
+    }
+
+    private void prepareComponents(Frame frame) {
+        int maxH = 0, maxV = 0;
+        // for (componentId in frame.components) {
+        final int compCount = frame.getCompCount();
+        for (int i=0; i<compCount; i++) {
+            final ComponentIn component = frame.getCompByIndex(i);
+            if (maxH < component.h) maxH = component.h;
+            if (maxV < component.v) maxV = component.v;
+        }
+        int mcusPerLine = (int) Math.ceil((float)frame.samplesPerLine / 8f / (float)maxH);
+        int mcusPerColumn = (int) Math.ceil((float)frame.scanLines / 8f / (float)maxV);
+        // for (componentId in frame.components) {
+        for (int i=0; i<compCount; i++) {
+            final ComponentIn component = frame.getCompByIndex(i);
+            final int blocksPerLine = (int) Math.ceil(Math.ceil((float)frame.samplesPerLine / 8f) * component.h / maxH);
+            final int blocksPerColumn = (int) Math.ceil(Math.ceil((float)frame.scanLines  / 8f) * component.v / maxV);
+            final int blocksPerLineForMcu = mcusPerLine * component.h;
+            final int blocksPerColumnForMcu = mcusPerColumn * component.v;
+            component.allocateBlocks(blocksPerColumn, blocksPerColumnForMcu, blocksPerLine, blocksPerLineForMcu);
+        }
+        frame.maxH = maxH;
+        frame.maxV = maxV;
+        frame.mcusPerLine = mcusPerLine;
+        frame.mcusPerColumn = mcusPerColumn;
+    }
+
+    private static class BinObjIdxed {
+        final BinObj children;
+        byte index;
+        BinObjIdxed() {
+            this.children = new BinObj();
+            this.index = 0;
+        }
+    }
+    private static class BinObj {
+        final boolean isValue;
+        final BinObj[] tree;
+        final byte b;
+        
+        BinObj(byte b) {
+            this.isValue= true;
+            this.b = b;
+            this.tree = null;
+        }
+        BinObj() {
+            this.isValue= false;
+            this.b = (byte)0;
+            this.tree = new BinObj[2];
+        }
+        final byte getValue() { return b; }
+        final BinObj get(int i) { return tree[i]; }
+        final void set(byte i, byte v) { tree[i] = new BinObj(v); }
+        final void set(byte i, BinObj v) { tree[i] = v; }
+    }
+
+    private BinObj buildHuffmanTable(int[] codeLengths, byte[] values) {
+        int k = 0;      
+        int length = 16;      
+        final ArrayList<BinObjIdxed> code = new ArrayList<BinObjIdxed>();
+        while (length > 0 && 0==codeLengths[length - 1]) {
+            length--;
+        }
+        code.add(new BinObjIdxed());        
+        BinObjIdxed p = code.get(0), q;
+        for (int i = 0; i < length; i++) {
+            for (int j = 0; j < codeLengths[i]; j++) {
+                p = code.remove(code.size()-1);
+                p.children.set(p.index, values[k]);
+                while (p.index > 0) {
+                    p = code.remove(code.size()-1);
+                }
+                p.index++;
+                code.add(p);
+                while (code.size() <= i) {
+                    q = new BinObjIdxed();
+                    code.add(q);
+                    p.children.set(p.index, q.children);
+                    p = q;
+                }
+                k++;
+            }
+            if (i + 1 < length) {
+                // p here points to last code
+                q = new BinObjIdxed();
+                code.add(q);
+                p.children.set(p.index, q.children);
+                p = q;
+            }
+        }
+        return code.get(0).children;
+    }
+
+    private final Output output = new Output();
+    private static class Output {
+        private int blocksPerLine;
+        private int blocksPerColumn;
+        private int samplesPerLine;
+
+        private ArrayList<byte[]> buildComponentData(Frame frame, ComponentIn component) {
+            ArrayList<byte[]> lines = new ArrayList<byte[]>();
+            blocksPerLine = component.blocksPerLine;
+            blocksPerColumn = component.blocksPerColumn;
+            samplesPerLine = blocksPerLine << 3;
+            final int[] R = new int[64];
+            final byte[] r = new byte[64];
+
+            for (int blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
+                final int scanLine = blockRow << 3;
+                // System.err.println("JPG.buildComponentData: row "+blockRow+"/"+blocksPerColumn+" -> scanLine "+scanLine); // JAU
+                for (int i = 0; i < 8; i++) {
+                    lines.add(new byte[samplesPerLine]);
+                }
+                for (int blockCol = 0; blockCol < blocksPerLine; blockCol++) {
+                    // System.err.println("JPG.buildComponentData: col "+blockCol+"/"+blocksPerLine+", comp.qttIdx "+component.qttIdx+", qtt "+frame.qtt[component.qttIdx]); // JAU
+                    quantizeAndInverse(component.getBlock(blockRow, blockCol), r, R, frame.qtt[component.qttIdx]);
+
+                    final int sample = blockCol << 3;
+                    int offset = 0;
+                    for (int j = 0; j < 8; j++) {
+                        final byte[] line = lines.get(scanLine + j);
+                        for (int i = 0; i < 8; i++)
+                            line[sample + i] = r[offset++];
+                    }
+                }
+            }
+            return lines;
+        }
+
+        // A port of poppler's IDCT method which in turn is taken from:
+        //   Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
+        //   "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
+        //   IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
+        //   988-991.
+        private void quantizeAndInverse(int[] zz, byte[] dataOut, int[] dataIn, int[] qt) {
+            int v0, v1, v2, v3, v4, v5, v6, v7, t;
+            int[] p = dataIn;
+            int i;
+
+            // dequant
+            for (i = 0; i < 64; i++) {
+                p[i] = zz[i] * qt[i];
+            }
+
+            // inverse DCT on rows
+            for (i = 0; i < 8; ++i) {
+                int row = 8 * i;
+
+                // check for all-zero AC coefficients
+                if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 &&
+                        p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 &&
+                        p[7 + row] == 0) {
+                    t = (dctSqrt2 * p[0 + row] + 512) >> 10;
+                    p[0 + row] = t;
+                    p[1 + row] = t;
+                    p[2 + row] = t;
+                    p[3 + row] = t;
+                    p[4 + row] = t;
+                    p[5 + row] = t;
+                    p[6 + row] = t;
+                    p[7 + row] = t;
+                    continue;
+                }
+
+                // stage 4
+                v0 = (dctSqrt2 * p[0 + row] + 128) >> 8;
+                        v1 = (dctSqrt2 * p[4 + row] + 128) >> 8;
+                v2 = p[2 + row];
+                v3 = p[6 + row];
+                v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8;
+                v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8;
+                v5 = p[3 + row] << 4;
+                v6 = p[5 + row] << 4;
+
+                // stage 3
+                t = (v0 - v1+ 1) >> 1;
+                v0 = (v0 + v1 + 1) >> 1;
+                v1 = t;
+                t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
+                v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
+                v3 = t;
+                t = (v4 - v6 + 1) >> 1;
+                v4 = (v4 + v6 + 1) >> 1;
+                v6 = t;
+                t = (v7 + v5 + 1) >> 1;
+                v5 = (v7 - v5 + 1) >> 1;
+                v7 = t;
+
+                // stage 2
+                t = (v0 - v3 + 1) >> 1;
+                v0 = (v0 + v3 + 1) >> 1;
+                v3 = t;
+                t = (v1 - v2 + 1) >> 1;
+                v1 = (v1 + v2 + 1) >> 1;
+                v2 = t;
+                t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
+                v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
+                v7 = t;
+                t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
+                v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
+                v6 = t;
+    
+                // stage 1
+                p[0 + row] = v0 + v7;
+                p[7 + row] = v0 - v7;
+                p[1 + row] = v1 + v6;
+                p[6 + row] = v1 - v6;
+                p[2 + row] = v2 + v5;
+                p[5 + row] = v2 - v5;
+                p[3 + row] = v3 + v4;
+                p[4 + row] = v3 - v4;
+            }
+
+            // inverse DCT on columns
+            for (i = 0; i < 8; ++i) {
+                int col = i;
+
+                // check for all-zero AC coefficients
+                if (p[1*8 + col] == 0 && p[2*8 + col] == 0 && p[3*8 + col] == 0 &&
+                        p[4*8 + col] == 0 && p[5*8 + col] == 0 && p[6*8 + col] == 0 &&
+                        p[7*8 + col] == 0) {
+                    t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
+                    p[0*8 + col] = t;
+                    p[1*8 + col] = t;
+                    p[2*8 + col] = t;
+                    p[3*8 + col] = t;
+                    p[4*8 + col] = t;
+                    p[5*8 + col] = t;
+                    p[6*8 + col] = t;
+                    p[7*8 + col] = t;
+                    continue;
+                }
+
+                // stage 4
+                v0 = (dctSqrt2 * p[0*8 + col] + 2048) >> 12;
+                v1 = (dctSqrt2 * p[4*8 + col] + 2048) >> 12;
+                v2 = p[2*8 + col];
+                v3 = p[6*8 + col];
+                v4 = (dctSqrt1d2 * (p[1*8 + col] - p[7*8 + col]) + 2048) >> 12;
+                v7 = (dctSqrt1d2 * (p[1*8 + col] + p[7*8 + col]) + 2048) >> 12;
+                v5 = p[3*8 + col];
+                v6 = p[5*8 + col];
+
+                // stage 3
+                t = (v0 - v1 + 1) >> 1;
+                v0 = (v0 + v1 + 1) >> 1;
+                v1 = t;
+                t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
+                v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
+                v3 = t;
+                t = (v4 - v6 + 1) >> 1;
+                v4 = (v4 + v6 + 1) >> 1;
+                v6 = t;
+                t = (v7 + v5 + 1) >> 1;
+                v5 = (v7 - v5 + 1) >> 1;
+                v7 = t;
+
+                // stage 2
+                t = (v0 - v3 + 1) >> 1;
+                v0 = (v0 + v3 + 1) >> 1;
+                v3 = t;
+                t = (v1 - v2 + 1) >> 1;
+                v1 = (v1 + v2 + 1) >> 1;
+                v2 = t;
+                t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
+                v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
+                v7 = t;
+                t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
+                v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
+                v6 = t;
+
+                // stage 1
+                p[0*8 + col] = v0 + v7;
+                p[7*8 + col] = v0 - v7;
+                p[1*8 + col] = v1 + v6;
+                p[6*8 + col] = v1 - v6;
+                p[2*8 + col] = v2 + v5;
+                p[5*8 + col] = v2 - v5;
+                p[3*8 + col] = v3 + v4;
+                p[4*8 + col] = v3 - v4;
+            }
+
+            // convert to 8-bit integers
+            for (i = 0; i < 64; ++i) {
+                int sample = 128 + ((p[i] + 8) >> 4);
+                dataOut[i] = (byte) ( sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample );
+            }
+        }
+    }
+
+    private static interface DecoderFunction {
+        void decode(ComponentIn component, int[] zz) throws IOException;
+    }
+
+    private class Decoder {
+        // private int precision;
+        // private int samplesPerLine;
+        // private int scanLines;
+        private int mcusPerLine;
+        private boolean progressive;
+        // private int maxH, maxV;
+        private int bitsData, bitsCount;
+        private int spectralStart, spectralEnd;
+        private int successive;
+        private int eobrun;
+        private int successiveACState, successiveACNextValue;
+
+        private int decodeScan(Frame frame, ArrayList<ComponentIn> components, int resetInterval,
+                int spectralStart, int spectralEnd, int successivePrev, int successive) throws IOException { 
+            // this.precision = frame.precision;
+            // this.samplesPerLine = frame.samplesPerLine;
+            // this.scanLines = frame.scanLines;
+            this.mcusPerLine = frame.mcusPerLine;
+            this.progressive = frame.progressive;
+            // this.maxH = frame.maxH;
+            // this.maxV = frame.maxV;
+            this.bitsData = 0;
+            this.bitsCount = 0;
+            this.spectralStart = spectralStart;
+            this.spectralEnd = spectralEnd;
+            this.successive = successive;
+            
+            final int componentsLength = components.size();
+
+            final DecoderFunction decodeFn;
+            if (progressive) {
+                if (spectralStart == 0) {
+                    decodeFn = successivePrev == 0 ? decodeDCFirst : decodeDCSuccessive;
+                } else {
+                    decodeFn = successivePrev == 0 ? decodeACFirst : decodeACSuccessive;
+                }
+            } else {
+                decodeFn = decodeBaseline;
+            }
+
+            int mcu = 0;
+            int mcuExpected;
+            if (componentsLength == 1) {
+                final ComponentIn c = components.get(0);            
+                mcuExpected = c.blocksPerLine * c.blocksPerColumn;
+            } else {
+                mcuExpected = mcusPerLine * frame.mcusPerColumn;
+            }
+            if (0 == resetInterval) {
+                resetInterval = mcuExpected;
+            }
+            if(DEBUG) {
+                System.err.println("JPEG.decodeScan.1 resetInterval "+resetInterval+", mcuExpected "+mcuExpected+", sA "+spectralStart+", sP "+successivePrev+", sE "+spectralEnd+", suc "+successive+", decodeFn "+decodeFn.getClass().getSimpleName());
+            }
+            int marker = 0;
+            while ( /* untilMarker || */ mcu < mcuExpected) {
+                // reset interval stuff
+                for (int i = 0; i < componentsLength; i++) {
+                    components.get(i).pred = 0;
+                }
+                eobrun = 0;
+
+                try {
+                    if (componentsLength == 1) {
+                        final ComponentIn component = components.get(0);
+                        for (int n = 0; n < resetInterval; n++) {
+                            decodeBlock(component, decodeFn, mcu);
+                            mcu++;
+                        }
+                    } else {
+                        for (int n = 0; n < resetInterval; n++) {
+                            for (int i = 0; i < componentsLength; i++) {
+                                final ComponentIn component = components.get(i);
+                                final int h = component.h;
+                                final int v = component.v;
+                                for (int j = 0; j < v; j++) {
+                                    for (int k = 0; k < h; k++) {
+                                        decodeMcu(component, decodeFn, mcu, j, k);
+                                    }
+                                }
+                            }
+                            mcu++;
+                        }
+                    }
+                } catch (MarkerException markerException) {
+                    if(DEBUG) { System.err.println("JPEG.decodeScan: Marker exception: "+markerException.getMessage()); markerException.printStackTrace(); }
+                    return markerException.getMarker();
+                } catch (CodecException codecException) {
+                    if(DEBUG) { System.err.println("JPEG.decodeScan: Codec exception: "+codecException.getMessage()); codecException.printStackTrace(); }
+                    bitsCount = 0;
+                    return M_EOI; // force end !
+                }
+
+                // find marker
+                bitsCount = 0;
+                markStream(2);
+                marker = readUint16();
+                if( marker < 0xFF00 ) {
+                    rewindStream();
+                    throw new CodecException("marker not found @ mcu "+mcu+"/"+mcuExpected+", u16: "+toHexString(marker));
+                }                
+                final boolean isRSTx = 0xFFD0 <= marker && marker <= 0xFFD7; // !RSTx
+                if(DEBUG) {
+                    System.err.println("JPEG.decodeScan: MCUs "+mcu+"/"+mcuExpected+", u16 "+toHexString(marker)+", RSTx "+isRSTx+", "+frame);
+                }
+                if ( !isRSTx ) {
+                    break; // handle !RSTx marker in caller
+                }                
+            }
+            return marker;
+        }
+
+        private int readBit() throws MarkerException, IOException {
+            if (bitsCount > 0) {
+                bitsCount--;
+                return (bitsData >> bitsCount) & 1;
+            }
+            bitsData = readUint8();
+            if( -1 == bitsData ) {
+                return -1;
+            }
+            if (bitsData == 0xFF) { // marker prefix
+                final int nextByte = readUint8(); // marker signature
+                if( -1 == nextByte ) {
+                    throw new CodecException("marked prefix 0xFF, then EOF");
+                }
+                if (0 != nextByte) {
+                    final int marker = (bitsData << 8) | nextByte;
+                    throw new MarkerException(marker, "Marker at readBit file pos " + _ipos);
+                }
+                // unstuff 0
+            }
+            bitsCount = 7;
+            return bitsData >>> 7;
+        }
+
+        private int decodeHuffman(BinObj tree) throws IOException {
+            BinObj node = tree;
+            int bit;
+            while ( ( bit = readBit() ) != -1 ) {
+                node = node.get(bit);
+                if ( node.isValue ) {
+                    return 0x000000FF & node.getValue();
+                }
+            }
+            throw new CodecException("EOF reached at "+_ipos);
+        }
+        private int receive(int length) throws IOException {
+            int n = 0;
+            while (length > 0) {
+                final int bit = readBit();
+                if (bit == -1) {
+                    return -1;
+                }
+                n = (n << 1) | bit;
+                length--;
+            }
+            return n;
+        }
+        private int receiveAndExtend(int length) throws IOException {
+            final int n = receive(length);
+            if (n >= 1 << (length - 1)) {
+                return n;
+            }
+            return n + (-1 << length) + 1;
+        }
+
+        final DecoderFunction decodeBaseline = new BaselineDecoder();
+        final DecoderFunction decodeDCFirst = new DCFirstDecoder();
+        final DecoderFunction decodeDCSuccessive = new DCSuccessiveDecoder();
+        final DecoderFunction decodeACFirst = new ACFirstDecoder();
+        final DecoderFunction decodeACSuccessive = new ACSuccessiveDecoder();
+
+        class BaselineDecoder implements DecoderFunction {
+            public void decode(ComponentIn component, int[] zz) throws IOException {
+                final int t = decodeHuffman(component.huffmanTableDC);
+                final int diff = ( t == 0 ) ? 0 : receiveAndExtend(t);
+                zz[0] = ( component.pred += diff );
+                int k = 1;
+                while (k < 64) {
+                    final int rs = decodeHuffman(component.huffmanTableAC);
+                    final int s = rs & 15, r = rs >> 4;
+                    if (s == 0) {
+                        if (r < 15) {
+                            break;
+                        }
+                        k += 16;
+                        continue;
+                    }
+                    k += r;
+                    final int z = dctZigZag[k];
+                    zz[z] = receiveAndExtend(s);
+                    k++;
+                }
+            }
+        }
+        class DCFirstDecoder implements DecoderFunction {
+            public void decode(ComponentIn component, int[] zz) throws IOException {
+                final int t = decodeHuffman(component.huffmanTableDC);
+                final int diff = ( t == 0 ) ? 0 : (receiveAndExtend(t) << successive);
+                zz[0] = ( component.pred += diff );
+            }
+        }
+        class DCSuccessiveDecoder implements DecoderFunction {
+            public void decode(ComponentIn component, int[] zz) throws IOException {
+                zz[0] |= readBit() << successive;
+            }
+        }
+
+        class ACFirstDecoder implements DecoderFunction {
+            public void decode(ComponentIn component, int[] zz) throws IOException {
+                if (eobrun > 0) {
+                    eobrun--;
+                    return;
+                }
+                int k = spectralStart, e = spectralEnd;
+                while (k <= e) {
+                    final int rs = decodeHuffman(component.huffmanTableAC);
+                    final int s = rs & 15, r = rs >> 4;
+                    if (s == 0) {
+                        if (r < 15) {
+                            eobrun = receive(r) + (1 << r) - 1;
+                            break;
+                        }
+                        k += 16;
+                        continue;
+                    }
+                    k += r;
+                    final int z = dctZigZag[k];
+                    zz[z] = receiveAndExtend(s) * (1 << successive);
+                    k++;
+                }
+            }
+        }
+        class ACSuccessiveDecoder implements DecoderFunction {
+            public void decode(ComponentIn component, int[] zz) throws IOException {
+                int k = spectralStart, e = spectralEnd, r = 0;
+                while (k <= e) {
+                    final int z = dctZigZag[k];
+                    switch (successiveACState) {
+                    case 0: // initial state
+                        final int rs = decodeHuffman(component.huffmanTableAC);
+                        final int s = rs & 15;
+                        r = rs >> 4;
+                        if (s == 0) {
+                            if (r < 15) {
+                                eobrun = receive(r) + (1 << r);
+                                successiveACState = 4;
+                            } else {
+                                r = 16;
+                                successiveACState = 1;
+                            }
+                        } else {
+                            // if (s !== 1) {                  
+                            if (s != 1) {
+                                throw new CodecException("invalid ACn encoding");
+                            }
+                            successiveACNextValue = receiveAndExtend(s);
+                            successiveACState = r != 0 ? 2 : 3;
+                        }
+                        continue;
+                    case 1: // skipping r zero items
+                    case 2:
+                        if ( zz[z] != 0 ) {
+                            zz[z] += (readBit() << successive);
+                        } else {
+                            r--;
+                            if (r == 0) {
+                                successiveACState = successiveACState == 2 ? 3 : 0;
+                            }
+                        }
+                        break;
+                    case 3: // set value for a zero item
+                        if ( zz[z] != 0 ) {
+                            zz[z] += (readBit() << successive);
+                        } else {
+                            zz[z] = successiveACNextValue << successive;
+                            successiveACState = 0;
+                        }
+                        break;
+                    case 4: // eob
+                        if ( zz[z] != 0 ) {
+                            zz[z] += (readBit() << successive);
+                        }
+                        break;
+                        }
+                        k++;
+                    }
+                    if (successiveACState == 4) {
+                        eobrun--;
+                        if (eobrun == 0) {
+                            successiveACState = 0;
+                        }
+                    }
+            }
+        }
+        void decodeMcu(ComponentIn component, DecoderFunction decoder, int mcu, int row, int col) throws IOException {
+            final int mcuRow = (mcu / mcusPerLine) | 0;
+            final int mcuCol = mcu % mcusPerLine;
+            final int blockRow = mcuRow * component.v + row;
+            final int blockCol = mcuCol * component.h + col;
+            decoder.decode(component, component.getBlock(blockRow, blockCol));
+        }
+        void decodeBlock(ComponentIn component, DecoderFunction decoder, int mcu) throws IOException {
+            final int blockRow = (mcu / component.blocksPerLine) | 0;
+            final int blockCol = mcu % component.blocksPerLine;
+            decoder.decode(component, component.getBlock(blockRow, blockCol));
+        }
+    }
+
+    private final Decoder decoder = new Decoder();
+
+    /** wrong color space ..
+    private final void storeYCbCr2BGR(final PixelStorage pixelStorage, int x, int y, int Y, final int Cb, final int Cr)
+    {
+        if(Y<0) Y=0;
+        int B = Y + ( ( 116130 * Cb ) >> 16 ) ;
+        if(B<0) B=0;
+        else if(B>255) B=255;
+
+        int G = Y - ( ( 22554 * Cb + 46802 * Cr ) >> 16 ) ;
+        if(G<0) G=0;
+        else if(G>255) G=255;
+
+        int R = Y + ( ( 91881 * Cr ) >> 16 );
+        if(R<0) R=0;
+        else if(R>255) R=255;
+        
+        pixelStorage.storeRGB(x, y, (byte)R, (byte)G, (byte)B);
+    } */
+    
+    public synchronized void getPixel(JPEGDecoder.ColorSink pixelStorage, int width, int height) {
+        final int scaleX = this.width / width, scaleY = this.height / height;
+
+        final int componentCount = this.components.length;
+        final ColorSpace sourceCS = ( null != adobe ) ? adobe.colorSpace : ColorSpace.YCbCr; 
+        final ColorSpace storageCS = pixelStorage.allocate(width, height, sourceCS, componentCount);
+        if( ColorSpace.RGB != storageCS && ColorSpace.YCbCr != storageCS ) {
+            throw new IllegalArgumentException("Unsupported storage color space: "+storageCS); 
+        }
+
+        switch (componentCount) {
+        case 1: {
+            // Grayscale
+            final ComponentOut component1 = this.components[0];
+            for (int y = 0; y < height; y++) {
+                final byte[] component1Line = component1.getLine((int)(y * component1.scaleY * scaleY));
+                for (int x = 0; x < width; x++) {
+                    final byte Y = component1Line[(int)(x * component1.scaleX * scaleX)];
+                    if( ColorSpace.YCbCr == storageCS ) {
+                        pixelStorage.storeYCbCr(x, y, Y, (byte)0, (byte)0);
+                    } else {
+                        pixelStorage.storeRGB(x, y, Y, Y, Y);
+                    }
+                }
+            }
+        }
+        break;
+        case 2: {
+            // PDF might compress two component data in custom colorspace
+            final ComponentOut component1 = this.components[0];
+            final ComponentOut component2 = this.components[1];
+            for (int y = 0; y < height; y++) {
+                final int ys = y * scaleY;
+                final byte[] component1Line = component1.getLine((int)(ys * component1.scaleY));
+                final byte[] component2Line = component1.getLine((int)(ys * component2.scaleY));
+                for (int x = 0; x < width; x++) {
+                    final int xs = x * scaleX;
+                    final byte Y1 = component1Line[(int)(xs * component1.scaleX)];
+                    final byte Y2 = component2Line[(int)(xs * component2.scaleX)];
+                    pixelStorage.store2(x, y, Y1, Y2);
+                }
+            }
+        }
+        break;
+        case 3: {
+            if (ColorSpace.YCbCr != sourceCS) {
+                throw new CodecException("Unsupported source color space w 3 components: "+sourceCS);
+            }
+            final ComponentOut component1 = this.components[0];
+            final ComponentOut component2 = this.components[1];
+            final ComponentOut component3 = this.components[2];
+            for (int y = 0; y < height; y++) {
+                final int ys = y * scaleY;
+                final byte[] component1Line = component1.getLine((int)(ys * component1.scaleY));
+                final byte[] component2Line = component2.getLine((int)(ys * component2.scaleY));
+                final byte[] component3Line = component3.getLine((int)(ys * component3.scaleY));
+                if( ColorSpace.YCbCr == storageCS ) {
+                    for (int x = 0; x < width; x++) {
+                        final int xs = x * scaleX;
+                        final byte Y  = component1Line[(int)(xs * component1.scaleX)];
+                        final byte Cb = component2Line[(int)(xs * component2.scaleX)];
+                        final byte Cr = component3Line[(int)(xs * component3.scaleX)];
+                        pixelStorage.storeYCbCr(x, y, Y, Cb, Cr);
+                    }
+                } else {
+                    for (int x = 0; x < width; x++) {
+                        final int xs = x * scaleX;
+                        final int Y  = 0x000000FF & component1Line[(int)(xs * component1.scaleX)];
+                        final int Cb = 0x000000FF & component2Line[(int)(xs * component2.scaleX)];
+                        final int Cr = 0x000000FF & component3Line[(int)(xs * component3.scaleX)];
+                        // storeYCbCr2BGR(pixelStorage, x, y, Y, Cb, Cr);
+                        final byte R = clampTo8bit(Y + 1.402f * (Cr - 128f));
+                        final byte G = clampTo8bit(Y - 0.3441363f * (Cb - 128f) - 0.71413636f * (Cr - 128f));
+                        final byte B = clampTo8bit(Y + 1.772f * (Cb - 128f));
+                        pixelStorage.storeRGB(x, y, R, G, B);
+                    }
+                }
+            }
+        }
+        break;
+        case 4: {
+            if (ColorSpace.YCCK != sourceCS && ColorSpace.CMYK != sourceCS) {
+                throw new CodecException("Unsupported source color space w 4 components: "+sourceCS);
+            }
+            final ComponentOut component1 = this.components[0];
+            final ComponentOut component2 = this.components[1];
+            final ComponentOut component3 = this.components[2];
+            final ComponentOut component4 = this.components[3];
+            for (int y = 0; y < height; y++) {
+                final int ys = y * scaleY;
+                final byte[] component1Line = component1.getLine((int)(ys * component1.scaleY));
+                final byte[] component2Line = component2.getLine((int)(ys * component2.scaleY));
+                final byte[] component3Line = component3.getLine((int)(ys * component3.scaleY));
+                final byte[] component4Line = component4.getLine((int)(ys * component4.scaleY));
+                if( ColorSpace.YCbCr == storageCS ) {
+                    if (ColorSpace.YCCK != sourceCS) {
+                        throw new CodecException("Unsupported storage color space "+storageCS+" with source color space "+sourceCS);
+                    }
+                    for (int x = 0; x < width; x++) {
+                        final int xs = x * scaleX;
+                        final byte Y1 = component1Line[(int)(xs * component1.scaleX)];
+                        final byte C1 = component2Line[(int)(xs * component2.scaleX)];
+                        final byte C2 = component3Line[(int)(xs * component3.scaleX)];
+                        // final byte K  = component4Line[(int)(xs * component4.scaleX)];
+                        // FIXME: YCCK is not really YCbCr, since K (black) is missing!
+                        pixelStorage.storeYCbCr(x, y, Y1, C1, C2);
+                    }
+                } else {
+                    if (ColorSpace.CMYK == sourceCS) {
+                        for (int x = 0; x < width; x++) {
+                            final int xs = x * scaleX;
+                            final int cC = 0x000000FF & component1Line[(int)(xs * component1.scaleX)];
+                            final int cM = 0x000000FF & component2Line[(int)(xs * component2.scaleX)];
+                            final int cY = 0x000000FF & component3Line[(int)(xs * component3.scaleX)];
+                            final int cK = 0x000000FF & component4Line[(int)(xs * component4.scaleX)];
+                            // CMYK -> RGB
+                            final byte R = clampTo8bit( ( cC * cK ) / 255f );
+                            final byte G = clampTo8bit( ( cM * cK ) / 255f );
+                            final byte B = clampTo8bit( ( cY * cK ) / 255f );
+                            pixelStorage.storeRGB(x, y, R, G, B);
+                        }                        
+                    } else { // ColorModel.YCCK == sourceCM
+                        for (int x = 0; x < width; x++) {
+                            final int xs = x * scaleX;
+                            final int Y  = 0x000000FF & component1Line[(int)(xs * component1.scaleX)];
+                            final int Cb = 0x000000FF & component2Line[(int)(xs * component2.scaleX)];
+                            final int Cr = 0x000000FF & component3Line[(int)(xs * component3.scaleX)];
+                            final int cK = 0x000000FF & component4Line[(int)(xs * component4.scaleX)];
+                            // YCCK -> 255f - [ R'G'B' ] -> CMYK
+                            final float cC = 255f - ( Y + 1.402f * (Cr - 128f) );
+                            final float cM = 255f - ( Y - 0.3441363f * (Cb - 128f) - 0.71413636f * (Cr - 128f) );
+                            final float cY = 255f - ( Y + 1.772f * (Cb - 128f) );
+                            // CMYK -> RGB
+                            final byte R = clampTo8bit( ( cC * cK ) / 255f );
+                            final byte G = clampTo8bit( ( cM * cK ) / 255f );
+                            final byte B = clampTo8bit( ( cY * cK ) / 255f );
+                            pixelStorage.storeRGB(x, y, R, G, B);
+                        }
+                    }
+                }
+            }
+        } 
+        break;
+        default:
+            throw new CodecException("Unsupported color model: Space "+sourceCS+", components "+componentCount);
+        }
+    }
+
+    private static byte clampTo8bit(float a) {
+        return (byte) ( a < 0f ? 0 : a > 255f ? 255 : a );
+    }
+
+    private static String toHexString(int v) {
+        return "0x"+Integer.toHexString(v);
+    }
+}
\ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java b/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java
index a34f73a..e88a95a 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java
@@ -30,17 +30,22 @@ public enum FilterType {
 	 */
 	FILTER_DEFAULT(-1),
 	/**
-	 * Aggresive strategy: select one of the above filters trying each of the filters (this is done every 8 rows)
+	 * Aggressive strategy: select one of the above filters trying each of the filters (every 8 rows)
 	 */
 	FILTER_AGGRESSIVE(-2),
 	/**
+	 * Very aggressive strategy: select one of the above filters trying each of the filters (for every row!)
+	 */
+	FILTER_VERYAGGRESSIVE(-3),
+	/**
 	 * Uses all fiters, one for lines, cyciclally. Only for tests.
 	 */
-	FILTER_ALTERNATE(-3),
+	FILTER_CYCLIC(-50),
+
 	/**
-	 * Aggresive strategy: select one of the above filters trying each of the filters (this is done for every row!)
+	 * Not specified, placeholder for unknown or NA filters.
 	 */
-	FILTER_VERYAGGRESSIVE(-4), ;
+	FILTER_UNKNOWN(-100), ;
 	public final int val;
 
 	private FilterType(int val) {
@@ -55,40 +60,4 @@ public enum FilterType {
 		return null;
 	}
 
-	public static int unfilterRowNone(int r) {
-		return (int) (r & 0xFF);
-	}
-
-	public static int unfilterRowSub(int r, int left) {
-		return ((int) (r + left) & 0xFF);
-	}
-
-	public static int unfilterRowUp(int r, int up) {
-		return ((int) (r + up) & 0xFF);
-	}
-
-	public static int unfilterRowAverage(int r, int left, int up) {
-		return (r + (left + up) / 2) & 0xFF;
-	}
-
-	public static int unfilterRowPaeth(int r, int a, int b, int c) { // a = left, b = above, c = upper left
-		return (r + filterPaethPredictor(a, b, c)) & 0xFF;
-	}
-
-	public static int filterPaethPredictor(int a, int b, int c) {
-		// from http://www.libpng.org/pub/png/spec/1.2/PNG-Filters.html
-		// a = left, b = above, c = upper left
-		final int p = a + b - c;// ; initial estimate
-		final int pa = p >= a ? p - a : a - p;
-		final int pb = p >= b ? p - b : b - p;
-		final int pc = p >= c ? p - c : c - p;
-		// ; return nearest of a,b,c,
-		// ; breaking ties in order a,b,c.
-		if (pa <= pb && pa <= pc)
-			return a;
-		else if (pb <= pc)
-			return b;
-		else
-			return c;
-	}
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/FilterWriteStrategy.java b/src/jogl/classes/jogamp/opengl/util/pngj/FilterWriteStrategy.java
index 27586b2..79eed8f 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/FilterWriteStrategy.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/FilterWriteStrategy.java
@@ -1,7 +1,7 @@
 package jogamp.opengl.util.pngj;
 
 /**
- * Manages the writer strategy for selecting the internal png "filter"
+ * Manages the writer strategy for selecting the internal png predictor filter
  */
 class FilterWriteStrategy {
 	private static final int COMPUTE_STATS_EVERY_N_LINES = 8;
@@ -89,7 +89,7 @@ class FilterWriteStrategy {
 				}
 			}
 		}
-		if (configuredType == FilterType.FILTER_ALTERNATE) {
+		if (configuredType == FilterType.FILTER_CYCLIC) {
 			currentType = FilterType.getByVal((currentType.val + 1) % 5);
 		}
 		return currentType;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java
index 2f6b89e..26562ef 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java
@@ -13,12 +13,12 @@ public class ImageInfo {
 	private static final int MAX_COLS_ROWS_VAL = 1000000;
 
 	/**
-	 * Image width, in pixels.
+	 * Cols= Image width, in pixels.
 	 */
 	public final int cols;
 
 	/**
-	 * Image height, in pixels
+	 * Rows= Image height, in pixels
 	 */
 	public final int rows;
 
@@ -29,8 +29,8 @@ public class ImageInfo {
 	public final int bitDepth;
 
 	/**
-	 * Number of channels, as used internally. This is 3 for RGB, 4 for RGBA, 2 for GA (gray with alpha), 1 for
-	 * grayscales or indexed.
+	 * Number of channels, as used internally: 3 for RGB, 4 for RGBA, 2 for GA (gray with alpha), 1 for grayscale or
+	 * indexed.
 	 */
 	public final int channels;
 
@@ -75,10 +75,14 @@ public class ImageInfo {
 	public final int samplesPerRow;
 
 	/**
-	 * For internal use only. Samples available for our packed scanline. Equals samplesPerRow if not packed. Elsewhere,
-	 * it's lower
+	 * Amount of "packed samples" : when several samples are stored in a single byte (bitdepth 1,2 4) they are counted
+	 * as one "packed sample". This is less that samplesPerRow only when bitdepth is 1-2-4 (flag packed = true)
+	 * <p>
+	 * This equals the number of elements in the scanline array if working with packedMode=true
+	 * <p>
+	 * For internal use, client code should rarely access this.
 	 */
-	final int samplesPerRowP;
+	public final int samplesPerRowPacked;
 
 	/**
 	 * Short constructor: assumes truecolor (RGB/RGBA)
@@ -119,7 +123,7 @@ public class ImageInfo {
 		this.bytesPixel = (bitspPixel + 7) / 8;
 		this.bytesPerRow = (bitspPixel * cols + 7) / 8;
 		this.samplesPerRow = channels * this.cols;
-		this.samplesPerRowP = packed ? bytesPerRow : samplesPerRow;
+		this.samplesPerRowPacked = packed ? bytesPerRow : samplesPerRow;
 		// several checks
 		switch (this.bitDepth) {
 		case 1:
@@ -147,7 +151,7 @@ public class ImageInfo {
 	public String toString() {
 		return "ImageInfo [cols=" + cols + ", rows=" + rows + ", bitDepth=" + bitDepth + ", channels=" + channels
 				+ ", bitspPixel=" + bitspPixel + ", bytesPixel=" + bytesPixel + ", bytesPerRow=" + bytesPerRow
-				+ ", samplesPerRow=" + samplesPerRow + ", samplesPerRowP=" + samplesPerRowP + ", alpha=" + alpha
+				+ ", samplesPerRow=" + samplesPerRow + ", samplesPerRowP=" + samplesPerRowPacked + ", alpha=" + alpha
 				+ ", greyscale=" + greyscale + ", indexed=" + indexed + ", packed=" + packed + "]";
 	}
 
@@ -157,16 +161,11 @@ public class ImageInfo {
 		int result = 1;
 		result = prime * result + (alpha ? 1231 : 1237);
 		result = prime * result + bitDepth;
-		result = prime * result + bitspPixel;
-		result = prime * result + bytesPerRow;
-		result = prime * result + bytesPixel;
 		result = prime * result + channels;
 		result = prime * result + cols;
 		result = prime * result + (greyscale ? 1231 : 1237);
 		result = prime * result + (indexed ? 1231 : 1237);
-		result = prime * result + (packed ? 1231 : 1237);
 		result = prime * result + rows;
-		result = prime * result + samplesPerRow;
 		return result;
 	}
 
@@ -183,12 +182,6 @@ public class ImageInfo {
 			return false;
 		if (bitDepth != other.bitDepth)
 			return false;
-		if (bitspPixel != other.bitspPixel)
-			return false;
-		if (bytesPerRow != other.bytesPerRow)
-			return false;
-		if (bytesPixel != other.bytesPixel)
-			return false;
 		if (channels != other.channels)
 			return false;
 		if (cols != other.cols)
@@ -197,12 +190,9 @@ public class ImageInfo {
 			return false;
 		if (indexed != other.indexed)
 			return false;
-		if (packed != other.packed)
-			return false;
 		if (rows != other.rows)
 			return false;
-		if (samplesPerRow != other.samplesPerRow)
-			return false;
 		return true;
 	}
+
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java
index bfbb35b..9f8a132 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java
@@ -1,6 +1,6 @@
 package jogamp.opengl.util.pngj;
 
-import java.util.Arrays;
+import jogamp.opengl.util.pngj.ImageLineHelper.ImageLineStats;
 
 /**
  * Lightweight wrapper for an image scanline, used for read and write.
@@ -20,26 +20,87 @@ public class ImageLine {
 	/**
 	 * The 'scanline' is an array of integers, corresponds to an image line (row).
 	 * <p>
-	 * Except for 'packed' formats (gray/indexed with 1-2-4 bitdepth) each int is a "sample" (one for channel), (0-255
-	 * or 0-65535) in the respective PNG sequence sequence : (R G B R G B...) or (R G B A R G B A...) or (g g g ...) or
-	 * ( i i i) (palette index)
+	 * Except for 'packed' formats (gray/indexed with 1-2-4 bitdepth) each <code>int</code> is a "sample" (one for
+	 * channel), (0-255 or 0-65535) in the corresponding PNG sequence: <code>R G B R G B...</code> or
+	 * <code>R G B A R G B A...</tt> 
+	 * or <code>g g g ...</code> or <code>i i i</code> (palette index)
 	 * <p>
-	 * For bitdepth 1/2/4 , each element is a PACKED byte! To get an unpacked copy, see <code>tf_pack()</code> and its
-	 * inverse <code>tf_unpack()</code>
+	 * For bitdepth=1/2/4 , and if samplesUnpacked=false, each value is a PACKED byte!
 	 * <p>
-	 * To convert a indexed line to RGB balues, see <code>ImageLineHelper.tf_palIdx2RGB()</code> (can't do the reverse)
+	 * To convert a indexed line to RGB balues, see <code>ImageLineHelper.palIdx2RGB()</code> (you can't do the reverse)
 	 */
-	public final int[] scanline; // see explanation above!!
+	public final int[] scanline;
+	/**
+	 * Same as {@link #scanline}, but with one byte per sample. Only one of scanline and scanlineb is valid - this
+	 * depends on {@link #sampleType}
+	 */
+	public final byte[] scanlineb;
 
 	protected FilterType filterUsed; // informational ; only filled by the reader
-	public final int channels; // copied from imgInfo, more handy
-	public final int bitDepth; // copied from imgInfo, more handy
+	final int channels; // copied from imgInfo, more handy
+	final int bitDepth; // copied from imgInfo, more handy
+	final int elementsPerRow; // = imgInfo.samplePerRowPacked, if packed:imgInfo.samplePerRow elswhere
+
+	public enum SampleType {
+		INT, // 4 bytes per sample
+		// SHORT, // 2 bytes per sample
+		BYTE // 1 byte per sample
+	}
+
+	/**
+	 * tells if we are using BYTE or INT to store the samples.
+	 */
+	public final SampleType sampleType;
+
+	/**
+	 * true: each element of the scanline array represents a sample always, even for internally packed PNG formats
+	 * 
+	 * false: if the original image was of packed type (bit depth less than 8) we keep samples packed in a single array
+	 * element
+	 */
+	public final boolean samplesUnpacked;
 
+	/**
+	 * default mode: INT packed
+	 */
 	public ImageLine(ImageInfo imgInfo) {
+		this(imgInfo, SampleType.INT, false);
+	}
+
+	/**
+	 * 
+	 * @param imgInfo
+	 *            Inmutable ImageInfo, basic parameter of the image we are reading or writing
+	 * @param stype
+	 *            INT or BYTE : this determines which scanline is the really used one
+	 * @param unpackedMode
+	 *            If true, we use unpacked format, even for packed original images
+	 * 
+	 */
+	public ImageLine(ImageInfo imgInfo, SampleType stype, boolean unpackedMode) {
+		this(imgInfo, stype, unpackedMode, null, null);
+	}
+
+	/**
+	 * If a preallocated array is passed, the copy is shallow
+	 */
+	ImageLine(ImageInfo imgInfo, SampleType stype, boolean unpackedMode, int[] sci, byte[] scb) {
 		this.imgInfo = imgInfo;
 		channels = imgInfo.channels;
-		scanline = new int[imgInfo.samplesPerRowP];
-		this.bitDepth = imgInfo.bitDepth;
+		bitDepth = imgInfo.bitDepth;
+		filterUsed = FilterType.FILTER_UNKNOWN;
+		this.sampleType = stype;
+		this.samplesUnpacked = unpackedMode || !imgInfo.packed;
+		elementsPerRow = this.samplesUnpacked ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked;
+		if (stype == SampleType.INT) {
+			scanline = sci != null ? sci : new int[elementsPerRow];
+			scanlineb = null;
+		} else if (stype == SampleType.BYTE) {
+			scanlineb = scb != null ? scb : new byte[elementsPerRow];
+			scanline = null;
+		} else
+			throw new PngjExceptionInternal("bad ImageLine initialization");
+		this.rown = -1;
 	}
 
 	/** This row number inside the image (0 is top) */
@@ -47,129 +108,213 @@ public class ImageLine {
 		return rown;
 	}
 
-	/** Increments row number */
-	public void incRown() {
-		this.rown++;
-	}
-
-	/** Sets row number */
+	/** Sets row number (0 : Rows-1) */
 	public void setRown(int n) {
 		this.rown = n;
 	}
 
-	/** Sets scanline, making copy from passed array */
-	public void setScanLine(int[] b) {
-		System.arraycopy(b, 0, scanline, 0, scanline.length);
+	/*
+	 * Unpacks scanline (for bitdepth 1-2-4)
+	 * 
+	 * Arrays must be prealocated. src : samplesPerRowPacked dst : samplesPerRow
+	 * 
+	 * This usually works in place (with src==dst and length=samplesPerRow)!
+	 * 
+	 * If not, you should only call this only when necesary (bitdepth <8)
+	 * 
+	 * If <code>scale==true<code>, it scales the value (just a bit shift) towards 0-255.
+	 */
+	static void unpackInplaceInt(final ImageInfo iminfo, final int[] src, final int[] dst, final boolean scale) {
+		final int bitDepth = iminfo.bitDepth;
+		if (bitDepth >= 8)
+			return; // nothing to do
+		final int mask0 = ImageLineHelper.getMaskForPackedFormatsLs(bitDepth);
+		final int scalefactor = 8 - bitDepth;
+		final int offset0 = 8 * iminfo.samplesPerRowPacked - bitDepth * iminfo.samplesPerRow;
+		int mask, offset, v;
+		if (offset0 != 8) {
+			mask = mask0 << offset0;
+			offset = offset0; // how many bits to shift the mask to the right to recover mask0
+		} else {
+			mask = mask0;
+			offset = 0;
+		}
+		for (int j = iminfo.samplesPerRow - 1, i = iminfo.samplesPerRowPacked - 1; j >= 0; j--) {
+			v = (src[i] & mask) >> offset;
+			if (scale)
+				v <<= scalefactor;
+			dst[j] = v;
+			mask <<= bitDepth;
+			offset += bitDepth;
+			if (offset == 8) {
+				mask = mask0;
+				offset = 0;
+				i--;
+			}
+		}
 	}
 
-	/**
-	 * Returns a copy from scanline, in byte array.
+	/*
+	 * Unpacks scanline (for bitdepth 1-2-4)
 	 * 
-	 * You can (OPTIONALLY) pass an preallocated array to use.
-	 **/
-	public int[] getScanLineCopy(int[] b) {
-		if (b == null || b.length < scanline.length)
-			b = new int[scanline.length];
-		System.arraycopy(scanline, 0, b, 0, scanline.length);
-		return b;
+	 * Arrays must be prealocated. src : samplesPerRow dst : samplesPerRowPacked
+	 * 
+	 * This usually works in place (with src==dst and length=samplesPerRow)! If not, you should only call this only when
+	 * necesary (bitdepth <8)
+	 * 
+	 * The trailing elements are trash
+	 * 
+	 * 
+	 * If <code>scale==true<code>, it scales the value (just a bit shift) towards 0-255.
+	 */
+	static void packInplaceInt(final ImageInfo iminfo, final int[] src, final int[] dst, final boolean scaled) {
+		final int bitDepth = iminfo.bitDepth;
+		if (bitDepth >= 8)
+			return; // nothing to do
+		final int mask0 = ImageLineHelper.getMaskForPackedFormatsLs(bitDepth);
+		final int scalefactor = 8 - bitDepth;
+		final int offset0 = 8 - bitDepth;
+		int v, v0;
+		int offset = 8 - bitDepth;
+		v0 = src[0]; // first value is special for in place
+		dst[0] = 0;
+		if (scaled)
+			v0 >>= scalefactor;
+		v0 = ((v0 & mask0) << offset);
+		for (int i = 0, j = 0; j < iminfo.samplesPerRow; j++) {
+			v = src[j];
+			if (scaled)
+				v >>= scalefactor;
+			dst[i] |= ((v & mask0) << offset);
+			offset -= bitDepth;
+			if (offset < 0) {
+				offset = offset0;
+				i++;
+				dst[i] = 0;
+			}
+		}
+		dst[0] |= v0;
 	}
 
-	/**
-	 * Unpacks scanline (for bitdepth 1-2-4) into buffer.
-	 * <p>
-	 * You can (OPTIONALLY) pass an preallocated array to use.
-	 * <p>
-	 * If scale==TRUE scales the value (just a bit shift).
-	 */
-	public int[] tf_unpack(int[] buf, boolean scale) {
-		int len = scanline.length;
-		if (bitDepth == 1)
-			len *= 8;
-		else if (bitDepth == 2)
-			len *= 4;
-		else if (bitDepth == 4)
-			len *= 2;
-		if (buf == null)
-			buf = new int[len];
+	static void unpackInplaceByte(final ImageInfo iminfo, final byte[] src, final byte[] dst, final boolean scale) {
+		final int bitDepth = iminfo.bitDepth;
 		if (bitDepth >= 8)
-			System.arraycopy(scanline, 0, buf, 0, scanline.length);
-		else {
-			int mask, offset, v;
-			int mask0 = getMaskForPackedFormats();
-			int offset0 = 8 - bitDepth;
+			return; // nothing to do
+		final int mask0 = ImageLineHelper.getMaskForPackedFormatsLs(bitDepth);
+		final int scalefactor = 8 - bitDepth;
+		final int offset0 = 8 * iminfo.samplesPerRowPacked - bitDepth * iminfo.samplesPerRow;
+		int mask, offset, v;
+		if (offset0 != 8) {
+			mask = mask0 << offset0;
+			offset = offset0; // how many bits to shift the mask to the right to recover mask0
+		} else {
 			mask = mask0;
-			offset = offset0;
-			for (int i = 0, j = 0; i < len; i++) {
-				v = (scanline[j] & mask) >> offset;
-				if (scale)
-					v <<= offset0;
-				buf[i] = v;
-				mask = mask >> bitDepth;
-				offset -= bitDepth;
-				if (mask == 0) { // new byte in source
-					mask = mask0;
-					offset = offset0;
-					j++;
-				}
+			offset = 0;
+		}
+		for (int j = iminfo.samplesPerRow - 1, i = iminfo.samplesPerRowPacked - 1; j >= 0; j--) {
+			v = (src[i] & mask) >> offset;
+			if (scale)
+				v <<= scalefactor;
+			dst[j] = (byte) v;
+			mask <<= bitDepth;
+			offset += bitDepth;
+			if (offset == 8) {
+				mask = mask0;
+				offset = 0;
+				i--;
 			}
 		}
-		return buf;
 	}
 
-	/**
-	 * Packs scanline (for bitdepth 1-2-4) from buffer.
-	 * <p>
-	 * If scale==TRUE scales the value (just a bit shift).
-	 */
-	public void tf_pack(int[] buf, boolean scale) { // writes scanline
-		int len = scanline.length;
-		if (bitDepth == 1)
-			len *= 8;
-		else if (bitDepth == 2)
-			len *= 4;
-		else if (bitDepth == 4)
-			len *= 2;
+	/** size original: samplesPerRow sizeFinal: samplesPerRowPacked (trailing elements are trash!) **/
+	static void packInplaceByte(final ImageInfo iminfo, final byte[] src, final byte[] dst, final boolean scaled) {
+		final int bitDepth = iminfo.bitDepth;
 		if (bitDepth >= 8)
-			System.arraycopy(buf, 0, scanline, 0, scanline.length);
-		else {
-			int offset0 = 8 - bitDepth;
-			int mask0 = getMaskForPackedFormats() >> offset0;
-			int offset, v;
-			offset = offset0;
-			Arrays.fill(scanline, 0);
-			for (int i = 0, j = 0; i < len; i++) {
-				v = buf[i];
-				if (scale)
-					v >>= offset0;
-				v = (v & mask0) << offset;
-				scanline[j] |= v;
-				offset -= bitDepth;
-				if (offset < 0) { // new byte in scanline
-					offset = offset0;
-					j++;
-				}
+			return; // nothing to do
+		final int mask0 = ImageLineHelper.getMaskForPackedFormatsLs(bitDepth);
+		final int scalefactor = 8 - bitDepth;
+		final int offset0 = 8 - bitDepth;
+		int v, v0;
+		int offset = 8 - bitDepth;
+		v0 = src[0]; // first value is special
+		dst[0] = 0;
+		if (scaled)
+			v0 >>= scalefactor;
+		v0 = ((v0 & mask0) << offset);
+		for (int i = 0, j = 0; j < iminfo.samplesPerRow; j++) {
+			v = src[j];
+			if (scaled)
+				v >>= scalefactor;
+			dst[i] |= ((v & mask0) << offset);
+			offset -= bitDepth;
+			if (offset < 0) {
+				offset = offset0;
+				i++;
+				dst[i] = 0;
 			}
 		}
+		dst[0] |= v0;
 	}
 
-	private int getMaskForPackedFormats() { // Utility function for pacj/unpack
-		if (bitDepth == 1)
-			return 0x80;
-		if (bitDepth == 2)
-			return 0xc0;
-		if (bitDepth == 4)
-			return 0xf0;
-		throw new RuntimeException("?");
+	/**
+	 * Creates a new ImageLine similar to this, but unpacked
+	 * 
+	 * The caller must be sure that the original was really packed
+	 */
+	public ImageLine unpackToNewImageLine() {
+		ImageLine newline = new ImageLine(imgInfo, sampleType, true);
+		if (sampleType == SampleType.INT)
+			unpackInplaceInt(imgInfo, scanline, newline.scanline, false);
+		else
+			unpackInplaceByte(imgInfo, scanlineb, newline.scanlineb, false);
+		return newline;
+	}
+
+	/**
+	 * Creates a new ImageLine similar to this, but packed
+	 * 
+	 * The caller must be sure that the original was really unpacked
+	 */
+	public ImageLine packToNewImageLine() {
+		ImageLine newline = new ImageLine(imgInfo, sampleType, false);
+		if (sampleType == SampleType.INT)
+			packInplaceInt(imgInfo, scanline, newline.scanline, false);
+		else
+			packInplaceByte(imgInfo, scanlineb, newline.scanlineb, false);
+		return newline;
 	}
 
 	public FilterType getFilterUsed() {
 		return filterUsed;
 	}
 
+	public void setFilterUsed(FilterType ft) {
+		filterUsed = ft;
+	}
+
+	public int[] getScanlineInt() {
+		return scanline;
+	}
+
+	public byte[] getScanlineByte() {
+		return scanlineb;
+	}
+
 	/**
 	 * Basic info
 	 */
 	public String toString() {
 		return "row=" + rown + " cols=" + imgInfo.cols + " bpc=" + imgInfo.bitDepth + " size=" + scanline.length;
 	}
+
+	/**
+	 * Prints some statistics - just for debugging
+	 */
+	public static void showLineInfo(ImageLine line) {
+		System.out.println(line);
+		ImageLineStats stats = new ImageLineHelper.ImageLineStats(line);
+		System.out.println(stats);
+		System.out.println(ImageLineHelper.infoFirstLastPixels(line));
+	}
+
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java
new file mode 100644
index 0000000..98f2356
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLineHelper.java
@@ -0,0 +1,318 @@
+package jogamp.opengl.util.pngj;
+
+import jogamp.opengl.util.pngj.ImageLine.SampleType;
+import jogamp.opengl.util.pngj.chunks.PngChunkPLTE;
+import jogamp.opengl.util.pngj.chunks.PngChunkTRNS;
+
+/**
+ * Bunch of utility static methods to process/analyze an image line at the pixel level.
+ * <p>
+ * Not essential at all, some methods are probably to be removed if future releases.
+ * <p>
+ * WARNING: most methods for getting/setting values work currently only for integer base imageLines
+ */
+public class ImageLineHelper {
+
+	private final static double BIG_VALUE = Double.MAX_VALUE * 0.5;
+
+	private final static double BIG_VALUE_NEG = Double.MAX_VALUE * (-0.5);
+
+	/**
+	 * Given an indexed line with a palette, unpacks as a RGB array, or RGBA if a non nul PngChunkTRNS chunk is passed
+	 * 
+	 * @param line
+	 *            ImageLine as returned from PngReader
+	 * @param pal
+	 *            Palette chunk
+	 * @param buf
+	 *            Preallocated array, optional
+	 * @return R G B (A), one sample 0-255 per array element. Ready for pngw.writeRowInt()
+	 */
+	public static int[] palette2rgb(ImageLine line, PngChunkPLTE pal, PngChunkTRNS trns, int[] buf) {
+		boolean isalpha = trns != null;
+		int channels = isalpha ? 4 : 3;
+		int nsamples = line.imgInfo.cols * channels;
+		if (buf == null || buf.length < nsamples)
+			buf = new int[nsamples];
+		if (!line.samplesUnpacked)
+			line = line.unpackToNewImageLine();
+		boolean isbyte = line.sampleType == SampleType.BYTE;
+		int nindexesWithAlpha = trns != null ? trns.getPalletteAlpha().length : 0;
+		for (int c = 0; c < line.imgInfo.cols; c++) {
+			int index = isbyte ? (line.scanlineb[c] & 0xFF) : line.scanline[c];
+			pal.getEntryRgb(index, buf, c * channels);
+			if (isalpha) {
+				int alpha = index < nindexesWithAlpha ? trns.getPalletteAlpha()[index] : 255;
+				buf[c * channels + 3] = alpha;
+			}
+		}
+		return buf;
+	}
+
+	public static int[] palette2rgb(ImageLine line, PngChunkPLTE pal, int[] buf) {
+		return palette2rgb(line, pal, null, buf);
+	}
+
+	/** what follows is pretty uninteresting/untested/obsolete, subject to change */
+	/**
+	 * Just for basic info or debugging. Shows values for first and last pixel. Does not include alpha
+	 */
+	public static String infoFirstLastPixels(ImageLine line) {
+		return line.imgInfo.channels == 1 ? String.format("first=(%d) last=(%d)", line.scanline[0],
+				line.scanline[line.scanline.length - 1]) : String.format("first=(%d %d %d) last=(%d %d %d)",
+				line.scanline[0], line.scanline[1], line.scanline[2], line.scanline[line.scanline.length
+						- line.imgInfo.channels], line.scanline[line.scanline.length - line.imgInfo.channels + 1],
+				line.scanline[line.scanline.length - line.imgInfo.channels + 2]);
+	}
+
+	public static String infoFull(ImageLine line) {
+		ImageLineStats stats = new ImageLineStats(line);
+		return "row=" + line.getRown() + " " + stats.toString() + "\n  " + infoFirstLastPixels(line);
+	}
+
+	/**
+	 * Computes some statistics for the line. Not very efficient or elegant, mainly for tests. Only for RGB/RGBA Outputs
+	 * values as doubles (0.0 - 1.0)
+	 */
+	static class ImageLineStats {
+		public double[] prom = { 0.0, 0.0, 0.0, 0.0 }; // channel averages
+		public double[] maxv = { BIG_VALUE_NEG, BIG_VALUE_NEG, BIG_VALUE_NEG, BIG_VALUE_NEG }; // maximo
+		public double[] minv = { BIG_VALUE, BIG_VALUE, BIG_VALUE, BIG_VALUE };
+		public double promlum = 0.0; // maximum global (luminance)
+		public double maxlum = BIG_VALUE_NEG; // max luminance
+		public double minlum = BIG_VALUE;
+		public double[] maxdif = { BIG_VALUE_NEG, BIG_VALUE_NEG, BIG_VALUE_NEG, BIG_VALUE }; // maxima
+		public final int channels; // diferencia
+
+		public String toString() {
+			return channels == 3 ? String.format(
+					"prom=%.1f (%.1f %.1f %.1f) max=%.1f (%.1f %.1f %.1f) min=%.1f (%.1f %.1f %.1f)", promlum, prom[0],
+					prom[1], prom[2], maxlum, maxv[0], maxv[1], maxv[2], minlum, minv[0], minv[1], minv[2])
+					+ String.format(" maxdif=(%.1f %.1f %.1f)", maxdif[0], maxdif[1], maxdif[2]) : String.format(
+					"prom=%.1f (%.1f %.1f %.1f %.1f) max=%.1f (%.1f %.1f %.1f %.1f) min=%.1f (%.1f %.1f %.1f %.1f)",
+					promlum, prom[0], prom[1], prom[2], prom[3], maxlum, maxv[0], maxv[1], maxv[2], maxv[3], minlum,
+					minv[0], minv[1], minv[2], minv[3])
+					+ String.format(" maxdif=(%.1f %.1f %.1f %.1f)", maxdif[0], maxdif[1], maxdif[2], maxdif[3]);
+		}
+
+		public ImageLineStats(ImageLine line) {
+			this.channels = line.channels;
+			if (line.channels < 3)
+				throw new PngjException("ImageLineStats only works for RGB - RGBA");
+			int ch = 0;
+			double lum, x, d;
+			for (int i = 0; i < line.imgInfo.cols; i++) {
+				lum = 0;
+				for (ch = channels - 1; ch >= 0; ch--) {
+					x = int2double(line, line.scanline[i * channels]);
+					if (ch < 3)
+						lum += x;
+					prom[ch] += x;
+					if (x > maxv[ch])
+						maxv[ch] = x;
+					if (x < minv[ch])
+						minv[ch] = x;
+					if (i >= channels) {
+						d = Math.abs(x - int2double(line, line.scanline[i - channels]));
+						if (d > maxdif[ch])
+							maxdif[ch] = d;
+					}
+				}
+				promlum += lum;
+				if (lum > maxlum)
+					maxlum = lum;
+				if (lum < minlum)
+					minlum = lum;
+			}
+			for (ch = 0; ch < channels; ch++) {
+				prom[ch] /= line.imgInfo.cols;
+			}
+			promlum /= (line.imgInfo.cols * 3.0);
+			maxlum /= 3.0;
+			minlum /= 3.0;
+		}
+	}
+
+	/**
+	 * integer packed R G B only for bitdepth=8! (does not check!)
+	 * 
+	 **/
+	public static int getPixelRGB8(ImageLine line, int column) {
+		int offset = column * line.channels;
+		return (line.scanline[offset] << 16) + (line.scanline[offset + 1] << 8) + (line.scanline[offset + 2]);
+	}
+
+	public static int getPixelARGB8(ImageLine line, int column) {
+		int offset = column * line.channels;
+		return (line.scanline[offset + 3] << 24) + (line.scanline[offset] << 16) + (line.scanline[offset + 1] << 8)
+				+ (line.scanline[offset + 2]);
+	}
+
+	public static void setPixelsRGB8(ImageLine line, int[] rgb) {
+		for (int i = 0, j = 0; i < line.imgInfo.cols; i++) {
+			line.scanline[j++] = ((rgb[i] >> 16) & 0xFF);
+			line.scanline[j++] = ((rgb[i] >> 8) & 0xFF);
+			line.scanline[j++] = ((rgb[i] & 0xFF));
+		}
+	}
+
+	public static void setPixelRGB8(ImageLine line, int col, int r, int g, int b) {
+		col *= line.channels;
+		line.scanline[col++] = r;
+		line.scanline[col++] = g;
+		line.scanline[col] = b;
+	}
+
+	public static void setPixelRGB8(ImageLine line, int col, int rgb) {
+		setPixelRGB8(line, col, (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
+	}
+
+	public static void setPixelsRGBA8(ImageLine line, int[] rgb) {
+		for (int i = 0, j = 0; i < line.imgInfo.cols; i++) {
+			line.scanline[j++] = ((rgb[i] >> 16) & 0xFF);
+			line.scanline[j++] = ((rgb[i] >> 8) & 0xFF);
+			line.scanline[j++] = ((rgb[i] & 0xFF));
+			line.scanline[j++] = ((rgb[i] >> 24) & 0xFF);
+		}
+	}
+
+	public static void setPixelRGBA8(ImageLine line, int col, int r, int g, int b, int a) {
+		col *= line.channels;
+		line.scanline[col++] = r;
+		line.scanline[col++] = g;
+		line.scanline[col++] = b;
+		line.scanline[col] = a;
+	}
+
+	public static void setPixelRGBA8(ImageLine line, int col, int rgb) {
+		setPixelRGBA8(line, col, (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF, (rgb >> 24) & 0xFF);
+	}
+
+	public static void setValD(ImageLine line, int i, double d) {
+		line.scanline[i] = double2int(line, d);
+	}
+
+	public static int interpol(int a, int b, int c, int d, double dx, double dy) {
+		// a b -> x (0-1)
+		// c d
+		//
+		double e = a * (1.0 - dx) + b * dx;
+		double f = c * (1.0 - dx) + d * dx;
+		return (int) (e * (1 - dy) + f * dy + 0.5);
+	}
+
+	public static double int2double(ImageLine line, int p) {
+		return line.bitDepth == 16 ? p / 65535.0 : p / 255.0;
+		// TODO: replace my multiplication? check for other bitdepths
+	}
+
+	public static double int2doubleClamped(ImageLine line, int p) {
+		// TODO: replace my multiplication?
+		double d = line.bitDepth == 16 ? p / 65535.0 : p / 255.0;
+		return d <= 0.0 ? 0 : (d >= 1.0 ? 1.0 : d);
+	}
+
+	public static int double2int(ImageLine line, double d) {
+		d = d <= 0.0 ? 0 : (d >= 1.0 ? 1.0 : d);
+		return line.bitDepth == 16 ? (int) (d * 65535.0 + 0.5) : (int) (d * 255.0 + 0.5); //
+	}
+
+	public static int double2intClamped(ImageLine line, double d) {
+		d = d <= 0.0 ? 0 : (d >= 1.0 ? 1.0 : d);
+		return line.bitDepth == 16 ? (int) (d * 65535.0 + 0.5) : (int) (d * 255.0 + 0.5); //
+	}
+
+	public static int clampTo_0_255(int i) {
+		return i > 255 ? 255 : (i < 0 ? 0 : i);
+	}
+
+	public static int clampTo_0_65535(int i) {
+		return i > 65535 ? 65535 : (i < 0 ? 0 : i);
+	}
+
+	public static int clampTo_128_127(int x) {
+		return x > 127 ? 127 : (x < -128 ? -128 : x);
+	}
+
+	/**
+	 * Unpacks scanline (for bitdepth 1-2-4) into a array <code>int[]</code>
+	 * <p>
+	 * You can (OPTIONALLY) pass an preallocated array, that will be filled and returned. If null, it will be allocated
+	 * <p>
+	 * If <code>scale==true<code>, it scales the value (just a bit shift) towards 0-255.
+	 * <p>
+	 * You probably should use {@link ImageLine#unpackToNewImageLine()}
+	 * 
+	 */
+	public static int[] unpack(ImageInfo imgInfo, int[] src, int[] dst, boolean scale) {
+		int len1 = imgInfo.samplesPerRow;
+		int len0 = imgInfo.samplesPerRowPacked;
+		if (dst == null || dst.length < len1)
+			dst = new int[len1];
+		if (imgInfo.packed)
+			ImageLine.unpackInplaceInt(imgInfo, src, dst, scale);
+		else
+			System.arraycopy(src, 0, dst, 0, len0);
+		return dst;
+	}
+
+	public static byte[] unpack(ImageInfo imgInfo, byte[] src, byte[] dst, boolean scale) {
+		int len1 = imgInfo.samplesPerRow;
+		int len0 = imgInfo.samplesPerRowPacked;
+		if (dst == null || dst.length < len1)
+			dst = new byte[len1];
+		if (imgInfo.packed)
+			ImageLine.unpackInplaceByte(imgInfo, src, dst, scale);
+		else
+			System.arraycopy(src, 0, dst, 0, len0);
+		return dst;
+	}
+
+	/**
+	 * Packs scanline (for bitdepth 1-2-4) from array into the scanline
+	 * <p>
+	 * If <code>scale==true<code>, it scales the value (just a bit shift).
+	 * 
+	 * You probably should use {@link ImageLine#packToNewImageLine()}
+	 */
+	public static int[] pack(ImageInfo imgInfo, int[] src, int[] dst, boolean scale) {
+		int len0 = imgInfo.samplesPerRowPacked;
+		if (dst == null || dst.length < len0)
+			dst = new int[len0];
+		if (imgInfo.packed)
+			ImageLine.packInplaceInt(imgInfo, src, dst, scale);
+		else
+			System.arraycopy(src, 0, dst, 0, len0);
+		return dst;
+	}
+
+	public static byte[] pack(ImageInfo imgInfo, byte[] src, byte[] dst, boolean scale) {
+		int len0 = imgInfo.samplesPerRowPacked;
+		if (dst == null || dst.length < len0)
+			dst = new byte[len0];
+		if (imgInfo.packed)
+			ImageLine.packInplaceByte(imgInfo, src, dst, scale);
+		else
+			System.arraycopy(src, 0, dst, 0, len0);
+		return dst;
+	}
+
+	static int getMaskForPackedFormats(int bitDepth) { // Utility function for pack/unpack
+		if (bitDepth == 4)
+			return 0xf0;
+		else if (bitDepth == 2)
+			return 0xc0;
+		else
+			return 0x80; // bitDepth == 1
+	}
+
+	static int getMaskForPackedFormatsLs(int bitDepth) { // Utility function for pack/unpack
+		if (bitDepth == 4)
+			return 0x0f;
+		else if (bitDepth == 2)
+			return 0x03;
+		else
+			return 0x01; // bitDepth == 1
+	}
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java
new file mode 100644
index 0000000..1e0ab74
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ImageLines.java
@@ -0,0 +1,101 @@
+package jogamp.opengl.util.pngj;
+
+import jogamp.opengl.util.pngj.ImageLine.SampleType;
+
+/**
+ * Wraps in a matrix a set of image rows, not necessarily contiguous - but equispaced.
+ * 
+ * The fields mirrors those of {@link ImageLine}, and you can access each row as a ImageLine backed by the matrix row,
+ * see {@link #getImageLineAtMatrixRow(int)}
+ */
+public class ImageLines {
+
+	public final ImageInfo imgInfo;
+	public final int channels;
+	public final int bitDepth;
+	public final SampleType sampleType;
+	public final boolean samplesUnpacked;
+	public final int elementsPerRow;
+	public final int rowOffset;
+	public final int nRows;
+	public final int rowStep;
+	public final int[][] scanlines;
+	public final byte[][] scanlinesb;
+
+	/**
+	 * Allocates a matrix to store {@code nRows} image rows. See {@link ImageLine} and {@link PngReader#readRowsInt()}
+	 * {@link PngReader#readRowsByte()}
+	 * 
+	 * @param imgInfo
+	 * @param stype
+	 * @param unpackedMode
+	 * @param rowOffset
+	 * @param nRows
+	 * @param rowStep
+	 */
+	public ImageLines(ImageInfo imgInfo, SampleType stype, boolean unpackedMode, int rowOffset, int nRows, int rowStep) {
+		this.imgInfo = imgInfo;
+		channels = imgInfo.channels;
+		bitDepth = imgInfo.bitDepth;
+		this.sampleType = stype;
+		this.samplesUnpacked = unpackedMode || !imgInfo.packed;
+		elementsPerRow = unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked;
+		this.rowOffset = rowOffset;
+		this.nRows = nRows;
+		this.rowStep = rowStep;
+		if (stype == SampleType.INT) {
+			scanlines = new int[nRows][elementsPerRow];
+			scanlinesb = null;
+		} else if (stype == SampleType.BYTE) {
+			scanlinesb = new byte[nRows][elementsPerRow];
+			scanlines = null;
+		} else
+			throw new PngjExceptionInternal("bad ImageLine initialization");
+	}
+
+	/**
+	 * Warning: this always returns a valid matrix row (clamping on 0 : nrows-1, and rounding down) Eg:
+	 * rowOffset=4,rowStep=2 imageRowToMatrixRow(17) returns 6 , imageRowToMatrixRow(1) returns 0
+	 */
+	public int imageRowToMatrixRow(int imrow) {
+		int r = (imrow - rowOffset) / rowStep;
+		return r < 0 ? 0 : (r < nRows ? r : nRows - 1);
+	}
+
+	/**
+	 * Same as imageRowToMatrixRow, but returns negative if invalid
+	 */
+	public int imageRowToMatrixRowStrict(int imrow) {
+		imrow -= rowOffset;
+		int mrow = imrow >= 0 && imrow % rowStep == 0 ? imrow / rowStep : -1;
+		return mrow < nRows ? mrow : -1;
+	}
+
+	/**
+	 * Converts from matrix row number (0 : nRows-1) to image row number
+	 * 
+	 * @param mrow
+	 *            Matrix row number
+	 * @return Image row number. Invalid only if mrow is invalid
+	 */
+	public int matrixRowToImageRow(int mrow) {
+		return mrow * rowStep + rowOffset;
+	}
+
+	/**
+	 * Returns a ImageLine is backed by the matrix, no allocation done
+	 * 
+	 * @param mrow
+	 *            Matrix row, from 0 to nRows This is not necessarily the image row, see
+	 *            {@link #imageRowToMatrixRow(int)} and {@link #matrixRowToImageRow(int)}
+	 * @return A new ImageLine, backed by the matrix, with the correct ('real') rownumber
+	 */
+	public ImageLine getImageLineAtMatrixRow(int mrow) {
+		if (mrow < 0 || mrow > nRows)
+			throw new PngjException("Bad row " + mrow + ". Should be positive and less than " + nRows);
+		ImageLine imline = sampleType == SampleType.INT ? new ImageLine(imgInfo, sampleType, samplesUnpacked,
+				scanlines[mrow], null) : new ImageLine(imgInfo, sampleType, samplesUnpacked, null, scanlinesb[mrow]);
+		imline.setRown(matrixRowToImageRow(mrow));
+		return imline;
+	}
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngDeinterlacer.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngDeinterlacer.java
new file mode 100644
index 0000000..e099c4f
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngDeinterlacer.java
@@ -0,0 +1,277 @@
+package jogamp.opengl.util.pngj;
+
+import java.util.Random;
+
+// you really dont' want to peek inside this
+class PngDeinterlacer {
+	private final ImageInfo imi;
+	private int pass; // 1-7
+	private int rows, cols, dY, dX, oY, oX, oXsamples, dXsamples; // at current pass
+	// current row in the virtual subsampled image; this incrementes from 0 to cols/dy 7 times
+	private int currRowSubimg = -1;
+	// in the real image, this will cycle from 0 to im.rows in different steps, 7 times
+	private int currRowReal = -1;
+
+	private final int packedValsPerPixel;
+	private final int packedMask;
+	private final int packedShift;
+
+	private int[][] imageInt; // FULL image -only used for PngWriter as temporary storage
+	private short[][] imageShort;
+	private byte[][] imageByte;
+
+	PngDeinterlacer(ImageInfo iminfo) {
+		this.imi = iminfo;
+		pass = 0;
+		if (imi.packed) {
+			packedValsPerPixel = 8 / imi.bitDepth;
+			packedShift = imi.bitDepth;
+			if (imi.bitDepth == 1)
+				packedMask = 0x80;
+			else if (imi.bitDepth == 2)
+				packedMask = 0xc0;
+			else
+				packedMask = 0xf0;
+		} else {
+			packedMask = packedShift = packedValsPerPixel = 1;// dont care
+		}
+		setPass(1);
+		setRow(0);
+	}
+
+	/** this refers to the row currRowSubimg */
+	void setRow(int n) {
+		currRowSubimg = n;
+		currRowReal = n * dY + oY;
+		if (currRowReal < 0 || currRowReal >= imi.rows)
+			throw new PngjExceptionInternal("bad row - this should not happen");
+	}
+
+	void setPass(int p) {
+		if (this.pass == p)
+			return;
+		pass = p;
+		switch (pass) {
+		case 1:
+			dY = dX = 8;
+			oX = oY = 0;
+			break;
+		case 2:
+			dY = dX = 8;
+			oX = 4;
+			oY = 0;
+			break;
+		case 3:
+			dX = 4;
+			dY = 8;
+			oX = 0;
+			oY = 4;
+			break;
+		case 4:
+			dX = dY = 4;
+			oX = 2;
+			oY = 0;
+			break;
+		case 5:
+			dX = 2;
+			dY = 4;
+			oX = 0;
+			oY = 2;
+			break;
+		case 6:
+			dX = dY = 2;
+			oX = 1;
+			oY = 0;
+			break;
+		case 7:
+			dX = 1;
+			dY = 2;
+			oX = 0;
+			oY = 1;
+			break;
+		default:
+			throw new PngjExceptionInternal("bad interlace pass" + pass);
+		}
+		rows = (imi.rows - oY) / dY + 1;
+		if ((rows - 1) * dY + oY >= imi.rows)
+			rows--; // can be 0
+		cols = (imi.cols - oX) / dX + 1;
+		if ((cols - 1) * dX + oX >= imi.cols)
+			cols--; // can be 0
+		if (cols == 0)
+			rows = 0; // really...
+		dXsamples = dX * imi.channels;
+		oXsamples = oX * imi.channels;
+	}
+
+	// notice that this is a "partial" deinterlace, it will be called several times for the same row!
+	void deinterlaceInt(int[] src, int[] dst, boolean readInPackedFormat) {
+		if (!(imi.packed && readInPackedFormat))
+			for (int i = 0, j = oXsamples; i < cols * imi.channels; i += imi.channels, j += dXsamples)
+				for (int k = 0; k < imi.channels; k++)
+					dst[j + k] = src[i + k];
+		else
+			deinterlaceIntPacked(src, dst);
+	}
+
+	// interlaced+packed = monster; this is very clumsy!
+	private void deinterlaceIntPacked(int[] src, int[] dst) {
+		int spos, smod, smask; // source byte position, bits to shift to left (01,2,3,4
+		int tpos, tmod, p, d;
+		spos = 0;
+		smask = packedMask;
+		smod = -1;
+		// can this really work?
+		for (int i = 0, j = oX; i < cols; i++, j += dX) {
+			spos = i / packedValsPerPixel;
+			smod += 1;
+			if (smod >= packedValsPerPixel)
+				smod = 0;
+			smask >>= packedShift; // the source mask cycles
+			if (smod == 0)
+				smask = packedMask;
+			tpos = j / packedValsPerPixel;
+			tmod = j % packedValsPerPixel;
+			p = src[spos] & smask;
+			d = tmod - smod;
+			if (d > 0)
+				p >>= (d * packedShift);
+			else if (d < 0)
+				p <<= ((-d) * packedShift);
+			dst[tpos] |= p;
+		}
+	}
+
+	// yes, duplication of code is evil, normally
+	void deinterlaceByte(byte[] src, byte[] dst, boolean readInPackedFormat) {
+		if (!(imi.packed && readInPackedFormat))
+			for (int i = 0, j = oXsamples; i < cols * imi.channels; i += imi.channels, j += dXsamples)
+				for (int k = 0; k < imi.channels; k++)
+					dst[j + k] = src[i + k];
+		else
+			deinterlacePackedByte(src, dst);
+	}
+
+	private void deinterlacePackedByte(byte[] src, byte[] dst) {
+		int spos, smod, smask; // source byte position, bits to shift to left (01,2,3,4
+		int tpos, tmod, p, d;
+		// what the heck are you reading here? I told you would not enjoy this. Try Dostoyevsky or Simone Weil instead
+		spos = 0;
+		smask = packedMask;
+		smod = -1;
+		// Arrays.fill(dst, 0);
+		for (int i = 0, j = oX; i < cols; i++, j += dX) {
+			spos = i / packedValsPerPixel;
+			smod += 1;
+			if (smod >= packedValsPerPixel)
+				smod = 0;
+			smask >>= packedShift; // the source mask cycles
+			if (smod == 0)
+				smask = packedMask;
+			tpos = j / packedValsPerPixel;
+			tmod = j % packedValsPerPixel;
+			p = src[spos] & smask;
+			d = tmod - smod;
+			if (d > 0)
+				p >>= (d * packedShift);
+			else if (d < 0)
+				p <<= ((-d) * packedShift);
+			dst[tpos] |= p;
+		}
+	}
+
+	/**
+	 * Is current row the last row for the lass pass??
+	 */
+	boolean isAtLastRow() {
+		return pass == 7 && currRowSubimg == rows - 1;
+	}
+
+	/**
+	 * current row number inside the "sub image"
+	 */
+	int getCurrRowSubimg() {
+		return currRowSubimg;
+	}
+
+	/**
+	 * current row number inside the "real image"
+	 */
+	int getCurrRowReal() {
+		return currRowReal;
+	}
+
+	/**
+	 * current pass number (1-7)
+	 */
+	int getPass() {
+		return pass;
+	}
+
+	/**
+	 * How many rows has the current pass?
+	 **/
+	int getRows() {
+		return rows;
+	}
+
+	/**
+	 * How many columns (pixels) are there in the current row
+	 */
+	int getCols() {
+		return cols;
+	}
+
+	public int getPixelsToRead() {
+		return getCols();
+	}
+
+	int[][] getImageInt() {
+		return imageInt;
+	}
+
+	void setImageInt(int[][] imageInt) {
+		this.imageInt = imageInt;
+	}
+
+	short[][] getImageShort() {
+		return imageShort;
+	}
+
+	void setImageShort(short[][] imageShort) {
+		this.imageShort = imageShort;
+	}
+
+	byte[][] getImageByte() {
+		return imageByte;
+	}
+
+	void setImageByte(byte[][] imageByte) {
+		this.imageByte = imageByte;
+	}
+
+	static void test() {
+		Random rand = new Random();
+		PngDeinterlacer ih = new PngDeinterlacer(new ImageInfo(rand.nextInt(35) + 1, rand.nextInt(52) + 1, 8, true));
+		int np = ih.imi.cols * ih.imi.rows;
+		System.out.println(ih.imi);
+		for (int p = 1; p <= 7; p++) {
+			ih.setPass(p);
+			for (int row = 0; row < ih.getRows(); row++) {
+				ih.setRow(row);
+				int b = ih.getCols();
+				np -= b;
+				System.out.printf("Read %d pixels. Pass:%d Realline:%d cols=%d dX=%d oX=%d last:%b\n", b, ih.pass,
+						ih.currRowReal, ih.cols, ih.dX, ih.oX, ih.isAtLastRow());
+
+			}
+		}
+		if (np != 0)
+			throw new PngjExceptionInternal("wtf??" + ih.imi);
+	}
+
+	public static void main(String[] args) {
+		test();
+	}
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngHelper.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java
similarity index 54%
rename from src/jogl/classes/jogamp/opengl/util/pngj/PngHelper.java
rename to src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java
index 1016b1b..63edf8d 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngHelper.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java
@@ -4,31 +4,46 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.charset.Charset;
-import java.util.HashSet;
-import java.util.Set;
 import java.util.zip.CRC32;
 
 /**
- * Some utility static methods.
+ * Some utility static methods for internal use.
  * <p>
- * See also <code>FileHelper</code> (if not sandboxed).
+ * Client code should not normally use this class
  * <p>
- * Client code should rarely need these methods.
  */
-public class PngHelper {
+public class PngHelperInternal {
 	/**
 	 * Default charset, used internally by PNG for several things
 	 */
 	public static Charset charsetLatin1 = Charset.forName("ISO-8859-1");
-	public static Charset charsetUTF8 = Charset.forName("UTF-8"); // only for some chunks
+	/**
+	 * UTF-8 is only used for some chunks
+	 */
+	public static Charset charsetUTF8 = Charset.forName("UTF-8");
 
 	static boolean DEBUG = false;
 
+	/**
+	 * PNG magic bytes
+	 */
+	public static byte[] getPngIdSignature() {
+		return new byte[] { -119, 80, 78, 71, 13, 10, 26, 10 };
+	}
+
+	public static int doubleToInt100000(double d) {
+		return (int) (d * 100000.0 + 0.5);
+	}
+
+	public static double intToDouble100000(int i) {
+		return i / 100000.0;
+	}
+
 	public static int readByte(InputStream is) {
 		try {
 			return is.read();
 		} catch (IOException e) {
-			throw new PngjOutputException(e);
+			throw new PngjInputException("error reading byte", e);
 		}
 	}
 
@@ -111,7 +126,7 @@ public class PngHelper {
 	}
 
 	/**
-	 * guaranteed to read exactly len bytes. throws error if it cant
+	 * guaranteed to read exactly len bytes. throws error if it can't
 	 */
 	public static void readBytes(InputStream is, byte[] b, int offset, int len) {
 		if (len == 0)
@@ -121,7 +136,7 @@ public class PngHelper {
 			while (read < len) {
 				int n = is.read(b, offset + read, len - read);
 				if (n < 1)
-					throw new RuntimeException("error reading bytes, " + n + " !=" + len);
+					throw new PngjInputException("error reading bytes, " + n + " !=" + len);
 				read += n;
 			}
 		} catch (IOException e) {
@@ -129,6 +144,21 @@ public class PngHelper {
 		}
 	}
 
+	public static void skipBytes(InputStream is, int len) {
+		byte[] buf = new byte[8192 * 4];
+		int read, remain = len;
+		try {
+			while (remain > 0) {
+				read = is.read(buf, 0, remain > buf.length ? buf.length : remain);
+				if (read < 0)
+					throw new PngjInputException("error reading (skipping) : EOF");
+				remain -= read;
+			}
+		} catch (IOException e) {
+			throw new PngjInputException("error reading (skipping)", e);
+		}
+	}
+
 	public static void writeBytes(OutputStream os, byte[] b) {
 		try {
 			os.write(b);
@@ -150,25 +180,6 @@ public class PngHelper {
 			System.out.println(msg);
 	}
 
-	public static Set<String> asSet(String... values) {
-		return new HashSet<String>(java.util.Arrays.asList(values));
-	}
-
-	public static Set<String> unionSets(Set<String> set1, Set<String> set2) {
-		Set<String> s = new HashSet<String>();
-		s.addAll(set1);
-		s.addAll(set2);
-		return s;
-	}
-
-	public static Set<String> unionSets(Set<String> set1, Set<String> set2, Set<String> set3) {
-		Set<String> s = new HashSet<String>();
-		s.addAll(set1);
-		s.addAll(set2);
-		s.addAll(set3);
-		return s;
-	}
-
 	private static final ThreadLocal<CRC32> crcProvider = new ThreadLocal<CRC32>() {
 		protected CRC32 initialValue() {
 			return new CRC32();
@@ -180,34 +191,74 @@ public class PngHelper {
 		return crcProvider.get();
 	}
 
-	static final byte[] pngIdBytes = { -119, 80, 78, 71, 13, 10, 26, 10 }; // png magic
+	// / filters
+	public static int filterRowNone(int r) {
+		return (int) (r & 0xFF);
+	}
 
-	public static double resMetersToDpi(long res) {
-		return (double) res * 0.0254;
+	public static int filterRowSub(int r, int left) {
+		return ((int) (r - left) & 0xFF);
 	}
 
-	public static long resDpiToMeters(double dpi) {
-		return (long) (dpi / 0.0254 + 0.5);
+	public static int filterRowUp(int r, int up) {
+		return ((int) (r - up) & 0xFF);
 	}
 
-	public static int doubleToInt100000(double d) {
-		return (int) (d * 100000.0 + 0.5);
+	public static int filterRowAverage(int r, int left, int up) {
+		return (r - (left + up) / 2) & 0xFF;
 	}
 
-	public static double intToDouble100000(int i) {
-		return i / 100000.0;
+	public static int filterRowPaeth(int r, int left, int up, int upleft) { // a = left, b = above, c = upper left
+		return (r - filterPaethPredictor(left, up, upleft)) & 0xFF;
 	}
 
-	public static int clampTo_0_255(int i) {
-		return i > 255 ? 255 : (i < 0 ? 0 : i);
+	public static int unfilterRowNone(int r) {
+		return (int) (r & 0xFF);
 	}
 
-	public static int clampTo_0_65535(int i) {
-		return i > 65535 ? 65535 : (i < 0 ? 0 : i);
+	public static int unfilterRowSub(int r, int left) {
+		return ((int) (r + left) & 0xFF);
+	}
+
+	public static int unfilterRowUp(int r, int up) {
+		return ((int) (r + up) & 0xFF);
+	}
+
+	public static int unfilterRowAverage(int r, int left, int up) {
+		return (r + (left + up) / 2) & 0xFF;
+	}
+
+	public static int unfilterRowPaeth(int r, int left, int up, int upleft) { // a = left, b = above, c = upper left
+		return (r + filterPaethPredictor(left, up, upleft)) & 0xFF;
+	}
+
+	final static int filterPaethPredictor(final int a, final int b, final int c) { // a = left, b = above, c = upper
+																					// left
+		// from http://www.libpng.org/pub/png/spec/1.2/PNG-Filters.html
+
+		final int p = a + b - c;// ; initial estimate
+		final int pa = p >= a ? p - a : a - p;
+		final int pb = p >= b ? p - b : b - p;
+		final int pc = p >= c ? p - c : c - p;
+		// ; return nearest of a,b,c,
+		// ; breaking ties in order a,b,c.
+		if (pa <= pb && pa <= pc)
+			return a;
+		else if (pb <= pc)
+			return b;
+		else
+			return c;
+	}
+
+	/*
+	 * we put this methods here so as to not pollute the public interface of PngReader
+	 */
+	public final static void initCrcForTests(PngReader pngr) {
+		pngr.initCrctest();
 	}
 
-	public static int clampTo_128_127(int x) {
-		return x > 127 ? 127 : (x < -128 ? -128 : x);
+	public final static long getCrctestVal(PngReader pngr) {
+		return pngr.getCrctestVal();
 	}
 
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java
index 66c4b49..6cc39b0 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java
@@ -11,23 +11,24 @@ import jogamp.opengl.util.pngj.chunks.ChunkHelper;
 
 
 /**
- * Reads IDAT chunks
+ * Reads a sequence of contiguous IDAT chunks
  */
 class PngIDatChunkInputStream extends InputStream {
 	private final InputStream inputStream;
 	private final CRC32 crcEngine;
+	private boolean checkCrc = true;
 	private int lenLastChunk;
 	private byte[] idLastChunk = new byte[4];
 	private int toReadThisChunk = 0;
 	private boolean ended = false;
-	private long offset; // offset inside inputstream
+	private long offset; // offset inside whole inputstream (counting bytes before IDAT)
 
 	// just informational
 	static class IdatChunkInfo {
 		public final int len;
-		public final int offset;
+		public final long offset;
 
-		private IdatChunkInfo(int len, int offset) {
+		private IdatChunkInfo(int len, long offset) {
 			this.len = len;
 			this.offset = offset;
 		}
@@ -38,16 +39,17 @@ class PngIDatChunkInputStream extends InputStream {
 	/**
 	 * Constructor must be called just after reading length and id of first IDAT chunk
 	 **/
-	PngIDatChunkInputStream(InputStream iStream, int lenFirstChunk, int offset) {
-		this.offset = (long) offset;
+	PngIDatChunkInputStream(InputStream iStream, int lenFirstChunk, long offset) {
+		this.offset = offset;
 		inputStream = iStream;
-		crcEngine = new CRC32();
 		this.lenLastChunk = lenFirstChunk;
 		toReadThisChunk = lenFirstChunk;
 		// we know it's a IDAT
 		System.arraycopy(ChunkHelper.b_IDAT, 0, idLastChunk, 0, 4);
+		crcEngine = new CRC32();
 		crcEngine.update(idLastChunk, 0, 4);
 		foundChunksInfo.add(new IdatChunkInfo(lenLastChunk, offset - 8));
+
 		// PngHelper.logdebug("IDAT Initial fragment: len=" + lenLastChunk);
 		if (this.lenLastChunk == 0)
 			endChunkGoForNext(); // rare, but...
@@ -58,31 +60,33 @@ class PngIDatChunkInputStream extends InputStream {
 	 */
 	@Override
 	public void close() throws IOException {
-		super.close(); // nothing
+		super.close(); // thsi does nothing
 	}
 
 	private void endChunkGoForNext() {
-		// Called after readging the last byte of chunk
+		// Called after readging the last byte of one IDAT chunk
 		// Checks CRC, and read ID from next CHUNK
 		// Those values are left in idLastChunk / lenLastChunk
 		// Skips empty IDATS
 		do {
-			int crc = PngHelper.readInt4(inputStream); //
+			int crc = PngHelperInternal.readInt4(inputStream); //
 			offset += 4;
-			int crccalc = (int) crcEngine.getValue();
-			if (lenLastChunk > 0 && crc != crccalc)
-				throw new PngjBadCrcException("error reading idat; offset: " + offset);
-			crcEngine.reset();
-			lenLastChunk = PngHelper.readInt4(inputStream);
-			if (lenLastChunk < 0)
-				throw new PngjInputException("invalid len for chunk: " + lenLastChunk);
+			if (checkCrc) {
+				int crccalc = (int) crcEngine.getValue();
+				if (lenLastChunk > 0 && crc != crccalc)
+					throw new PngjBadCrcException("error reading idat; offset: " + offset);
+				crcEngine.reset();
+			}
+			lenLastChunk = PngHelperInternal.readInt4(inputStream);
 			toReadThisChunk = lenLastChunk;
-			PngHelper.readBytes(inputStream, idLastChunk, 0, 4);
+			PngHelperInternal.readBytes(inputStream, idLastChunk, 0, 4);
 			offset += 8;
+			// found a NON IDAT chunk? this stream is ended
 			ended = !Arrays.equals(idLastChunk, ChunkHelper.b_IDAT);
 			if (!ended) {
-				foundChunksInfo.add(new IdatChunkInfo(lenLastChunk, (int) (offset - 8)));
-				crcEngine.update(idLastChunk, 0, 4);
+				foundChunksInfo.add(new IdatChunkInfo(lenLastChunk, offset - 8));
+				if (checkCrc)
+					crcEngine.update(idLastChunk, 0, 4);
 			}
 			// PngHelper.logdebug("IDAT ended. next len= " + lenLastChunk + " idat?" +
 			// (!ended));
@@ -96,8 +100,9 @@ class PngIDatChunkInputStream extends InputStream {
 	void forceChunkEnd() {
 		if (!ended) {
 			byte[] dummy = new byte[toReadThisChunk];
-			PngHelper.readBytes(inputStream, dummy, 0, toReadThisChunk);
-			crcEngine.update(dummy, 0, toReadThisChunk);
+			PngHelperInternal.readBytes(inputStream, dummy, 0, toReadThisChunk);
+			if (checkCrc)
+				crcEngine.update(dummy, 0, toReadThisChunk);
 			endChunkGoForNext();
 		}
 	}
@@ -107,11 +112,14 @@ class PngIDatChunkInputStream extends InputStream {
 	 */
 	@Override
 	public int read(byte[] b, int off, int len) throws IOException {
+		if (ended)
+			return -1; // can happen only when raw reading, see Pngreader.readAndSkipsAllRows()
 		if (toReadThisChunk == 0)
-			throw new RuntimeException("this should not happen");
+			throw new PngjExceptionInternal("this should not happen");
 		int n = inputStream.read(b, off, len >= toReadThisChunk ? toReadThisChunk : len);
 		if (n > 0) {
-			crcEngine.update(b, off, n);
+			if (checkCrc)
+				crcEngine.update(b, off, n);
 			this.offset += n;
 			toReadThisChunk -= n;
 		}
@@ -150,4 +158,11 @@ class PngIDatChunkInputStream extends InputStream {
 	boolean isEnded() {
 		return ended;
 	}
+
+	/**
+	 * Disables CRC checking. This can make reading faster
+	 */
+	void disableCrcCheck() {
+		checkCrc = false;
+	}
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java
index 8b9fa5d..411d188 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java
@@ -7,23 +7,23 @@ import jogamp.opengl.util.pngj.chunks.ChunkRaw;
 
 
 /**
- * outputs the stream for IDAT chunk , fragmented at fixed size (16384 default).
+ * outputs the stream for IDAT chunk , fragmented at fixed size (32k default).
  */
 class PngIDatChunkOutputStream extends ProgressiveOutputStream {
-	private static final int SIZE_DEFAULT = 16384;
+	private static final int SIZE_DEFAULT = 32768; // 32k
 	private final OutputStream outputStream;
 
 	PngIDatChunkOutputStream(OutputStream outputStream) {
-		this(outputStream, SIZE_DEFAULT);
+		this(outputStream, 0);
 	}
 
 	PngIDatChunkOutputStream(OutputStream outputStream, int size) {
-		super(size);
+		super(size > 0 ? size : SIZE_DEFAULT);
 		this.outputStream = outputStream;
 	}
 
 	@Override
-	public final void flushBuffer(byte[] b, int len) {
+	protected final void flushBuffer(byte[] b, int len) {
 		ChunkRaw c = new ChunkRaw(len, ChunkHelper.b_IDAT, false);
 		c.data = b;
 		c.writeChunk(outputStream);
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java
index 7343893..8cb4295 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java
@@ -1,42 +1,66 @@
 package jogamp.opengl.util.pngj;
 
+import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
+import java.util.HashSet;
+import java.util.zip.CRC32;
 import java.util.zip.InflaterInputStream;
 
-import jogamp.opengl.util.pngj.PngIDatChunkInputStream.IdatChunkInfo;
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.ImageLine.SampleType;
 import jogamp.opengl.util.pngj.chunks.ChunkHelper;
-import jogamp.opengl.util.pngj.chunks.ChunkList;
 import jogamp.opengl.util.pngj.chunks.ChunkLoadBehaviour;
 import jogamp.opengl.util.pngj.chunks.ChunkRaw;
+import jogamp.opengl.util.pngj.chunks.ChunksList;
 import jogamp.opengl.util.pngj.chunks.PngChunk;
+import jogamp.opengl.util.pngj.chunks.PngChunkIDAT;
 import jogamp.opengl.util.pngj.chunks.PngChunkIHDR;
+import jogamp.opengl.util.pngj.chunks.PngChunkSkipped;
 import jogamp.opengl.util.pngj.chunks.PngMetadata;
 
-
 /**
- * Reads a PNG image, line by line
+ * Reads a PNG image, line by line.
+ * <p>
+ * The reading sequence is as follows: <br>
+ * 1. At construction time, the header and IHDR chunk are read (basic image info) <br>
+ * 2. Afterwards you can set some additional global options. Eg. {@link #setUnpackedMode(boolean)},
+ * {@link #setCrcCheckDisabled()}.<br>
+ * 3. Optional: If you call getMetadata() or getChunksLisk() before start reading the rows, all the chunks before IDAT
+ * are automatically loaded and available <br>
+ * 4a. The rows are read onen by one of the <tt>readRowXXX</tt> methods: {@link #readRowInt(int)},
+ * {@link PngReader#readRowByte(int)}, etc, in order, from 0 to nrows-1 (you can skip or repeat rows, but not go
+ * backwards)<br>
+ * 4b. Alternatively, you can read all rows, or a subset, in a single call: {@link #readRowsInt()},
+ * {@link #readRowsByte()} ,etc. In general this consumes more memory, but for interlaced images this is equally
+ * efficient, and more so if reading a small subset of rows.<br>
+ * 5. Read of the last row auyomatically loads the trailing chunks, and ends the reader.<br>
+ * 6. end() forcibly finishes/aborts the reading and closes the stream
  */
 public class PngReader {
 	/**
 	 * Basic image info - final and inmutable.
 	 */
 	public final ImageInfo imgInfo;
-	protected final String filename; // not necesarily a file, can be a description - merely informative
 
-	private static int MAX_BYTES_CHUNKS_TO_LOAD = 640000;
-	private ChunkLoadBehaviour chunkLoadBehaviour = ChunkLoadBehaviour.LOAD_CHUNK_ALWAYS;
+	/**
+	 * not necesarily a filename, can be a description - merely informative
+	 */
+	protected final String filename;
+
+	private ChunkLoadBehaviour chunkLoadBehaviour = ChunkLoadBehaviour.LOAD_CHUNK_ALWAYS; // see setter/getter
 
-	private final InputStream is;
-	private InflaterInputStream idatIstream;
-	private PngIDatChunkInputStream iIdatCstream;
+	private boolean shouldCloseStream = true; // true: closes stream after ending - see setter/getter
 
-	protected int currentChunkGroup = -1;
-	protected int rowNum = -1; // current row number
-	private int offset = 0;
-	private int bytesChunksLoaded; // bytes loaded from anciallary chunks
+	// some performance/defensive limits
+	private long maxTotalBytesRead = 200 * 1024 * 1024; // 200MB
+	private int maxBytesMetadata = 5 * 1024 * 1024; // for ancillary chunks - see setter/getter
+	private int skipChunkMaxSize = 2 * 1024 * 1024; // chunks exceeding this size will be skipped (nor even CRC checked)
+	private String[] skipChunkIds = { "fdAT" }; // chunks with these ids will be skipped (nor even CRC checked)
+	private HashSet<String> skipChunkIdsSet; // lazily created from skipChunksById
+
+	protected final PngMetadata metadata; // this a wrapper over chunks
+	protected final ChunksList chunksList;
 
 	protected ImageLine imgLine;
 
@@ -45,12 +69,30 @@ public class PngReader {
 	protected byte[] rowbprev = null; // rowb previous
 	protected byte[] rowbfilter = null; // current line 'filtered': exactly as in uncompressed stream
 
+	// only set for interlaced PNG
+	private final boolean interlaced;
+	private final PngDeinterlacer deinterlacer;
+
+	private boolean crcEnabled = true;
+
+	// this only influences the 1-2-4 bitdepth format
+	private boolean unpackedMode = false;
 	/**
-	 * All chunks loaded. Criticals are included, except that all IDAT chunks appearance are replaced by a single
-	 * dummy-marker IDAT chunk. These might be copied to the PngWriter
+	 * Current chunk group, (0-6) already read or reading
+	 * <p>
+	 * see {@link ChunksList}
 	 */
-	private final ChunkList chunksList;
-	private final PngMetadata metadata; // this a wrapper over chunks
+	protected int currentChunkGroup = -1;
+
+	protected int rowNum = -1; // last read row number, starting from 0
+	private long offset = 0; // offset in InputStream = bytes read
+	private int bytesChunksLoaded; // bytes loaded from anciallary chunks
+
+	protected final InputStream inputStream;
+	protected InflaterInputStream idatIstream;
+	protected PngIDatChunkInputStream iIdatCstream;
+
+	protected CRC32 crctest; // If set to non null, it gets a CRC of the unfiltered bytes, to check for images equality
 
 	/**
 	 * Constructs a PngReader from an InputStream.
@@ -65,175 +107,234 @@ public class PngReader {
 	 */
 	public PngReader(InputStream inputStream, String filenameOrDescription) {
 		this.filename = filenameOrDescription == null ? "" : filenameOrDescription;
-		this.is = inputStream;
-		this.chunksList = new ChunkList(null);
-		this.metadata = new PngMetadata(chunksList, true);
-		// reads header (magic bytes)
-		byte[] pngid = new byte[PngHelper.pngIdBytes.length];
-		PngHelper.readBytes(is, pngid, 0, pngid.length);
+		this.inputStream = inputStream;
+		this.chunksList = new ChunksList(null);
+		this.metadata = new PngMetadata(chunksList);
+		// starts reading: signature
+		byte[] pngid = new byte[8];
+		PngHelperInternal.readBytes(inputStream, pngid, 0, pngid.length);
 		offset += pngid.length;
-		if (!Arrays.equals(pngid, PngHelper.pngIdBytes))
+		if (!Arrays.equals(pngid, PngHelperInternal.getPngIdSignature()))
 			throw new PngjInputException("Bad PNG signature");
 		// reads first chunk
-		currentChunkGroup = ChunkList.CHUNK_GROUP_0_IDHR;
-		int clen = PngHelper.readInt4(is);
+		currentChunkGroup = ChunksList.CHUNK_GROUP_0_IDHR;
+		int clen = PngHelperInternal.readInt4(inputStream);
 		offset += 4;
 		if (clen != 13)
-			throw new RuntimeException("IDHR chunk len != 13 ?? " + clen);
+			throw new PngjInputException("IDHR chunk len != 13 ?? " + clen);
 		byte[] chunkid = new byte[4];
-		PngHelper.readBytes(is, chunkid, 0, 4);
+		PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
 		if (!Arrays.equals(chunkid, ChunkHelper.b_IHDR))
 			throw new PngjInputException("IHDR not found as first chunk??? [" + ChunkHelper.toString(chunkid) + "]");
 		offset += 4;
-		ChunkRaw chunk = new ChunkRaw(clen, chunkid, true);
-		String chunkids = ChunkHelper.toString(chunkid);
-		offset += chunk.readChunkData(is);
-		PngChunkIHDR ihdr = (PngChunkIHDR) addChunkToList(chunk);
+		PngChunkIHDR ihdr = (PngChunkIHDR) readChunk(chunkid, clen, false);
 		boolean alpha = (ihdr.getColormodel() & 0x04) != 0;
 		boolean palette = (ihdr.getColormodel() & 0x01) != 0;
 		boolean grayscale = (ihdr.getColormodel() == 0 || ihdr.getColormodel() == 4);
+		// creates ImgInfo and imgLine, and allocates buffers
 		imgInfo = new ImageInfo(ihdr.getCols(), ihdr.getRows(), ihdr.getBitspc(), alpha, grayscale, palette);
-		imgLine = new ImageLine(imgInfo);
-		if (ihdr.getInterlaced() != 0)
-			throw new PngjUnsupportedException("PNG interlaced not supported by this library");
-		if (ihdr.getFilmeth() != 0 || ihdr.getCompmeth() != 0)
-			throw new PngjInputException("compmethod o filtermethod unrecognized");
+		// allocation: one extra byte for filter type one pixel
+		rowbfilter = new byte[imgInfo.bytesPerRow + 1];
+		rowb = new byte[imgInfo.bytesPerRow + 1];
+		rowbprev = new byte[rowb.length];
+		interlaced = ihdr.getInterlaced() == 1;
+		deinterlacer = interlaced ? new PngDeinterlacer(imgInfo) : null;
+		// some checks
+		if (ihdr.getFilmeth() != 0 || ihdr.getCompmeth() != 0 || (ihdr.getInterlaced() & 0xFFFE) != 0)
+			throw new PngjInputException("compression method o filter method or interlaced unrecognized ");
 		if (ihdr.getColormodel() < 0 || ihdr.getColormodel() > 6 || ihdr.getColormodel() == 1
 				|| ihdr.getColormodel() == 5)
 			throw new PngjInputException("Invalid colormodel " + ihdr.getColormodel());
 		if (ihdr.getBitspc() != 1 && ihdr.getBitspc() != 2 && ihdr.getBitspc() != 4 && ihdr.getBitspc() != 8
 				&& ihdr.getBitspc() != 16)
 			throw new PngjInputException("Invalid bit depth " + ihdr.getBitspc());
-		// allocation: one extra byte for filter type one pixel
-		rowbfilter = new byte[imgInfo.bytesPerRow + 1];
-		rowb = new byte[imgInfo.bytesPerRow + 1];
-		rowbprev = new byte[rowb.length];
 	}
 
-	private static class FoundChunkInfo {
-		public final String id;
-		public final int len;
-		public final int offset;
-		public final boolean loaded;
+	private boolean firstChunksNotYetRead() {
+		return currentChunkGroup < ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+	}
+
+	/**
+	 * Reads last Internally called after having read the last line. It reads extra chunks after IDAT, if present.
+	 */
+	private void readLastAndClose() {
+		// offset = iIdatCstream.getOffset();
+		if (currentChunkGroup < ChunksList.CHUNK_GROUP_5_AFTERIDAT) {
+			try {
+				idatIstream.close();
+			} catch (Exception e) {
+			}
+			readLastChunks();
+		}
+		close();
+	}
+
+	private void close() {
+		if (currentChunkGroup < ChunksList.CHUNK_GROUP_6_END) { // this could only happen if forced close
+			try {
+				idatIstream.close();
+			} catch (Exception e) {
+			}
+			currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
+		}
+		if (shouldCloseStream) {
+			try {
+				inputStream.close();
+			} catch (Exception e) {
+				throw new PngjInputException("error closing input stream!", e);
+			}
+		}
+	}
+
+	// nbytes: NOT including the filter byte. leaves result in rowb
+	private void unfilterRow(int nbytes) {
+		int ftn = rowbfilter[0];
+		FilterType ft = FilterType.getByVal(ftn);
+		if (ft == null)
+			throw new PngjInputException("Filter type " + ftn + " invalid");
+		switch (ft) {
+		case FILTER_NONE:
+			unfilterRowNone(nbytes);
+			break;
+		case FILTER_SUB:
+			unfilterRowSub(nbytes);
+			break;
+		case FILTER_UP:
+			unfilterRowUp(nbytes);
+			break;
+		case FILTER_AVERAGE:
+			unfilterRowAverage(nbytes);
+			break;
+		case FILTER_PAETH:
+			unfilterRowPaeth(nbytes);
+			break;
+		default:
+			throw new PngjInputException("Filter type " + ftn + " not implemented");
+		}
+		if (crctest != null)
+			crctest.update(rowb, 1, rowb.length - 1);
+	}
+
+	private void unfilterRowAverage(final int nbytes) {
+		int i, j, x;
+		for (j = 1 - imgInfo.bytesPixel, i = 1; i <= nbytes; i++, j++) {
+			x = j > 0 ? (rowb[j] & 0xff) : 0;
+			rowb[i] = (byte) (rowbfilter[i] + (x + (rowbprev[i] & 0xFF)) / 2);
+		}
+	}
 
-		private FoundChunkInfo(String id, int len, int offset, boolean loaded) {
-			this.id = id;
-			this.len = len;
-			this.offset = offset;
-			this.loaded = loaded;
+	private void unfilterRowNone(final int nbytes) {
+		for (int i = 1; i <= nbytes; i++) {
+			rowb[i] = (byte) (rowbfilter[i]);
 		}
+	}
 
-		public String toString() {
-			return "chunk " + id + " len=" + len + " offset=" + offset + (this.loaded ? " " : " X ");
+	private void unfilterRowPaeth(final int nbytes) {
+		int i, j, x, y;
+		for (j = 1 - imgInfo.bytesPixel, i = 1; i <= nbytes; i++, j++) {
+			x = j > 0 ? (rowb[j] & 0xFF) : 0;
+			y = j > 0 ? (rowbprev[j] & 0xFF) : 0;
+			rowb[i] = (byte) (rowbfilter[i] + PngHelperInternal.filterPaethPredictor(x, rowbprev[i] & 0xFF, y));
 		}
 	}
 
-	private PngChunk addChunkToList(ChunkRaw chunk) {
-		// this requires that the currentChunkGroup is ok
-		PngChunk chunkType = PngChunk.factory(chunk, imgInfo);
-		if (!chunkType.crit) {
-			bytesChunksLoaded += chunk.len;
+	private void unfilterRowSub(final int nbytes) {
+		int i, j;
+		for (i = 1; i <= imgInfo.bytesPixel; i++) {
+			rowb[i] = (byte) (rowbfilter[i]);
+		}
+		for (j = 1, i = imgInfo.bytesPixel + 1; i <= nbytes; i++, j++) {
+			rowb[i] = (byte) (rowbfilter[i] + rowb[j]);
 		}
-		if (bytesChunksLoaded > MAX_BYTES_CHUNKS_TO_LOAD) {
-			throw new PngjInputException("Chunk exceeded available space (" + MAX_BYTES_CHUNKS_TO_LOAD + ") chunk: "
-					+ chunk + " See PngReader.MAX_BYTES_CHUNKS_TO_LOAD\n");
+	}
+
+	private void unfilterRowUp(final int nbytes) {
+		for (int i = 1; i <= nbytes; i++) {
+			rowb[i] = (byte) (rowbfilter[i] + rowbprev[i]);
 		}
-		chunksList.appendReadChunk(chunkType, currentChunkGroup);
-		return chunkType;
 	}
 
 	/**
-	 * Reads chunks before first IDAT. Position before: after IDHR (crc included) Position after: just after the first
-	 * IDAT chunk id
-	 * 
+	 * Reads chunks before first IDAT. Normally this is called automatically
+	 * <p>
+	 * Position before: after IDHR (crc included) Position after: just after the first IDAT chunk id
+	 * <P>
 	 * This can be called several times (tentatively), it does nothing if already run
-	 * 
+	 * <p>
 	 * (Note: when should this be called? in the constructor? hardly, because we loose the opportunity to call
 	 * setChunkLoadBehaviour() and perhaps other settings before reading the first row? but sometimes we want to access
 	 * some metadata (plte, phys) before. Because of this, this method can be called explicitly but is also called
-	 * implicititly in some methods (getMetatada(), getChunks())
-	 * 
-	 **/
-	public void readFirstChunks() {
+	 * implicititly in some methods (getMetatada(), getChunksList())
+	 */
+	private final void readFirstChunks() {
 		if (!firstChunksNotYetRead())
 			return;
 		int clen = 0;
 		boolean found = false;
 		byte[] chunkid = new byte[4]; // it's important to reallocate in each iteration
-		currentChunkGroup = ChunkList.CHUNK_GROUP_1_AFTERIDHR;
+		currentChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
 		while (!found) {
-			clen = PngHelper.readInt4(is);
+			clen = PngHelperInternal.readInt4(inputStream);
 			offset += 4;
 			if (clen < 0)
 				break;
-			PngHelper.readBytes(is, chunkid, 0, 4);
+			PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
 			offset += 4;
 			if (Arrays.equals(chunkid, ChunkHelper.b_IDAT)) {
 				found = true;
-				currentChunkGroup = ChunkList.CHUNK_GROUP_4_IDAT;
+				currentChunkGroup = ChunksList.CHUNK_GROUP_4_IDAT;
 				// add dummy idat chunk to list
-				ChunkRaw chunk = new ChunkRaw(0, chunkid, false);
-				addChunkToList(chunk);
+				chunksList.appendReadChunk(new PngChunkIDAT(imgInfo, clen, offset - 8), currentChunkGroup);
 				break;
 			} else if (Arrays.equals(chunkid, ChunkHelper.b_IEND)) {
 				throw new PngjInputException("END chunk found before image data (IDAT) at offset=" + offset);
 			}
-			ChunkRaw chunk = new ChunkRaw(clen, chunkid, true);
-			String chunkids = ChunkHelper.toString(chunkid);
-			boolean loadchunk = ChunkHelper.shouldLoad(chunkids, chunkLoadBehaviour);
-			offset += chunk.readChunkData(is);
-			if (chunkids.equals(ChunkHelper.PLTE))
-				currentChunkGroup = ChunkList.CHUNK_GROUP_2_PLTE;
-			if (loadchunk)
-				addChunkToList(chunk);
-			if (chunkids.equals(ChunkHelper.PLTE))
-				currentChunkGroup = ChunkList.CHUNK_GROUP_3_AFTERPLTE;
+			if (Arrays.equals(chunkid, ChunkHelper.b_PLTE))
+				currentChunkGroup = ChunksList.CHUNK_GROUP_2_PLTE;
+			readChunk(chunkid, clen, false);
+			if (Arrays.equals(chunkid, ChunkHelper.b_PLTE))
+				currentChunkGroup = ChunksList.CHUNK_GROUP_3_AFTERPLTE;
 		}
 		int idatLen = found ? clen : -1;
 		if (idatLen < 0)
 			throw new PngjInputException("first idat chunk not found!");
-		iIdatCstream = new PngIDatChunkInputStream(is, idatLen, offset);
+		iIdatCstream = new PngIDatChunkInputStream(inputStream, idatLen, offset);
 		idatIstream = new InflaterInputStream(iIdatCstream);
+		if (!crcEnabled)
+			iIdatCstream.disableCrcCheck();
 	}
 
 	/**
 	 * Reads (and processes) chunks after last IDAT.
 	 **/
-	private void readLastChunks() {
+	void readLastChunks() {
 		// PngHelper.logdebug("idat ended? " + iIdatCstream.isEnded());
-		currentChunkGroup = ChunkList.CHUNK_GROUP_5_AFTERIDAT;
+		currentChunkGroup = ChunksList.CHUNK_GROUP_5_AFTERIDAT;
 		if (!iIdatCstream.isEnded())
 			iIdatCstream.forceChunkEnd();
 		int clen = iIdatCstream.getLenLastChunk();
 		byte[] chunkid = iIdatCstream.getIdLastChunk();
 		boolean endfound = false;
 		boolean first = true;
-		boolean ignore = false;
+		boolean skip = false;
 		while (!endfound) {
-			ignore = false;
+			skip = false;
 			if (!first) {
-				clen = PngHelper.readInt4(is);
+				clen = PngHelperInternal.readInt4(inputStream);
 				offset += 4;
 				if (clen < 0)
-					throw new PngjInputException("bad len " + clen);
-				PngHelper.readBytes(is, chunkid, 0, 4);
+					throw new PngjInputException("bad chuck len " + clen);
+				PngHelperInternal.readBytes(inputStream, chunkid, 0, 4);
 				offset += 4;
 			}
 			first = false;
 			if (Arrays.equals(chunkid, ChunkHelper.b_IDAT)) {
-				// PngHelper.logdebug("extra IDAT chunk len - ignoring : ");
-				ignore = true;
+				skip = true; // extra dummy (empty?) idat chunk, it can happen, ignore it
 			} else if (Arrays.equals(chunkid, ChunkHelper.b_IEND)) {
-				currentChunkGroup = ChunkList.CHUNK_GROUP_6_END;
+				currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
 				endfound = true;
 			}
-			ChunkRaw chunk = new ChunkRaw(clen, chunkid, true);
-			String chunkids = ChunkHelper.toString(chunkid);
-			boolean loadchunk = ChunkHelper.shouldLoad(chunkids, chunkLoadBehaviour);
-			offset += chunk.readChunkData(is);
-			if (loadchunk && !ignore) {
-				addChunkToList(chunk);
-			}
+			readChunk(chunkid, clen, skip);
 		}
 		if (!endfound)
 			throw new PngjInputException("end chunk not found - offset=" + offset);
@@ -241,173 +342,597 @@ public class PngReader {
 	}
 
 	/**
-	 * Calls <code>readRow(int[] buffer, int nrow)</code> using internal ImageLine as buffer. This doesn't allocate or
-	 * copy anything.
+	 * Reads chunkd from input stream, adds to ChunksList, and returns it. If it's skipped, a PngChunkSkipped object is
+	 * created
+	 */
+	private PngChunk readChunk(byte[] chunkid, int clen, boolean skipforced) {
+		if (clen < 0)
+			throw new PngjInputException("invalid chunk lenght: " + clen);
+		// skipChunksByIdSet is created lazyly, if fist IHDR has already been read
+		if (skipChunkIdsSet == null && currentChunkGroup > ChunksList.CHUNK_GROUP_0_IDHR)
+			skipChunkIdsSet = new HashSet<String>(Arrays.asList(skipChunkIds));
+		String chunkidstr = ChunkHelper.toString(chunkid);
+		boolean critical = ChunkHelper.isCritical(chunkidstr);
+		PngChunk pngChunk = null;
+		boolean skip = skipforced;
+		if (maxTotalBytesRead > 0 && clen + offset > maxTotalBytesRead)
+			throw new PngjInputException("Maximum total bytes to read exceeeded: " + maxTotalBytesRead + " offset:"
+					+ offset + " clen=" + clen);
+		// an ancillary chunks can be skipped because of several reasons:
+		if (currentChunkGroup > ChunksList.CHUNK_GROUP_0_IDHR && !critical)
+			skip = skip || (skipChunkMaxSize > 0 && clen >= skipChunkMaxSize) || skipChunkIdsSet.contains(chunkidstr)
+					|| (maxBytesMetadata > 0 && clen > maxBytesMetadata - bytesChunksLoaded)
+					|| !ChunkHelper.shouldLoad(chunkidstr, chunkLoadBehaviour);
+		if (skip) {
+			PngHelperInternal.skipBytes(inputStream, clen);
+			PngHelperInternal.readInt4(inputStream); // skip - we dont call PngHelperInternal.skipBytes(inputStream,
+														// clen + 4) for risk of overflow
+			pngChunk = new PngChunkSkipped(chunkidstr, imgInfo, clen);
+		} else {
+			ChunkRaw chunk = new ChunkRaw(clen, chunkid, true);
+			chunk.readChunkData(inputStream, crcEnabled || critical);
+			pngChunk = PngChunk.factory(chunk, imgInfo);
+			if (!pngChunk.crit)
+				bytesChunksLoaded += chunk.len;
+		}
+		pngChunk.setOffset(offset - 8L);
+		chunksList.appendReadChunk(pngChunk, currentChunkGroup);
+		offset += clen + 4L;
+		return pngChunk;
+	}
+
+	/**
+	 * Logs/prints a warning.
+	 * <p>
+	 * The default behaviour is print to stderr, but it can be overriden.
+	 * <p>
+	 * This happens rarely - most errors are fatal.
+	 */
+	protected void logWarn(String warn) {
+		System.err.println(warn);
+	}
+
+	/**
+	 * @see #setChunkLoadBehaviour(ChunkLoadBehaviour)
+	 */
+	public ChunkLoadBehaviour getChunkLoadBehaviour() {
+		return chunkLoadBehaviour;
+	}
+
+	/**
+	 * Determines which ancillary chunks (metada) are to be loaded
+	 * 
+	 * @param chunkLoadBehaviour
+	 *            {@link ChunkLoadBehaviour}
+	 */
+	public void setChunkLoadBehaviour(ChunkLoadBehaviour chunkLoadBehaviour) {
+		this.chunkLoadBehaviour = chunkLoadBehaviour;
+	}
+
+	/**
+	 * All loaded chunks (metada). If we have not yet end reading the image, this will include only the chunks before
+	 * the pixels data (IDAT)
+	 * <p>
+	 * Critical chunks are included, except that all IDAT chunks appearance are replaced by a single dummy-marker IDAT
+	 * chunk. These might be copied to the PngWriter
+	 * <p>
+	 * 
+	 * @see #getMetadata()
+	 */
+	public ChunksList getChunksList() {
+		if (firstChunksNotYetRead())
+			readFirstChunks();
+		return chunksList;
+	}
+
+	int getCurrentChunkGroup() {
+		return currentChunkGroup;
+	}
+
+	/**
+	 * High level wrapper over chunksList
 	 * 
-	 * @return The ImageLine that also is available inside this object.
+	 * @see #getChunksList()
+	 */
+	public PngMetadata getMetadata() {
+		if (firstChunksNotYetRead())
+			readFirstChunks();
+		return metadata;
+	}
+
+	/**
+	 * If called for first time, calls readRowInt. Elsewhere, it calls the appropiate readRowInt/readRowByte
+	 * <p>
+	 * In general, specifying the concrete readRowInt/readRowByte is preferrable
+	 * 
+	 * @see #readRowInt(int) {@link #readRowByte(int)}
 	 */
 	public ImageLine readRow(int nrow) {
-		readRow(imgLine.scanline, nrow);
-		imgLine.filterUsed = FilterType.getByVal(rowbfilter[0]);
+		if (imgLine == null)
+			imgLine = new ImageLine(imgInfo, SampleType.INT, unpackedMode);
+		return imgLine.sampleType != SampleType.BYTE ? readRowInt(nrow) : readRowByte(nrow);
+	}
+
+	/**
+	 * Reads the row as INT, storing it in the {@link #imgLine} property and returning it.
+	 * 
+	 * The row must be greater or equal than the last read row.
+	 * 
+	 * @param nrow
+	 *            Row number, from 0 to rows-1. Increasing order.
+	 * @return ImageLine object, also available as field. Data is in {@link ImageLine#scanline} (int) field.
+	 */
+	public ImageLine readRowInt(int nrow) {
+		if (imgLine == null)
+			imgLine = new ImageLine(imgInfo, SampleType.INT, unpackedMode);
+		if (imgLine.getRown() == nrow) // already read
+			return imgLine;
+		readRowInt(imgLine.scanline, nrow);
+		imgLine.setFilterUsed(FilterType.getByVal(rowbfilter[0]));
+		imgLine.setRown(nrow);
+		return imgLine;
+	}
+
+	/**
+	 * Reads the row as BYTES, storing it in the {@link #imgLine} property and returning it.
+	 * 
+	 * The row must be greater or equal than the last read row. This method allows to pass the same row that was last
+	 * read.
+	 * 
+	 * @param nrow
+	 *            Row number, from 0 to rows-1. Increasing order.
+	 * @return ImageLine object, also available as field. Data is in {@link ImageLine#scanlineb} (byte) field.
+	 */
+	public ImageLine readRowByte(int nrow) {
+		if (imgLine == null)
+			imgLine = new ImageLine(imgInfo, SampleType.BYTE, unpackedMode);
+		if (imgLine.getRown() == nrow) // already read
+			return imgLine;
+		readRowByte(imgLine.scanlineb, nrow);
+		imgLine.setFilterUsed(FilterType.getByVal(rowbfilter[0]));
 		imgLine.setRown(nrow);
 		return imgLine;
 	}
 
 	/**
+	 * @see #readRowInt(int[], int)
+	 */
+	public final int[] readRow(int[] buffer, final int nrow) {
+		return readRowInt(buffer, nrow);
+	}
+
+	/**
 	 * Reads a line and returns it as a int[] array.
+	 * <p>
+	 * You can pass (optionally) a prealocatted buffer.
+	 * <p>
+	 * If the bitdepth is less than 8, the bytes are packed - unless {@link #unpackedMode} is true.
+	 * 
+	 * @param buffer
+	 *            Prealocated buffer, or null.
+	 * @param nrow
+	 *            Row number (0 is top). Most be strictly greater than the last read row.
 	 * 
+	 * @return The scanline in the same passwd buffer if it was allocated, a newly allocated one otherwise
+	 */
+	public final int[] readRowInt(int[] buffer, final int nrow) {
+		if (buffer == null)
+			buffer = new int[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+		if (!interlaced) {
+			if (nrow <= rowNum)
+				throw new PngjInputException("rows must be read in increasing order: " + nrow);
+			int bytesread = 0;
+			while (rowNum < nrow)
+				bytesread = readRowRaw(rowNum + 1); // read rows, perhaps skipping if necessary
+			decodeLastReadRowToInt(buffer, bytesread);
+		} else { // interlaced
+			if (deinterlacer.getImageInt() == null)
+				deinterlacer.setImageInt(readRowsInt().scanlines); // read all image and store it in deinterlacer
+			System.arraycopy(deinterlacer.getImageInt()[nrow], 0, buffer, 0, unpackedMode ? imgInfo.samplesPerRow
+					: imgInfo.samplesPerRowPacked);
+		}
+		return buffer;
+	}
+
+	/**
+	 * Reads a line and returns it as a byte[] array.
+	 * <p>
 	 * You can pass (optionally) a prealocatted buffer.
+	 * <p>
+	 * If the bitdepth is less than 8, the bytes are packed - unless {@link #unpackedMode} is true. <br>
+	 * If the bitdepth is 16, the least significant byte is lost.
+	 * <p>
 	 * 
 	 * @param buffer
 	 *            Prealocated buffer, or null.
 	 * @param nrow
-	 *            Row number (0 is top). This is mostly for checking, because this library reads rows in sequence.
+	 *            Row number (0 is top). Most be strictly greater than the last read row.
 	 * 
 	 * @return The scanline in the same passwd buffer if it was allocated, a newly allocated one otherwise
 	 */
-	public int[] readRow(int[] buffer, int nrow) {
-		if (nrow < 0 || nrow >= imgInfo.rows)
-			throw new PngjInputException("invalid line");
-		if (nrow != rowNum + 1)
-			throw new PngjInputException("invalid line (expected: " + (rowNum + 1));
+	public final byte[] readRowByte(byte[] buffer, final int nrow) {
+		if (buffer == null)
+			buffer = new byte[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+		if (!interlaced) {
+			if (nrow <= rowNum)
+				throw new PngjInputException("rows must be read in increasing order: " + nrow);
+			int bytesread = 0;
+			while (rowNum < nrow)
+				bytesread = readRowRaw(rowNum + 1); // read rows, perhaps skipping if necessary
+			decodeLastReadRowToByte(buffer, bytesread);
+		} else { // interlaced
+			if (deinterlacer.getImageByte() == null)
+				deinterlacer.setImageByte(readRowsByte().scanlinesb); // read all image and store it in deinterlacer
+			System.arraycopy(deinterlacer.getImageByte()[nrow], 0, buffer, 0, unpackedMode ? imgInfo.samplesPerRow
+					: imgInfo.samplesPerRowPacked);
+		}
+		return buffer;
+	}
+
+	/**
+	 * @param nrow
+	 * @deprecated Now {@link #readRow(int)} implements the same funcion. This method will be removed in future releases
+	 */
+	public ImageLine getRow(int nrow) {
+		return readRow(nrow);
+	}
+
+	private void decodeLastReadRowToInt(int[] buffer, int bytesRead) {
+		if (imgInfo.bitDepth <= 8)
+			for (int i = 0, j = 1; i < bytesRead; i++)
+				buffer[i] = (rowb[j++] & 0xFF); // http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html
+		else
+			for (int i = 0, j = 1; j <= bytesRead; i++)
+				buffer[i] = ((rowb[j++] & 0xFF) << 8) + (rowb[j++] & 0xFF); // 16 bitspc
+		if (imgInfo.packed && unpackedMode)
+			ImageLine.unpackInplaceInt(imgInfo, buffer, buffer, false);
+	}
+
+	private void decodeLastReadRowToByte(byte[] buffer, int bytesRead) {
+		if (imgInfo.bitDepth <= 8)
+			System.arraycopy(rowb, 1, buffer, 0, bytesRead);
+		else
+			for (int i = 0, j = 1; j < bytesRead; i++, j += 2)
+				buffer[i] = rowb[j];// 16 bits in 1 byte: this discards the LSB!!!
+		if (imgInfo.packed && unpackedMode)
+			ImageLine.unpackInplaceByte(imgInfo, buffer, buffer, false);
+	}
+
+	/**
+	 * Reads a set of lines and returns it as a ImageLines object, which wraps matrix. Internally it reads all lines,
+	 * but decodes and stores only the wanted ones. This starts and ends the reading, and cannot be combined with other
+	 * reading methods.
+	 * <p>
+	 * This it's more efficient (speed an memory) that doing calling readRowInt() for each desired line only if the
+	 * image is interlaced.
+	 * <p>
+	 * Notice that the columns in the matrix is not the pixel width of the image, but rather pixels x channels
+	 * 
+	 * @see #readRowInt(int) to read about the format of each row
+	 * 
+	 * @param rowOffset
+	 *            Number of rows to be skipped
+	 * @param nRows
+	 *            Total number of rows to be read. -1: read all available
+	 * @param rowStep
+	 *            Row increment. If 1, we read consecutive lines; if 2, we read even/odd lines, etc
+	 * @return Set of lines as a ImageLines, which wraps a matrix
+	 */
+	public ImageLines readRowsInt(int rowOffset, int nRows, int rowStep) {
+		if (nRows < 0)
+			nRows = (imgInfo.rows - rowOffset) / rowStep;
+		if (rowStep < 1 || rowOffset < 0 || nRows * rowStep + rowOffset > imgInfo.rows)
+			throw new PngjInputException("bad args");
+		ImageLines imlines = new ImageLines(imgInfo, SampleType.INT, unpackedMode, rowOffset, nRows, rowStep);
+		if (!interlaced) {
+			for (int j = 0; j < imgInfo.rows; j++) {
+				int bytesread = readRowRaw(j); // read and perhaps discards
+				int mrow = imlines.imageRowToMatrixRowStrict(j);
+				if (mrow >= 0)
+					decodeLastReadRowToInt(imlines.scanlines[mrow], bytesread);
+			}
+		} else { // and now, for something completely different (interlaced)
+			int[] buf = new int[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+			for (int p = 1; p <= 7; p++) {
+				deinterlacer.setPass(p);
+				for (int i = 0; i < deinterlacer.getRows(); i++) {
+					int bytesread = readRowRaw(i);
+					int j = deinterlacer.getCurrRowReal();
+					int mrow = imlines.imageRowToMatrixRowStrict(j);
+					if (mrow >= 0) {
+						decodeLastReadRowToInt(buf, bytesread);
+						deinterlacer.deinterlaceInt(buf, imlines.scanlines[mrow], !unpackedMode);
+					}
+				}
+			}
+		}
+		end();
+		return imlines;
+	}
+
+	/**
+	 * Same as readRowsInt(0, imgInfo.rows, 1)
+	 * 
+	 * @see #readRowsInt(int, int, int)
+	 */
+	public ImageLines readRowsInt() {
+		return readRowsInt(0, imgInfo.rows, 1);
+	}
+
+	/**
+	 * Reads a set of lines and returns it as a ImageLines object, which wrapas a byte[][] matrix. Internally it reads
+	 * all lines, but decodes and stores only the wanted ones. This starts and ends the reading, and cannot be combined
+	 * with other reading methods.
+	 * <p>
+	 * This it's more efficient (speed an memory) that doing calling readRowByte() for each desired line only if the
+	 * image is interlaced.
+	 * <p>
+	 * Notice that the columns in the matrix is not the pixel width of the image, but rather pixels x channels
+	 * 
+	 * @see #readRowByte(int) to read about the format of each row. Notice that if the bitdepth is 16 this will lose
+	 *      information
+	 * 
+	 * @param rowOffset
+	 *            Number of rows to be skipped
+	 * @param nRows
+	 *            Total number of rows to be read. -1: read all available
+	 * @param rowStep
+	 *            Row increment. If 1, we read consecutive lines; if 2, we read even/odd lines, etc
+	 * @return Set of lines as a matrix
+	 */
+	public ImageLines readRowsByte(int rowOffset, int nRows, int rowStep) {
+		if (nRows < 0)
+			nRows = (imgInfo.rows - rowOffset) / rowStep;
+		if (rowStep < 1 || rowOffset < 0 || nRows * rowStep + rowOffset > imgInfo.rows)
+			throw new PngjInputException("bad args");
+		ImageLines imlines = new ImageLines(imgInfo, SampleType.BYTE, unpackedMode, rowOffset, nRows, rowStep);
+		if (!interlaced) {
+			for (int j = 0; j < imgInfo.rows; j++) {
+				int bytesread = readRowRaw(j); // read and perhaps discards
+				int mrow = imlines.imageRowToMatrixRowStrict(j);
+				if (mrow >= 0)
+					decodeLastReadRowToByte(imlines.scanlinesb[mrow], bytesread);
+			}
+		} else { // and now, for something completely different (interlaced)
+			byte[] buf = new byte[unpackedMode ? imgInfo.samplesPerRow : imgInfo.samplesPerRowPacked];
+			for (int p = 1; p <= 7; p++) {
+				deinterlacer.setPass(p);
+				for (int i = 0; i < deinterlacer.getRows(); i++) {
+					int bytesread = readRowRaw(i);
+					int j = deinterlacer.getCurrRowReal();
+					int mrow = imlines.imageRowToMatrixRowStrict(j);
+					if (mrow >= 0) {
+						decodeLastReadRowToByte(buf, bytesread);
+						deinterlacer.deinterlaceByte(buf, imlines.scanlinesb[mrow], !unpackedMode);
+					}
+				}
+			}
+		}
+		end();
+		return imlines;
+	}
+
+	/**
+	 * Same as readRowsByte(0, imgInfo.rows, 1)
+	 * 
+	 * @see #readRowsByte(int, int, int)
+	 */
+	public ImageLines readRowsByte() {
+		return readRowsByte(0, imgInfo.rows, 1);
+	}
+
+	/*
+	 * For the interlaced case, nrow indicates the subsampled image - the pass must be set already.
+	 * 
+	 * This must be called in strict order, both for interlaced or no interlaced.
+	 * 
+	 * Updates rowNum.
+	 * 
+	 * Leaves raw result in rowb
+	 * 
+	 * Returns bytes actually read (not including the filter byte)
+	 */
+	private int readRowRaw(final int nrow) {
+		//
 		if (nrow == 0 && firstChunksNotYetRead())
 			readFirstChunks();
-		rowNum++;
-		if (buffer == null || buffer.length < imgInfo.samplesPerRowP)
-			buffer = new int[imgInfo.samplesPerRowP];
-		// swap
+		if (nrow == 0 && interlaced)
+			Arrays.fill(rowb, (byte) 0); // new subimage: reset filters: this is enough, see the swap that happens lines
+											// below
+		int bytesRead = imgInfo.bytesPerRow; // NOT including the filter byte
+		if (interlaced) {
+			if (nrow < 0 || nrow > deinterlacer.getRows() || (nrow != 0 && nrow != deinterlacer.getCurrRowSubimg() + 1))
+				throw new PngjInputException("invalid row in interlaced mode: " + nrow);
+			deinterlacer.setRow(nrow);
+			bytesRead = (imgInfo.bitspPixel * deinterlacer.getPixelsToRead() + 7) / 8;
+			if (bytesRead < 1)
+				throw new PngjExceptionInternal("wtf??");
+		} else { // check for non interlaced
+			if (nrow < 0 || nrow >= imgInfo.rows || nrow != rowNum + 1)
+				throw new PngjInputException("invalid row: " + nrow);
+		}
+		rowNum = nrow;
+		// swap buffers
 		byte[] tmp = rowb;
 		rowb = rowbprev;
 		rowbprev = tmp;
 		// loads in rowbfilter "raw" bytes, with filter
-		PngHelper.readBytes(idatIstream, rowbfilter, 0, rowbfilter.length);
+		PngHelperInternal.readBytes(idatIstream, rowbfilter, 0, bytesRead + 1);
+		offset = iIdatCstream.getOffset();
+		if (offset < 0)
+			throw new PngjExceptionInternal("bad offset ??" + offset);
+		if (maxTotalBytesRead > 0 && offset >= maxTotalBytesRead)
+			throw new PngjInputException("Reading IDAT: Maximum total bytes to read exceeeded: " + maxTotalBytesRead
+					+ " offset:" + offset);
 		rowb[0] = 0;
-		unfilterRow();
+		unfilterRow(bytesRead);
 		rowb[0] = rowbfilter[0];
-		convertRowFromBytes(buffer);
-		return buffer;
+		if ((rowNum == imgInfo.rows - 1 && !interlaced) || (interlaced && deinterlacer.isAtLastRow()))
+			readLastAndClose();
+		return bytesRead;
 	}
 
 	/**
-	 * This should be called after having read the last line. It reads extra chunks after IDAT, if present.
+	 * Reads all the (remaining) file, skipping the pixels data. This is much more efficient that calling readRow(),
+	 * specially for big files (about 10 times faster!), because it doesn't even decompress the IDAT stream and disables
+	 * CRC check Use this if you are not interested in reading pixels,only metadata.
 	 */
-	public void end() {
-		offset = (int) iIdatCstream.getOffset();
-		try {
-			idatIstream.close();
-		} catch (Exception e) {
-		}
-		readLastChunks();
+	public void readSkippingAllRows() {
+		if (firstChunksNotYetRead())
+			readFirstChunks();
+		// we read directly from the compressed stream, we dont decompress nor chec CRC
+		iIdatCstream.disableCrcCheck();
 		try {
-			is.close();
-		} catch (Exception e) {
-			throw new PngjInputException("error closing input stream!", e);
+			int r;
+			do {
+				r = iIdatCstream.read(rowbfilter, 0, rowbfilter.length);
+			} while (r >= 0);
+		} catch (IOException e) {
+			throw new PngjInputException("error in raw read of IDAT", e);
 		}
+		offset = iIdatCstream.getOffset();
+		if (offset < 0)
+			throw new PngjExceptionInternal("bad offset ??" + offset);
+		if (maxTotalBytesRead > 0 && offset >= maxTotalBytesRead)
+			throw new PngjInputException("Reading IDAT: Maximum total bytes to read exceeeded: " + maxTotalBytesRead
+					+ " offset:" + offset);
+		readLastAndClose();
 	}
 
-	private void convertRowFromBytes(int[] buffer) {
-		// http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html
-		int i, j;
-		if (imgInfo.bitDepth <= 8) {
-			for (i = 0, j = 1; i < imgInfo.samplesPerRowP; i++) {
-				buffer[i] = (rowb[j++] & 0xFF);
-			}
-		} else { // 16 bitspc
-			for (i = 0, j = 1; i < imgInfo.samplesPerRowP; i++) {
-				buffer[i] = ((rowb[j++] & 0xFF) << 8) + (rowb[j++] & 0xFF);
-			}
-		}
+	/**
+	 * Set total maximum bytes to read (0: unlimited; default: 200MB). <br>
+	 * These are the bytes read (not loaded) in the input stream. If exceeded, an exception will be thrown.
+	 */
+	public void setMaxTotalBytesRead(long maxTotalBytesToRead) {
+		this.maxTotalBytesRead = maxTotalBytesToRead;
 	}
 
-	private void unfilterRow() {
-		int ftn = rowbfilter[0];
-		FilterType ft = FilterType.getByVal(ftn);
-		if (ft == null)
-			throw new PngjInputException("Filter type " + ftn + " invalid");
-		switch (ft) {
-		case FILTER_NONE:
-			unfilterRowNone();
-			break;
-		case FILTER_SUB:
-			unfilterRowSub();
-			break;
-		case FILTER_UP:
-			unfilterRowUp();
-			break;
-		case FILTER_AVERAGE:
-			unfilterRowAverage();
-			break;
-		case FILTER_PAETH:
-			unfilterRowPaeth();
-			break;
-		default:
-			throw new PngjInputException("Filter type " + ftn + " not implemented");
-		}
+	/**
+	 * @return Total maximum bytes to read.
+	 */
+	public long getMaxTotalBytesRead() {
+		return maxTotalBytesRead;
 	}
 
-	private void unfilterRowNone() {
-		for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
-			rowb[i] = (byte) (rowbfilter[i]);
-		}
+	/**
+	 * Set total maximum bytes to load from ancillary chunks (0: unlimited; default: 5Mb).<br>
+	 * If exceeded, some chunks will be skipped
+	 */
+	public void setMaxBytesMetadata(int maxBytesChunksToLoad) {
+		this.maxBytesMetadata = maxBytesChunksToLoad;
 	}
 
-	private void unfilterRowSub() {
-		int i, j;
-		for (i = 1; i <= imgInfo.bytesPixel; i++) {
-			rowb[i] = (byte) (rowbfilter[i]);
-		}
-		for (j = 1, i = imgInfo.bytesPixel + 1; i <= imgInfo.bytesPerRow; i++, j++) {
-			rowb[i] = (byte) (rowbfilter[i] + rowb[j]);
-		}
+	/**
+	 * @return Total maximum bytes to load from ancillary ckunks.
+	 */
+	public int getMaxBytesMetadata() {
+		return maxBytesMetadata;
 	}
 
-	private void unfilterRowUp() {
-		for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
-			rowb[i] = (byte) (rowbfilter[i] + rowbprev[i]);
-		}
+	/**
+	 * Set maximum size in bytes for individual ancillary chunks (0: unlimited; default: 2MB). <br>
+	 * Chunks exceeding this length will be skipped (the CRC will not be checked) and the chunk will be saved as a
+	 * PngChunkSkipped object. See also setSkipChunkIds
+	 */
+	public void setSkipChunkMaxSize(int skipChunksBySize) {
+		this.skipChunkMaxSize = skipChunksBySize;
 	}
 
-	private void unfilterRowAverage() {
-		int i, j, x;
-		for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imgInfo.bytesPerRow; i++, j++) {
-			x = j > 0 ? (rowb[j] & 0xff) : 0;
-			rowb[i] = (byte) (rowbfilter[i] + (x + (rowbprev[i] & 0xFF)) / 2);
-		}
+	/**
+	 * @return maximum size in bytes for individual ancillary chunks.
+	 */
+	public int getSkipChunkMaxSize() {
+		return skipChunkMaxSize;
 	}
 
-	private void unfilterRowPaeth() {
-		int i, j, x, y;
-		for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imgInfo.bytesPerRow; i++, j++) {
-			x = j > 0 ? (rowb[j] & 0xFF) : 0;
-			y = j > 0 ? (rowbprev[j] & 0xFF) : 0;
-			rowb[i] = (byte) (rowbfilter[i] + FilterType.filterPaethPredictor(x, rowbprev[i] & 0xFF, y));
-		}
+	/**
+	 * Chunks ids to be skipped. <br>
+	 * These chunks will be skipped (the CRC will not be checked) and the chunk will be saved as a PngChunkSkipped
+	 * object. See also setSkipChunkMaxSize
+	 */
+	public void setSkipChunkIds(String[] skipChunksById) {
+		this.skipChunkIds = skipChunksById == null ? new String[] {} : skipChunksById;
 	}
 
-	public ChunkLoadBehaviour getChunkLoadBehaviour() {
-		return chunkLoadBehaviour;
+	/**
+	 * @return Chunk-IDs to be skipped.
+	 */
+	public String[] getSkipChunkIds() {
+		return skipChunkIds;
 	}
 
-	public void setChunkLoadBehaviour(ChunkLoadBehaviour chunkLoadBehaviour) {
-		this.chunkLoadBehaviour = chunkLoadBehaviour;
+	/**
+	 * if true, input stream will be closed after ending read
+	 * <p>
+	 * default=true
+	 */
+	public void setShouldCloseStream(boolean shouldCloseStream) {
+		this.shouldCloseStream = shouldCloseStream;
 	}
 
-	private boolean firstChunksNotYetRead() {
-		return currentChunkGroup < ChunkList.CHUNK_GROUP_1_AFTERIDHR;
+	/**
+	 * Normally this does nothing, but it can be used to force a premature closing. Its recommended practice to call it
+	 * after reading the image pixels.
+	 */
+	public void end() {
+		if (currentChunkGroup < ChunksList.CHUNK_GROUP_6_END)
+			close();
 	}
 
-	public ChunkList getChunksList() {
-		if (firstChunksNotYetRead())
-			readFirstChunks();
-		return chunksList;
+	/**
+	 * Interlaced PNG is accepted -though not welcomed- now...
+	 */
+	public boolean isInterlaced() {
+		return interlaced;
 	}
 
-	public PngMetadata getMetadata() {
-		if (firstChunksNotYetRead())
-			readFirstChunks();
-		return metadata;
+	/**
+	 * set/unset "unpackedMode"<br>
+	 * If false (default) packed types (bitdepth=1,2 or 4) will keep several samples packed in one element (byte or int) <br>
+	 * If true, samples will be unpacked on reading, and each element in the scanline will be sample. This implies more
+	 * processing and memory, but it's the most efficient option if you intend to read individual pixels. <br>
+	 * This option should only be set before start reading.
+	 * 
+	 * @param unPackedMode
+	 */
+	public void setUnpackedMode(boolean unPackedMode) {
+		this.unpackedMode = unPackedMode;
+	}
+
+	/**
+	 * @see PngReader#setUnpackedMode(boolean)
+	 */
+	public boolean isUnpackedMode() {
+		return unpackedMode;
+	}
+
+	/**
+	 * Disables the CRC integrity check in IDAT chunks and ancillary chunks, this gives a slight increase in reading
+	 * speed for big files
+	 */
+	public void setCrcCheckDisabled() {
+		crcEnabled = false;
+	}
+
+	/**
+	 * Just for testing. TO be called after ending reading, only if initCrctest() was called before start
+	 * 
+	 * @return CRC of the raw pixels values
+	 */
+	long getCrctestVal() {
+		return crctest.getValue();
+	}
+
+	/**
+	 * Inits CRC object and enables CRC calculation
+	 */
+	void initCrctest() {
+		this.crctest = new CRC32();
 	}
 
+	/**
+	 * Basic info, for debugging.
+	 */
 	public String toString() { // basic info
 		return "filename=" + filename + " " + imgInfo.toString();
 	}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java
index ee8472b..601cd96 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java
@@ -7,51 +7,84 @@ import java.util.List;
 import java.util.zip.Deflater;
 import java.util.zip.DeflaterOutputStream;
 
+import jogamp.opengl.util.pngj.ImageLine.SampleType;
 import jogamp.opengl.util.pngj.chunks.ChunkCopyBehaviour;
 import jogamp.opengl.util.pngj.chunks.ChunkHelper;
-import jogamp.opengl.util.pngj.chunks.ChunkList;
+import jogamp.opengl.util.pngj.chunks.ChunksList;
+import jogamp.opengl.util.pngj.chunks.ChunksListForWrite;
 import jogamp.opengl.util.pngj.chunks.PngChunk;
 import jogamp.opengl.util.pngj.chunks.PngChunkIEND;
 import jogamp.opengl.util.pngj.chunks.PngChunkIHDR;
+import jogamp.opengl.util.pngj.chunks.PngChunkSkipped;
 import jogamp.opengl.util.pngj.chunks.PngChunkTextVar;
 import jogamp.opengl.util.pngj.chunks.PngMetadata;
 
-
 /**
- * Writes a PNG image, line by line.
+ * Writes a PNG image
  */
 public class PngWriter {
 
 	public final ImageInfo imgInfo;
 
-	protected int compLevel = 6; // zip compression level 0 - 9
-	private int deflaterStrategy = Deflater.FILTERED;
-	protected FilterWriteStrategy filterStrat;
+	private final String filename; // optional, can be a description
+
+	/**
+	 * last read row number, starting from 0
+	 */
+	protected int rowNum = -1;
+
+	private final ChunksListForWrite chunksList;
 
+	private final PngMetadata metadata; // high level wrapper over chunkList
+
+	/**
+	 * Current chunk grounp, (0-6) already read or reading
+	 * <p>
+	 * see {@link ChunksList}
+	 */
 	protected int currentChunkGroup = -1;
-	protected int rowNum = -1; // current line number
 
-	// current line, one (packed) sample per element (layout differnt from rowb!)
-	protected int[] scanline = null;
-	protected byte[] rowb = null; // element 0 is filter type!
-	protected byte[] rowbprev = null; // rowb prev
-	protected byte[] rowbfilter = null; // current line with filter
+	/**
+	 * PNG filter strategy
+	 */
+	protected FilterWriteStrategy filterStrat;
 
-	protected final OutputStream os;
-	protected final String filename; // optional, can be a description
+	/**
+	 * zip compression level 0 - 9
+	 */
+	private int compLevel = 6;
+	private boolean shouldCloseStream = true; // true: closes stream after ending write
 
 	private PngIDatChunkOutputStream datStream;
+
 	private DeflaterOutputStream datStreamDeflated;
 
-	private final ChunkList chunkList;
-	private final PngMetadata metadata; // high level wrapper over chunkList
+	/**
+	 * Deflate algortithm compression strategy
+	 */
+	private int deflaterStrategy = Deflater.FILTERED;
+
+	private int[] histox = new int[256]; // auxiliar buffer, only used by reportResultsForFilter
+
+	private int idatMaxSize = 0; // 0=use default (PngIDatChunkOutputStream 32768)
+
+	private final OutputStream os;
+
+	protected byte[] rowb = null; // element 0 is filter type!
+	protected byte[] rowbfilter = null; // current line with filter
+
+	protected byte[] rowbprev = null; // rowb prev
+
+	// this only influences the 1-2-4 bitdepth format - and if we pass a ImageLine to writeRow, this is ignored
+	private boolean unpackedMode = false;
 
 	public PngWriter(OutputStream outputStream, ImageInfo imgInfo) {
 		this(outputStream, imgInfo, "[NO FILENAME AVAILABLE]");
 	}
 
 	/**
-	 * Constructs a new PngWriter from a output stream.
+	 * Constructs a new PngWriter from a output stream. After construction nothing is writen yet. You still can set some
+	 * parameters (compression, filters) and queue chunks before start writing the pixels.
 	 * <p>
 	 * See also <code>FileHelper.createPngWriter()</code> if available.
 	 * 
@@ -67,171 +100,156 @@ public class PngWriter {
 		this.os = outputStream;
 		this.imgInfo = imgInfo;
 		// prealloc
-		scanline = new int[imgInfo.samplesPerRowP];
 		rowb = new byte[imgInfo.bytesPerRow + 1];
 		rowbprev = new byte[rowb.length];
 		rowbfilter = new byte[rowb.length];
-		datStream = new PngIDatChunkOutputStream(this.os);
-		chunkList = new ChunkList(imgInfo);
-		metadata = new PngMetadata(chunkList, false);
-		filterStrat = new FilterWriteStrategy(imgInfo, FilterType.FILTER_DEFAULT);
+		chunksList = new ChunksListForWrite(imgInfo);
+		metadata = new PngMetadata(chunksList);
+		filterStrat = new FilterWriteStrategy(imgInfo, FilterType.FILTER_DEFAULT); // can be changed
 	}
 
-	/**
-	 * Write id signature and also "IHDR" chunk
-	 */
-	private void writeSignatureAndIHDR() {
-		currentChunkGroup = ChunkList.CHUNK_GROUP_0_IDHR;
-		if (datStreamDeflated == null) {
-			Deflater def = new Deflater(compLevel);
-			def.setStrategy(deflaterStrategy);
-			datStreamDeflated = new DeflaterOutputStream(datStream, def, 8192);
+	private void init() {
+		datStream = new PngIDatChunkOutputStream(this.os, idatMaxSize);
+		Deflater def = new Deflater(compLevel);
+		def.setStrategy(deflaterStrategy);
+		datStreamDeflated = new DeflaterOutputStream(datStream, def);
+		writeSignatureAndIHDR();
+		writeFirstChunks();
+	}
+
+	private void reportResultsForFilter(int rown, FilterType type, boolean tentative) {
+		Arrays.fill(histox, 0);
+		int s = 0, v;
+		for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
+			v = rowbfilter[i];
+			if (v < 0)
+				s -= (int) v;
+			else
+				s += (int) v;
+			histox[v & 0xFF]++;
 		}
-		PngHelper.writeBytes(os, PngHelper.pngIdBytes); // signature
-		PngChunkIHDR ihdr = new PngChunkIHDR(imgInfo);
-		// http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
-		ihdr.setCols(imgInfo.cols);
-		ihdr.setRows(imgInfo.rows);
-		ihdr.setBitspc(imgInfo.bitDepth);
-		int colormodel = 0;
-		if (imgInfo.alpha)
-			colormodel += 0x04;
-		if (imgInfo.indexed)
-			colormodel += 0x01;
-		if (!imgInfo.greyscale)
-			colormodel += 0x02;
-		ihdr.setColormodel(colormodel);
-		ihdr.setCompmeth(0); // compression method 0=deflate
-		ihdr.setFilmeth(0); // filter method (0)
-		ihdr.setInterlaced(0); // we never interlace
-		ihdr.createChunk().writeChunk(os);
+		filterStrat.fillResultsForFilter(rown, type, s, histox, tentative);
+	}
 
+	private void writeEndChunk() {
+		PngChunkIEND c = new PngChunkIEND(imgInfo);
+		c.createRawChunk().writeChunk(os);
 	}
 
 	private void writeFirstChunks() {
 		int nw = 0;
-		currentChunkGroup = ChunkList.CHUNK_GROUP_1_AFTERIDHR;
-		nw = chunkList.writeChunks(os, currentChunkGroup);
-		currentChunkGroup = ChunkList.CHUNK_GROUP_2_PLTE;
-		nw = chunkList.writeChunks(os, currentChunkGroup);
+		currentChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+		nw = chunksList.writeChunks(os, currentChunkGroup);
+		currentChunkGroup = ChunksList.CHUNK_GROUP_2_PLTE;
+		nw = chunksList.writeChunks(os, currentChunkGroup);
 		if (nw > 0 && imgInfo.greyscale)
 			throw new PngjOutputException("cannot write palette for this format");
 		if (nw == 0 && imgInfo.indexed)
 			throw new PngjOutputException("missing palette");
-		currentChunkGroup = ChunkList.CHUNK_GROUP_3_AFTERPLTE;
-		nw = chunkList.writeChunks(os, currentChunkGroup);
-		currentChunkGroup = ChunkList.CHUNK_GROUP_4_IDAT;
+		currentChunkGroup = ChunksList.CHUNK_GROUP_3_AFTERPLTE;
+		nw = chunksList.writeChunks(os, currentChunkGroup);
+		currentChunkGroup = ChunksList.CHUNK_GROUP_4_IDAT;
 	}
 
 	private void writeLastChunks() { // not including end
-		currentChunkGroup = ChunkList.CHUNK_GROUP_5_AFTERIDAT;
-		chunkList.writeChunks(os, currentChunkGroup);
+		currentChunkGroup = ChunksList.CHUNK_GROUP_5_AFTERIDAT;
+		chunksList.writeChunks(os, currentChunkGroup);
 		// should not be unwriten chunks
-		List<PngChunk> pending = chunkList.getQueuedChunks();
+		List<PngChunk> pending = chunksList.getQueuedChunks();
 		if (!pending.isEmpty())
 			throw new PngjOutputException(pending.size() + " chunks were not written! Eg: " + pending.get(0).toString());
-		currentChunkGroup = ChunkList.CHUNK_GROUP_6_END;
-	}
-
-	private void writeEndChunk() {
-		PngChunkIEND c = new PngChunkIEND(imgInfo);
-		c.createChunk().writeChunk(os);
+		currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
 	}
 
 	/**
-	 * Writes a full image row. This must be called sequentially from n=0 to n=rows-1 One integer per sample , in the
-	 * natural order: R G B R G B ... (or R G B A R G B A... if has alpha) The values should be between 0 and 255 for 8
-	 * bitspc images, and between 0- 65535 form 16 bitspc images (this applies also to the alpha channel if present) The
-	 * array can be reused.
-	 * 
-	 * @param newrow
-	 *            Array of pixel values
-	 * @param rown
-	 *            Row number, from 0 (top) to rows-1 (bottom). This is just used as a check. Pass -1 if you want to
-	 *            autocompute it
+	 * Write id signature and also "IHDR" chunk
 	 */
-	public void writeRow(int[] newrow, int rown) {
-		if (rown == 0) {
-			writeSignatureAndIHDR();
-			writeFirstChunks();
-		}
-		if (rown < -1 || rown > imgInfo.rows)
-			throw new RuntimeException("invalid value for row " + rown);
-		rowNum++;
-		if (rown >= 0 && rowNum != rown)
-			throw new RuntimeException("rows must be written in strict consecutive order: tried to write row " + rown
-					+ ", expected=" + rowNum);
-		scanline = newrow;
-		// swap
-		byte[] tmp = rowb;
-		rowb = rowbprev;
-		rowbprev = tmp;
-		convertRowToBytes();
-		filterRow(rown);
-		try {
-			datStreamDeflated.write(rowbfilter, 0, imgInfo.bytesPerRow + 1);
-		} catch (IOException e) {
-			throw new PngjOutputException(e);
-		}
-	}
+	private void writeSignatureAndIHDR() {
+		currentChunkGroup = ChunksList.CHUNK_GROUP_0_IDHR;
 
-	/**
-	 * Same as writeRow(int[] newrow, int rown), but does not check row number
-	 * 
-	 * @param newrow
-	 */
-	public void writeRow(int[] newrow) {
-		writeRow(newrow, -1);
-	}
+		PngHelperInternal.writeBytes(os, PngHelperInternal.getPngIdSignature()); // signature
+		PngChunkIHDR ihdr = new PngChunkIHDR(imgInfo);
+		// http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
+		ihdr.setCols(imgInfo.cols);
+		ihdr.setRows(imgInfo.rows);
+		ihdr.setBitspc(imgInfo.bitDepth);
+		int colormodel = 0;
+		if (imgInfo.alpha)
+			colormodel += 0x04;
+		if (imgInfo.indexed)
+			colormodel += 0x01;
+		if (!imgInfo.greyscale)
+			colormodel += 0x02;
+		ihdr.setColormodel(colormodel);
+		ihdr.setCompmeth(0); // compression method 0=deflate
+		ihdr.setFilmeth(0); // filter method (0)
+		ihdr.setInterlaced(0); // we never interlace
+		ihdr.createRawChunk().writeChunk(os);
 
-	/**
-	 * Writes line. See writeRow(int[] newrow, int rown)
-	 */
-	public void writeRow(ImageLine imgline, int rownumber) {
-		writeRow(imgline.scanline, rownumber);
 	}
 
-	/**
-	 * Writes line, checks that the row number is consistent with that of the ImageLine See writeRow(int[] newrow, int
-	 * rown)
-	 * 
-	 * @deprecated Better use writeRow(ImageLine imgline, int rownumber)
-	 */
-	public void writeRow(ImageLine imgline) {
-		writeRow(imgline.scanline, imgline.getRown());
-	}
+	protected void encodeRowFromByte(byte[] row) {
+		if (row.length == imgInfo.samplesPerRowPacked) {
+			// some duplication of code - because this case is typical and it works faster this way
+			int j = 1;
+			if (imgInfo.bitDepth <= 8) {
+				for (byte x : row) { // optimized
+					rowb[j++] = x;
+				}
+			} else { // 16 bitspc
+				for (byte x : row) { // optimized
+					rowb[j] = x;
+					j += 2;
+				}
+			}
+		} else {
+			// perhaps we need to pack?
+			if (row.length >= imgInfo.samplesPerRow && unpackedMode)
+				ImageLine.packInplaceByte(imgInfo, row, row, false); // row is packed in place!
+			if (imgInfo.bitDepth <= 8) {
+				for (int i = 0, j = 1; i < imgInfo.samplesPerRowPacked; i++) {
+					rowb[j++] = row[i];
+				}
+			} else { // 16 bitspc
+				for (int i = 0, j = 1; i < imgInfo.samplesPerRowPacked; i++) {
+					rowb[j++] = row[i];
+					rowb[j++] = 0;
+				}
+			}
 
-	/**
-	 * Finalizes the image creation and closes the stream. This MUST be called after writing the lines.
-	 */
-	public void end() {
-		if (rowNum != imgInfo.rows - 1)
-			throw new PngjOutputException("all rows have not been written");
-		try {
-			datStreamDeflated.finish();
-			datStream.flush();
-			writeLastChunks();
-			writeEndChunk();
-			os.close();
-		} catch (IOException e) {
-			throw new PngjOutputException(e);
 		}
 	}
 
-	private int[] histox = new int[256]; // auxiliar buffer, only used by reportResultsForFilter
-
-	private void reportResultsForFilter(int rown, FilterType type, boolean tentative) {
-		Arrays.fill(histox, 0);
-		int s = 0, v;
-		for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
-			v = rowbfilter[i];
-			if (v < 0)
-				s -= (int) v;
-			else
-				s += (int) v;
-			histox[v & 0xFF]++;
+	protected void encodeRowFromInt(int[] row) {
+		// http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html
+		if (row.length == imgInfo.samplesPerRowPacked) {
+			// some duplication of code - because this case is typical and it works faster this way
+			int j = 1;
+			if (imgInfo.bitDepth <= 8) {
+				for (int x : row) { // optimized
+					rowb[j++] = (byte) x;
+				}
+			} else { // 16 bitspc
+				for (int x : row) { // optimized
+					rowb[j++] = (byte) (x >> 8);
+					rowb[j++] = (byte) (x);
+				}
+			}
+		} else {
+			// perhaps we need to pack?
+			if (row.length >= imgInfo.samplesPerRow && unpackedMode)
+				ImageLine.packInplaceInt(imgInfo, row, row, false); // row is packed in place!
+			if (imgInfo.bitDepth <= 8) {
+				for (int i = 0, j = 1; i < imgInfo.samplesPerRowPacked; i++) {
+					rowb[j++] = (byte) (row[i]);
+				}
+			} else { // 16 bitspc
+				for (int i = 0, j = 1; i < imgInfo.samplesPerRowPacked; i++) {
+					rowb[j++] = (byte) (row[i] >> 8);
+					rowb[j++] = (byte) (row[i]);
+				}
+			}
 		}
-		filterStrat.fillResultsForFilter(rown, type, s, histox, tentative);
 	}
 
 	private void filterRow(int rown) {
@@ -268,123 +286,98 @@ public class PngWriter {
 			filterRowPaeth();
 			break;
 		default:
-			throw new PngjOutputException("Filter type " + filterType + " not implemented");
+			throw new PngjUnsupportedException("Filter type " + filterType + " not implemented");
 		}
 		reportResultsForFilter(rown, filterType, false);
 	}
 
-	protected int sumRowbfilter() { // sums absolute value
-		int s = 0;
-		for (int i = 1; i <= imgInfo.bytesPerRow; i++)
-			if (rowbfilter[i] < 0)
-				s -= (int) rowbfilter[i];
-			else
-				s += (int) rowbfilter[i];
-		return s;
+	private void prepareEncodeRow(int rown) {
+		if (datStream == null)
+			init();
+		rowNum++;
+		if (rown >= 0 && rowNum != rown)
+			throw new PngjOutputException("rows must be written in order: expected:" + rowNum + " passed:" + rown);
+		// swap
+		byte[] tmp = rowb;
+		rowb = rowbprev;
+		rowbprev = tmp;
 	}
 
-	protected void filterRowNone() {
-		for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
-			rowbfilter[i] = (byte) rowb[i];
+	private void filterAndSend(int rown) {
+		filterRow(rown);
+		try {
+			datStreamDeflated.write(rowbfilter, 0, imgInfo.bytesPerRow + 1);
+		} catch (IOException e) {
+			throw new PngjOutputException(e);
 		}
 	}
 
-	protected void filterRowSub() {
-		int i, j;
-		for (i = 1; i <= imgInfo.bytesPixel; i++)
-			rowbfilter[i] = (byte) rowb[i];
-		for (j = 1, i = imgInfo.bytesPixel + 1; i <= imgInfo.bytesPerRow; i++, j++) {
-			rowbfilter[i] = (byte) (rowb[i] - rowb[j]);
+	protected void filterRowAverage() {
+		int i, j, imax;
+		imax = imgInfo.bytesPerRow;
+		for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imax; i++, j++) {
+			rowbfilter[i] = (byte) (rowb[i] - ((rowbprev[i] & 0xFF) + (j > 0 ? (rowb[j] & 0xFF) : 0)) / 2);
 		}
 	}
 
-	protected void filterRowUp() {
+	protected void filterRowNone() {
 		for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
-			rowbfilter[i] = (byte) (rowb[i] - rowbprev[i]);
-		}
-	}
-
-	protected void filterRowAverage() {
-		int i, j;
-		for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imgInfo.bytesPerRow; i++, j++) {
-			rowbfilter[i] = (byte) (rowb[i] - ((rowbprev[i] & 0xFF) + (j > 0 ? (rowb[j] & 0xFF) : 0)) / 2);
+			rowbfilter[i] = (byte) rowb[i];
 		}
 	}
 
 	protected void filterRowPaeth() {
-		int i, j;
-		for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imgInfo.bytesPerRow; i++, j++) {
-			rowbfilter[i] = (byte) (rowb[i] - FilterType.filterPaethPredictor(j > 0 ? (rowb[j] & 0xFF) : 0,
-					rowbprev[i] & 0xFF, j > 0 ? (rowbprev[j] & 0xFF) : 0));
+		int i, j, imax;
+		imax = imgInfo.bytesPerRow;
+		for (j = 1 - imgInfo.bytesPixel, i = 1; i <= imax; i++, j++) {
+			// rowbfilter[i] = (byte) (rowb[i] - PngHelperInternal.filterPaethPredictor(j > 0 ? (rowb[j] & 0xFF) : 0,
+			// rowbprev[i] & 0xFF, j > 0 ? (rowbprev[j] & 0xFF) : 0));
+			rowbfilter[i] = (byte) PngHelperInternal.filterRowPaeth(rowb[i], j > 0 ? (rowb[j] & 0xFF) : 0,
+					rowbprev[i] & 0xFF, j > 0 ? (rowbprev[j] & 0xFF) : 0);
 		}
 	}
 
-	protected void convertRowToBytes() {
-		// http://www.libpng.org/pub/png/spec/1.2/PNG-DataRep.html
+	protected void filterRowSub() {
 		int i, j;
-		if (imgInfo.bitDepth <= 8) {
-			for (i = 0, j = 1; i < imgInfo.samplesPerRowP; i++) {
-				rowb[j++] = (byte) (scanline[i]);
-			}
-		} else { // 16 bitspc
-			for (i = 0, j = 1; i < imgInfo.samplesPerRowP; i++) {
-				// x = (int) (scanline[i]) & 0xFFFF;
-				rowb[j++] = (byte) (scanline[i] >> 8);
-				rowb[j++] = (byte) (scanline[i]);
-			}
+		for (i = 1; i <= imgInfo.bytesPixel; i++)
+			rowbfilter[i] = (byte) rowb[i];
+		for (j = 1, i = imgInfo.bytesPixel + 1; i <= imgInfo.bytesPerRow; i++, j++) {
+			// !!! rowbfilter[i] = (byte) (rowb[i] - rowb[j]);
+			rowbfilter[i] = (byte) PngHelperInternal.filterRowSub(rowb[i], rowb[j]);
 		}
 	}
 
-	// /// several getters / setters - all this setters are optional
-
-	/**
-	 * Filename or description, from the optional constructor argument.
-	 */
-	public String getFilename() {
-		return filename;
+	protected void filterRowUp() {
+		for (int i = 1; i <= imgInfo.bytesPerRow; i++) {
+			// rowbfilter[i] = (byte) (rowb[i] - rowbprev[i]); !!!
+			rowbfilter[i] = (byte) PngHelperInternal.filterRowUp(rowb[i], rowbprev[i]);
+		}
 	}
 
-	/**
-	 * Sets internal prediction filter type, or strategy to choose it.
-	 * <p>
-	 * This must be called just after constructor, before starting writing.
-	 * <p>
-	 * See also setCompLevel()
-	 * 
-	 * @param filterType
-	 *            One of the five prediction types or strategy to choose it (see <code>PngFilterType</code>) Recommended
-	 *            values: DEFAULT (default) or AGGRESIVE
-	 */
-	public void setFilterType(FilterType filterType) {
-		filterStrat = new FilterWriteStrategy(imgInfo, filterType);
+	protected int sumRowbfilter() { // sums absolute value
+		int s = 0;
+		for (int i = 1; i <= imgInfo.bytesPerRow; i++)
+			if (rowbfilter[i] < 0)
+				s -= (int) rowbfilter[i];
+			else
+				s += (int) rowbfilter[i];
+		return s;
 	}
 
 	/**
-	 * Sets compression level of ZIP algorithm.
+	 * copy chunks from reader - copy_mask : see ChunksToWrite.COPY_XXX
 	 * <p>
-	 * This must be called just after constructor, before starting writing.
+	 * If we are after idat, only considers those chunks after IDAT in PngReader
 	 * <p>
-	 * See also setFilterType()
-	 * 
-	 * @param compLevel
-	 *            between 0 and 9 (default:6 , recommended: 6 or more)
-	 */
-	public void setCompLevel(int compLevel) {
-		if (compLevel < 0 || compLevel > 9)
-			throw new PngjException("Compression level invalid (" + compLevel + ") Must be 0..9");
-		this.compLevel = compLevel;
-	}
-
-	/**
-	 * copy chunks from reader - copy_mask : see ChunksToWrite.COPY_XXX
-	 * 
-	 * If we are after idat, only considers those chunks after IDAT in PngReader TODO: this should be more customizable
+	 * TODO: this should be more customizable
 	 */
 	private void copyChunks(PngReader reader, int copy_mask, boolean onlyAfterIdat) {
-		boolean idatDone = currentChunkGroup >= ChunkList.CHUNK_GROUP_4_IDAT;
+		boolean idatDone = currentChunkGroup >= ChunksList.CHUNK_GROUP_4_IDAT;
+		if (onlyAfterIdat && reader.getCurrentChunkGroup() < ChunksList.CHUNK_GROUP_6_END)
+			throw new PngjExceptionInternal("tried to copy last chunks but reader has not ended");
 		for (PngChunk chunk : reader.getChunksList().getChunks()) {
 			int group = chunk.getChunkGroup();
-			if (group < ChunkList.CHUNK_GROUP_4_IDAT && idatDone)
+			if (group < ChunksList.CHUNK_GROUP_4_IDAT && idatDone)
 				continue;
 			boolean copy = false;
 			if (chunk.crit) {
@@ -413,9 +406,11 @@ public class PngWriter {
 						&& !(ChunkHelper.isUnknown(chunk) || text || chunk.id.equals(ChunkHelper.hIST) || chunk.id
 								.equals(ChunkHelper.tIME)))
 					copy = true;
+				if (chunk instanceof PngChunkSkipped)
+					copy = false;
 			}
 			if (copy) {
-				chunkList.queueChunk(PngChunk.cloneChunk(chunk, imgInfo), !chunk.allowsMultiple(), false);
+				chunksList.queue(PngChunk.cloneChunk(chunk, imgInfo));
 			}
 		}
 	}
@@ -451,12 +446,228 @@ public class PngWriter {
 		copyChunks(reader, copy_mask, true);
 	}
 
-	public ChunkList getChunkList() {
-		return chunkList;
+	/**
+	 * Computes compressed size/raw size, approximate.
+	 * <p>
+	 * Actually: compressed size = total size of IDAT data , raw size = uncompressed pixel bytes = rows * (bytesPerRow +
+	 * 1).
+	 * 
+	 * This must be called after pngw.end()
+	 */
+	public double computeCompressionRatio() {
+		if (currentChunkGroup < ChunksList.CHUNK_GROUP_6_END)
+			throw new PngjOutputException("must be called after end()");
+		double compressed = (double) datStream.getCountFlushed();
+		double raw = (imgInfo.bytesPerRow + 1) * imgInfo.rows;
+		return compressed / raw;
 	}
 
+	/**
+	 * Finalizes the image creation and closes the stream. This MUST be called after writing the lines.
+	 */
+	public void end() {
+		if (rowNum != imgInfo.rows - 1)
+			throw new PngjOutputException("all rows have not been written");
+		try {
+			datStreamDeflated.finish();
+			datStream.flush();
+			writeLastChunks();
+			writeEndChunk();
+			if (shouldCloseStream)
+				os.close();
+		} catch (IOException e) {
+			throw new PngjOutputException(e);
+		}
+	}
+
+	/**
+	 * returns the chunks list (queued and writen chunks)
+	 */
+	public ChunksListForWrite getChunksList() {
+		return chunksList;
+	}
+
+	/**
+	 * Filename or description, from the optional constructor argument.
+	 */
+	public String getFilename() {
+		return filename;
+	}
+
+	/**
+	 * High level wrapper over chunksList for metadata handling
+	 */
 	public PngMetadata getMetadata() {
 		return metadata;
 	}
 
+	/**
+	 * Sets compression level of ZIP algorithm.
+	 * <p>
+	 * This must be called just after constructor, before starting writing.
+	 * <p>
+	 * See also setFilterType()
+	 * 
+	 * @param compLevel
+	 *            between 0 and 9 (default:6 , recommended: 6 or more)
+	 */
+	public void setCompLevel(int compLevel) {
+		if (compLevel < 0 || compLevel > 9)
+			throw new PngjOutputException("Compression level invalid (" + compLevel + ") Must be 0..9");
+		this.compLevel = compLevel;
+	}
+
+	/**
+	 * Sets internal prediction filter type, or strategy to choose it.
+	 * <p>
+	 * This must be called just after constructor, before starting writing.
+	 * <p>
+	 * See also setCompLevel()
+	 * 
+	 * @param filterType
+	 *            One of the five prediction types or strategy to choose it (see <code>PngFilterType</code>) Recommended
+	 *            values: DEFAULT (default) or AGGRESIVE
+	 */
+	public void setFilterType(FilterType filterType) {
+		filterStrat = new FilterWriteStrategy(imgInfo, filterType);
+	}
+
+	/**
+	 * Sets maximum size of IDAT fragments. This has little effect on performance you should rarely call this
+	 * <p>
+	 * 
+	 * @param idatMaxSize
+	 *            default=0 : use defaultSize (32K)
+	 */
+	public void setIdatMaxSize(int idatMaxSize) {
+		this.idatMaxSize = idatMaxSize;
+	}
+
+	/**
+	 * if true, input stream will be closed after ending write
+	 * <p>
+	 * default=true
+	 */
+	public void setShouldCloseStream(boolean shouldCloseStream) {
+		this.shouldCloseStream = shouldCloseStream;
+	}
+
+	/**
+	 * Deflater strategy: one of Deflater.FILTERED Deflater.HUFFMAN_ONLY Deflater.DEFAULT_STRATEGY
+	 * <p>
+	 * Default: Deflater.FILTERED . This should be changed very rarely.
+	 */
+	public void setDeflaterStrategy(int deflaterStrategy) {
+		this.deflaterStrategy = deflaterStrategy;
+	}
+
+	/**
+	 * Writes line, checks that the row number is consistent with that of the ImageLine See writeRow(int[] newrow, int
+	 * rown)
+	 * 
+	 * @deprecated Better use writeRow(ImageLine imgline, int rownumber)
+	 */
+	public void writeRow(ImageLine imgline) {
+		writeRow(imgline.scanline, imgline.getRown());
+	}
+
+	/**
+	 * Writes line. See writeRow(int[] newrow, int rown)
+	 * 
+	 * The <tt>packed</tt> flag of the imageline is honoured!
+	 * 
+	 * @see #writeRowInt(int[], int)
+	 */
+	public void writeRow(ImageLine imgline, int rownumber) {
+		unpackedMode = imgline.samplesUnpacked;
+		if (imgline.sampleType == SampleType.INT)
+			writeRowInt(imgline.scanline, rownumber);
+		else
+			writeRowByte(imgline.scanlineb, rownumber);
+	}
+
+	/**
+	 * Same as writeRow(int[] newrow, int rown), but does not check row number
+	 * 
+	 * @param newrow
+	 */
+	public void writeRow(int[] newrow) {
+		writeRow(newrow, -1);
+	}
+
+	/**
+	 * Alias to writeRowInt
+	 * 
+	 * @see #writeRowInt(int[], int)
+	 */
+	public void writeRow(int[] newrow, int rown) {
+		writeRowInt(newrow, rown);
+	}
+
+	/**
+	 * Writes a full image row.
+	 * <p>
+	 * This must be called sequentially from n=0 to n=rows-1 One integer per sample , in the natural order: R G B R G B
+	 * ... (or R G B A R G B A... if has alpha) The values should be between 0 and 255 for 8 bitspc images, and between
+	 * 0- 65535 form 16 bitspc images (this applies also to the alpha channel if present) The array can be reused.
+	 * <p>
+	 * Warning: the array might be modified in some cases (unpacked row with low bitdepth)
+	 * <p>
+	 * 
+	 * @param newrow
+	 *            Array of pixel values. Warning: the array size should be exact (samplesPerRowP)
+	 * @param rown
+	 *            Row number, from 0 (top) to rows-1 (bottom). This is just used as a check. Pass -1 if you want to
+	 *            autocompute it
+	 */
+	public void writeRowInt(int[] newrow, int rown) {
+		prepareEncodeRow(rown);
+		encodeRowFromInt(newrow);
+		filterAndSend(rown);
+	}
+
+	/**
+	 * Same semantics as writeRowInt but using bytes. Each byte is still a sample. If 16bitdepth, we are passing only
+	 * the most significant byte (and hence losing some info)
+	 * 
+	 * @see PngWriter#writeRowInt(int[], int)
+	 */
+	public void writeRowByte(byte[] newrow, int rown) {
+		prepareEncodeRow(rown);
+		encodeRowFromByte(newrow);
+		filterAndSend(rown);
+	}
+
+	/**
+	 * Writes all the pixels, calling writeRowInt() for each image row
+	 */
+	public void writeRowsInt(int[][] image) {
+		for (int i = 0; i < imgInfo.rows; i++)
+			writeRowInt(image[i], i);
+	}
+
+	/**
+	 * Writes all the pixels, calling writeRowByte() for each image row
+	 */
+	public void writeRowsByte(byte[][] image) {
+		for (int i = 0; i < imgInfo.rows; i++)
+			writeRowByte(image[i], i);
+	}
+
+	public boolean isUnpackedMode() {
+		return unpackedMode;
+	}
+
+	/**
+	 * If false (default), and image has bitdepth 1-2-4, the scanlines passed are assumed to be already packed.
+	 * <p>
+	 * If true, each element is a sample, the writer will perform the packing if necessary.
+	 * <p>
+	 * Warning: when using {@link #writeRow(ImageLine, int)} (recommended) the <tt>packed</tt> flag of the ImageLine
+	 * object overrides (and overwrites!) this field.
+	 */
+	public void setUseUnPackedMode(boolean useUnpackedMode) {
+		this.unpackedMode = useUnpackedMode;
+	}
+
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java
new file mode 100644
index 0000000..963abc5
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java
@@ -0,0 +1,23 @@
+package jogamp.opengl.util.pngj;
+
+/**
+ * Exception for anomalous internal problems (sort of asserts) that point to some issue with the library
+ * 
+ * @author Hernan J Gonzalez
+ * 
+ */
+public class PngjExceptionInternal extends RuntimeException {
+	private static final long serialVersionUID = 1L;
+
+	public PngjExceptionInternal(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+	public PngjExceptionInternal(String message) {
+		super(message);
+	}
+
+	public PngjExceptionInternal(Throwable cause) {
+		super(cause);
+	}
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java b/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
index bbec247..a5bad66 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
@@ -8,6 +8,7 @@ import java.io.IOException;
  */
 abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
 	private final int size;
+	private long countFlushed = 0;
 
 	public ProgressiveOutputStream(int size) {
 		this.size = size;
@@ -60,6 +61,7 @@ abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
 			if (nb == 0)
 				return;
 			flushBuffer(buf, nb);
+			countFlushed += nb;
 			int bytesleft = count - nb;
 			count = bytesleft;
 			if (bytesleft > 0)
@@ -67,5 +69,9 @@ abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
 		}
 	}
 
-	public abstract void flushBuffer(byte[] b, int n);
+	protected abstract void flushBuffer(byte[] b, int n);
+
+	public long getCountFlushed() {
+		return countFlushed;
+	}
 }
\ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkCopyBehaviour.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkCopyBehaviour.java
index 43c0cb1..a2d976f 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkCopyBehaviour.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkCopyBehaviour.java
@@ -1,8 +1,9 @@
 package jogamp.opengl.util.pngj.chunks;
 
 /**
- * Chunk copy policy to apply when copyng from a pngReader to a pngWriter http://www.w3.org/TR/PNG/#14
+ * Chunk copy policy to apply when copyng from a pngReader to a pngWriter.
  * <p>
+ * http://www.w3.org/TR/PNG/#14 <br>
  * These are masks, can be OR-ed
  **/
 public class ChunkCopyBehaviour {
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java
index 26dafd4..ed091d3 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkHelper.java
@@ -8,11 +8,13 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
 import java.util.zip.DeflaterOutputStream;
 import java.util.zip.InflaterInputStream;
 
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
 
@@ -41,38 +43,83 @@ public class ChunkHelper {
 	public static final String tEXt = "tEXt";
 	public static final String zTXt = "zTXt";
 
-	public static Set<String> KNOWN_CHUNKS_CRITICAL = PngHelper.asSet(IHDR, PLTE, IDAT, IEND);
-
+	/**
+	 * Converts to bytes using Latin1 (ISO-8859-1)
+	 */
 	public static byte[] toBytes(String x) {
-		return x.getBytes(PngHelper.charsetLatin1);
+		return x.getBytes(PngHelperInternal.charsetLatin1);
 	}
 
+	/**
+	 * Converts to String using Latin1 (ISO-8859-1)
+	 */
 	public static String toString(byte[] x) {
-		return new String(x, PngHelper.charsetLatin1);
+		return new String(x, PngHelperInternal.charsetLatin1);
 	}
 
-	public static boolean isCritical(String id) { // critical chunk ?
-		// first letter is uppercase
+	/**
+	 * Converts to String using Latin1 (ISO-8859-1)
+	 */
+	public static String toString(byte[] x, int offset, int len) {
+		return new String(x, offset, len, PngHelperInternal.charsetLatin1);
+	}
+
+	/**
+	 * Converts to bytes using UTF-8
+	 */
+	public static byte[] toBytesUTF8(String x) {
+		return x.getBytes(PngHelperInternal.charsetUTF8);
+	}
+
+	/**
+	 * Converts to string using UTF-8
+	 */
+	public static String toStringUTF8(byte[] x) {
+		return new String(x, PngHelperInternal.charsetUTF8);
+	}
+
+	/**
+	 * Converts to string using UTF-8
+	 */
+	public static String toStringUTF8(byte[] x, int offset, int len) {
+		return new String(x, offset, len, PngHelperInternal.charsetUTF8);
+	}
+
+	/**
+	 * critical chunk : first letter is uppercase
+	 */
+	public static boolean isCritical(String id) {
 		return (Character.isUpperCase(id.charAt(0)));
 	}
 
-	public static boolean isPublic(String id) { // public chunk?
-		// second letter is uppercase
+	/**
+	 * public chunk: second letter is uppercase
+	 */
+	public static boolean isPublic(String id) { //
 		return (Character.isUpperCase(id.charAt(1)));
 	}
 
 	/**
-	 * "Unknown" just means that our chunk factory (even when it has been augmented by client code) did not recognize its id
+	 * Safe to copy chunk: fourth letter is lower case
 	 */
-	public static boolean isUnknown(PngChunk c) {
-		return c instanceof PngChunkUNKNOWN;
+	public static boolean isSafeToCopy(String id) {
+		return (!Character.isUpperCase(id.charAt(3)));
 	}
 
-	public static boolean isSafeToCopy(String id) { // safe to copy?
-		// fourth letter is lower case
-		return (!Character.isUpperCase(id.charAt(3)));
+	/**
+	 * "Unknown" just means that our chunk factory (even when it has been augmented by client code) did not recognize
+	 * its id
+	 */
+	public static boolean isUnknown(PngChunk c) {
+		return c instanceof PngChunkUNKNOWN;
 	}
 
+	/**
+	 * Finds position of null byte in array
+	 * 
+	 * @param b
+	 * @return -1 if not found
+	 */
 	public static int posNullByte(byte[] b) {
 		for (int i = 0; i < b.length; i++)
 			if (b[i] == 0)
@@ -80,6 +127,13 @@ public class ChunkHelper {
 		return -1;
 	}
 
+	/**
+	 * Decides if a chunk should be loaded, according to a ChunkLoadBehaviour
+	 * 
+	 * @param id
+	 * @param behav
+	 * @return true/false
+	 */
 	public static boolean shouldLoad(String id, ChunkLoadBehaviour behav) {
 		if (isCritical(id))
 			return true;
@@ -131,4 +185,69 @@ public class ChunkHelper {
 		return (v & mask) != 0;
 	}
 
+	/**
+	 * Returns only the chunks that "match" the predicate
+	 * 
+	 * See also trimList()
+	 */
+	public static List<PngChunk> filterList(List<PngChunk> target, ChunkPredicate predicateKeep) {
+		List<PngChunk> result = new ArrayList<PngChunk>();
+		for (PngChunk element : target) {
+			if (predicateKeep.match(element)) {
+				result.add(element);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Remove (in place) the chunks that "match" the predicate
+	 * 
+	 * See also filterList
+	 */
+	public static int trimList(List<PngChunk> target, ChunkPredicate predicateRemove) {
+		Iterator<PngChunk> it = target.iterator();
+		int cont = 0;
+		while (it.hasNext()) {
+			PngChunk c = it.next();
+			if (predicateRemove.match(c)) {
+				it.remove();
+				cont++;
+			}
+		}
+		return cont;
+	}
+
+	/**
+	 * MY adhoc criteria: two chunks are "equivalent" ("practically equal") if they have same id and (perhaps, if
+	 * multiple are allowed) if the match also in some "internal key" (eg: key for string values, palette for sPLT, etc)
+	 * 
+	 * Notice that the use of this is optional, and that the PNG standard allows Text chunks that have same key
+	 * 
+	 * @return true if "equivalent"
+	 */
+	public static final boolean equivalent(PngChunk c1, PngChunk c2) {
+		if (c1 == c2)
+			return true;
+		if (c1 == null || c2 == null || !c1.id.equals(c2.id))
+			return false;
+		// same id
+		if (c1.getClass() != c2.getClass())
+			return false; // should not happen
+		if (!c2.allowsMultiple())
+			return true;
+		if (c1 instanceof PngChunkTextVar) {
+			return ((PngChunkTextVar) c1).getKey().equals(((PngChunkTextVar) c2).getKey());
+		}
+		if (c1 instanceof PngChunkSPLT) {
+			return ((PngChunkSPLT) c1).getPalName().equals(((PngChunkSPLT) c2).getPalName());
+		}
+		// unknown chunks that allow multiple? consider they don't match
+		return false;
+	}
+
+	public static boolean isText(PngChunk c) {
+		return c instanceof PngChunkTextVar;
+	}
+
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkList.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkList.java
deleted file mode 100644
index badbbd0..0000000
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkList.java
+++ /dev/null
@@ -1,282 +0,0 @@
-package jogamp.opengl.util.pngj.chunks;
-
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngjException;
-
-
-/**
- * All chunks that form an image, read or to be written
- * 
- * chunks include all chunks, but IDAT is a single pseudo chunk without data
- **/
-public class ChunkList {
-	// ref: http://www.w3.org/TR/PNG/#table53
-	public static final int CHUNK_GROUP_0_IDHR = 0; // required - single
-	public static final int CHUNK_GROUP_1_AFTERIDHR = 1; // optional - multiple
-	public static final int CHUNK_GROUP_2_PLTE = 2; // optional - single
-	public static final int CHUNK_GROUP_3_AFTERPLTE = 3; // optional - multple
-	public static final int CHUNK_GROUP_4_IDAT = 4; // required (single pseudo chunk)
-	public static final int CHUNK_GROUP_5_AFTERIDAT = 5; // optional - multple
-	public static final int CHUNK_GROUP_6_END = 6; // only 1 chunk - requried
-
-	/**
-	 * All chunks, read, written (does not include IHDR, IDAT, END for written)
-	 */
-	private List<PngChunk> chunks = new ArrayList<PngChunk>();
-
-	/**
-	 * chunks not yet writen - does not include IHDR, IDAT, END, perhaps yes PLTE
-	 */
-	private Set<PngChunk> queuedChunks = new LinkedHashSet<PngChunk>();
-
-	final ImageInfo imageInfo; // only required for writing
-
-	public ChunkList(ImageInfo imfinfo) {
-		this.imageInfo = imfinfo;
-	}
-
-	/**
-	 * Adds chunk in next position. This is used when reading
-	 */
-	public void appendReadChunk(PngChunk chunk, int chunkGroup) {
-		chunk.setChunkGroup(chunkGroup);
-		chunks.add(chunk);
-	}
-
-	public List<PngChunk> getById(String id, boolean includeQueued, boolean includeProcessed) {
-		List<PngChunk> list = new ArrayList<PngChunk>();
-		if (includeQueued)
-			for (PngChunk c : queuedChunks)
-				if (c.id.equals(id))
-					list.add(c);
-		if (includeProcessed)
-			for (PngChunk c : chunks)
-				if (c.id.equals(id))
-					list.add(c);
-		return list;
-	}
-
-	/**
-	 * Remove Chunk: only from queued
-	 */
-	public boolean removeChunk(PngChunk c) {
-		return queuedChunks.remove(c);
-	}
-
-	/**
-	 * add chunk to write queue
-	 */
-	public void queueChunk(PngChunk chunk, boolean replace, boolean priority) {
-		chunk.setPriority(priority);
-		if (replace) {
-			List<PngChunk> current = getById(chunk.id, true, false);
-			for (PngChunk chunk2 : current)
-				removeChunk(chunk2);
-		}
-		queuedChunks.add(chunk);
-	}
-
-	/**
-	 * this should be called only for ancillary chunks and PLTE (groups 1 - 3 - 5)
-	 **/
-	private static boolean shouldWrite(PngChunk c, int currentGroup) {
-		if (currentGroup == CHUNK_GROUP_2_PLTE)
-			return c.id.equals(ChunkHelper.PLTE);
-		if (currentGroup % 2 == 0)
-			throw new RuntimeException("?");
-		int minChunkGroup, maxChunkGroup;
-		if (c.mustGoBeforePLTE())
-			minChunkGroup = maxChunkGroup = ChunkList.CHUNK_GROUP_1_AFTERIDHR;
-		else if (c.mustGoBeforeIDAT()) {
-			maxChunkGroup = ChunkList.CHUNK_GROUP_3_AFTERPLTE;
-			minChunkGroup = c.mustGoAfterPLTE() ? ChunkList.CHUNK_GROUP_3_AFTERPLTE : ChunkList.CHUNK_GROUP_1_AFTERIDHR;
-		} else {
-			maxChunkGroup = ChunkList.CHUNK_GROUP_5_AFTERIDAT;
-			minChunkGroup = ChunkList.CHUNK_GROUP_1_AFTERIDHR;
-		}
-
-		int preferred = maxChunkGroup;
-		if (c.isWritePriority())
-			preferred = minChunkGroup;
-		if (ChunkHelper.isUnknown(c) && c.getChunkGroup() > 0)
-			preferred = c.getChunkGroup();
-		if (currentGroup == preferred)
-			return true;
-		if (currentGroup > preferred && currentGroup <= maxChunkGroup)
-			return true;
-		return false;
-	}
-
-	public int writeChunks(OutputStream os, int currentGroup) {
-		int cont = 0;
-		Iterator<PngChunk> it = queuedChunks.iterator();
-		while (it.hasNext()) {
-			PngChunk c = it.next();
-			if (!shouldWrite(c, currentGroup))
-				continue;
-			c.write(os);
-			chunks.add(c);
-			c.setChunkGroup(currentGroup);
-			it.remove();
-			cont++;
-		}
-		return cont;
-	}
-
-	/**
-	 * returns a copy of processed (read or writen) chunks
-	 */
-	public List<PngChunk> getChunks() {
-		return new ArrayList<PngChunk>(chunks);
-	}
-
-	public List<String> getChunksUnkown() {
-		List<String> l = new ArrayList<String>();
-		for (PngChunk chunk : chunks)
-			if (ChunkHelper.isUnknown(chunk))
-				l.add(chunk.id);
-		return l;
-	}
-
-	/**
-	 * returns a copy of queued (for write) chunks
-	 */
-	public List<PngChunk> getQueuedChunks() {
-		return new ArrayList<PngChunk>(queuedChunks);
-	}
-
-	/**
-	 * behaviour:
-	 * 
-	 * a chunk already processed matches : exception a chunk queued matches and overwrite=true: replace it , return true
-	 * a chunk queued matches and overwrite=false: do nothing, return false no matching: set it, return true
-	 * 
-	 * @param c
-	 * @param overwriteIfPresent
-	 * @return true if added chunk
-	 */
-	public boolean setChunk(PngChunk c, boolean overwriteIfPresent) {
-		List<PngChunk> list = getMatching(c, false, true); // processed
-		if (!list.isEmpty())
-			throw new PngjException("chunk " + c.id + " already set ");
-		list = getMatching(c, true, false); // queued
-		if (!list.isEmpty()) {
-			if (overwriteIfPresent) {
-				for (PngChunk cx : list)
-					removeChunk(cx);
-				queueChunk(c, false, false);
-				return true;
-			}
-			return false;
-		}
-		queueChunk(c, false, false);
-		return true;
-	}
-
-	/**
-	 * returns only one chunk or null if nothing found - does not include queued
-	 * 
-	 * If innerid!=null , the chunk is assumed to be PngChunkTextVar or PngChunkSPLT, and filtered by that id
-	 * 
-	 * If more than one chunk (after filtering by inner id) is found, then an exception is thrown (failifMultiple=true)
-	 * or the last one is returned (failifMultiple=false)
-	 **/
-	public PngChunk getChunk1(String id, String innerid, boolean failIfMultiple) {
-		List<PngChunk> list = getChunks(id);
-		if (list.isEmpty())
-			return null;
-		if (innerid != null) {
-			List<PngChunk> list2 = new ArrayList<PngChunk>();
-			for (PngChunk c : list) {
-				if (c instanceof PngChunkTextVar)
-					if (((PngChunkTextVar) c).getKey().equals(innerid))
-						list2.add(c);
-				if (c instanceof PngChunkSPLT)
-					if (((PngChunkSPLT) c).getPalName().equals(innerid))
-						list2.add(c);
-			}
-			list = list2;
-		}
-		if (list.isEmpty())
-			return null;
-		if (list.size() > 1 && failIfMultiple)
-			throw new PngjException("unexpected multiple chunks id=" + id);
-		return list.get(list.size() - 1);
-	}
-
-	public PngChunk getChunk1(String id) {
-		return getChunk1(id, null, true);
-	}
-	
-	public List<PngChunk> getChunks(String id) { // not including queued
-		return getById(id, false, true);
-	}
-
-	private List<PngChunk> getMatching(PngChunk cnew, boolean includeQueued, boolean includeProcessed) {
-		List<PngChunk> list = new ArrayList<PngChunk>();
-		if (includeQueued)
-			for (PngChunk c : getQueuedChunks())
-				if (matches(cnew, c))
-					list.add(c);
-		if (includeProcessed)
-			for (PngChunk c : getChunks())
-				if (matches(cnew, c))
-					list.add(c);
-		return list;
-	}
-
-	/**
-	 * MY adhoc criteria: two chunks "match" if they have same id and (perhaps, if multiple are allowed) if the match
-	 * also in some "internal key" (eg: key for string values, palette for sPLT, etc)
-	 * 
-	 * @return true if "matches"
-	 */
-	public static boolean matches(PngChunk c2, PngChunk c1) {
-		if (c1 == null || c2 == null || !c1.id.equals(c2.id))
-			return false;
-		// same id
-		if (c1.getClass() != c2.getClass())
-			return false; // should not happen
-		if (!c2.allowsMultiple())
-			return true;
-		if (c1 instanceof PngChunkTextVar) {
-			return ((PngChunkTextVar) c1).getKey().equals(((PngChunkTextVar) c2).getKey());
-		}
-		if (c1 instanceof PngChunkSPLT) {
-			return ((PngChunkSPLT) c1).getPalName().equals(((PngChunkSPLT) c2).getPalName());
-		}
-		// unknown chunks that allow multiple? consider they don't match
-		return false;
-	}
-	
-	public String toString() {
-		return "ChunkList: processed: " + chunks.size() + " queue: " + queuedChunks.size();
-	}
-
-	/**
-	 * for debugging
-	 */
-	public String toStringFull() {
-		StringBuilder sb = new StringBuilder(toString());
-		sb.append("\n Processed:\n");
-		for (PngChunk chunk : chunks) {
-			sb.append(chunk).append(" G=" + chunk.getChunkGroup() + "\n");
-		}
-		if (!queuedChunks.isEmpty()) {
-			sb.append(" Queued:\n");
-			for (PngChunk chunk : chunks) {
-				sb.append(chunk).append("\n");
-			}
-
-		}
-		return sb.toString();
-	}
-
-}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java
index a3f8535..03d50c2 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkLoadBehaviour.java
@@ -1,10 +1,25 @@
 package jogamp.opengl.util.pngj.chunks;
 
+/**
+ * Defines gral strategy about what to do with ancillary (non-critical) chunks when reading
+ */
 public enum ChunkLoadBehaviour {
-	// what to do with non critical chunks when reading?
-	LOAD_CHUNK_NEVER, /* ignore non-critical chunks */
-	LOAD_CHUNK_KNOWN, /* load chunk if 'known' */
-	LOAD_CHUNK_IF_SAFE, /* load chunk if 'known' or safe to copy */
-	LOAD_CHUNK_ALWAYS /* load chunk always */
-	;
+	/**
+	 * All non-critical chunks are skipped
+	 */
+	LOAD_CHUNK_NEVER,
+	/**
+	 * Ancillary chunks are loaded only if 'known' (registered with the factory).
+	 */
+	LOAD_CHUNK_KNOWN,
+	/**
+	 * 
+	 * Load chunk if "known" or "safe to copy".
+	 */
+	LOAD_CHUNK_IF_SAFE,
+	/**
+	 * Load all chunks. <br>
+	 * Notice that other restrictions might apply, see PngReader.skipChunkMaxSize PngReader.skipChunkIds
+	 */
+	LOAD_CHUNK_ALWAYS;
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkPredicate.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkPredicate.java
new file mode 100644
index 0000000..a750ae3
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkPredicate.java
@@ -0,0 +1,14 @@
+package jogamp.opengl.util.pngj.chunks;
+
+/**
+ * Decides if another chunk "matches", according to some criterion
+ */
+public interface ChunkPredicate {
+	/**
+	 * The other chunk matches with this one
+	 * 
+	 * @param chunk
+	 * @return true if match
+	 */
+	boolean match(PngChunk chunk);
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
index 6770d5e..8dd0ef4 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
@@ -5,24 +5,47 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.zip.CRC32;
 
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjBadCrcException;
 import jogamp.opengl.util.pngj.PngjOutputException;
 
 
 /**
- * Wraps the raw chunk data Short lived object, to be created while serialing/deserializing Do not reuse it for
- * different chunks
- * 
- * see http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
+ * Raw (physical) chunk.
+ * <p>
+ * Short lived object, to be created while serialing/deserializing Do not reuse it for different chunks. <br>
+ * See http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html
  */
 public class ChunkRaw {
+	/**
+	 * The length counts only the data field, not itself, the chunk type code, or the CRC. Zero is a valid length.
+	 * Although encoders and decoders should treat the length as unsigned, its value must not exceed 231-1 bytes.
+	 */
 	public final int len;
-	public final byte[] idbytes = new byte[4]; // 4 bytes
-	public byte[] data = null; // crc not included
+
+	/**
+	 * A 4-byte chunk type code. uppercase and lowercase ASCII letters
+	 */
+	public final byte[] idbytes = new byte[4];
+
+	/**
+	 * The data bytes appropriate to the chunk type, if any. This field can be of zero length. Does not include crc
+	 */
+	public byte[] data = null;
+	/**
+	 * A 4-byte CRC (Cyclic Redundancy Check) calculated on the preceding bytes in the chunk, including the chunk type
+	 * code and chunk data fields, but not including the length field.
+	 */
 	private int crcval = 0;
 
-	// public int offset=-1; // only for read chunks - informational
+	/**
+	 * @param len
+	 *            : data len
+	 * @param idbytes
+	 *            : chunk type (deep copied)
+	 * @param alloc
+	 *            : it true, the data array will be allocced
+	 */
 	public ChunkRaw(int len, byte[] idbytes, boolean alloc) {
 		this.len = len;
 		System.arraycopy(idbytes, 0, this.idbytes, 0, 4);
@@ -30,54 +53,58 @@ public class ChunkRaw {
 			allocData();
 	}
 
-	public void writeChunk(OutputStream os) {
-		if (idbytes.length != 4)
-			throw new PngjOutputException("bad chunkid [" + ChunkHelper.toString(idbytes) + "]");
-		computeCrc();
-		PngHelper.writeInt4(os, len);
-		PngHelper.writeBytes(os, idbytes);
-		if (len > 0)
-			PngHelper.writeBytes(os, data, 0, len);
-		// System.err.println("writing chunk " + this.toString() + "crc=" + crcval);
-
-		PngHelper.writeInt4(os, crcval);
+	private void allocData() {
+		if (data == null || data.length < len)
+			data = new byte[len];
 	}
 
 	/**
-	 * called after setting data, before writing to os
+	 * this is called after setting data, before writing to os
 	 */
-	private void computeCrc() {
-		CRC32 crcengine = PngHelper.getCRC();
+	private int computeCrc() {
+		CRC32 crcengine = PngHelperInternal.getCRC();
 		crcengine.reset();
 		crcengine.update(idbytes, 0, 4);
 		if (len > 0)
 			crcengine.update(data, 0, len); //
-		crcval = (int) crcengine.getValue();
+		return (int) crcengine.getValue();
 	}
 
-	public String toString() {
-		return "chunkid=" + ChunkHelper.toString(idbytes) + " len=" + len;
+	/**
+	 * Computes the CRC and writes to the stream. If error, a PngjOutputException is thrown
+	 */
+	public void writeChunk(OutputStream os) {
+		if (idbytes.length != 4)
+			throw new PngjOutputException("bad chunkid [" + ChunkHelper.toString(idbytes) + "]");
+		crcval = computeCrc();
+		PngHelperInternal.writeInt4(os, len);
+		PngHelperInternal.writeBytes(os, idbytes);
+		if (len > 0)
+			PngHelperInternal.writeBytes(os, data, 0, len);
+		PngHelperInternal.writeInt4(os, crcval);
 	}
 
 	/**
 	 * position before: just after chunk id. positon after: after crc Data should be already allocated. Checks CRC
 	 * Return number of byte read.
 	 */
-	public int readChunkData(InputStream is) {
-		PngHelper.readBytes(is, data, 0, len);
-		int crcori = PngHelper.readInt4(is);
-		computeCrc();
-		if (crcori != crcval)
-			throw new PngjBadCrcException("crc invalid for chunk " + toString() + " calc=" + crcval + " read=" + crcori);
+	public int readChunkData(InputStream is, boolean checkCrc) {
+		PngHelperInternal.readBytes(is, data, 0, len);
+		crcval = PngHelperInternal.readInt4(is);
+		if (checkCrc) {
+			int crc = computeCrc();
+			if (crc != crcval)
+				throw new PngjBadCrcException("chunk: " + this + " crc calc=" + crc + " read=" + crcval);
+		}
 		return len + 4;
 	}
 
-	public ByteArrayInputStream getAsByteStream() { // only the data
+	ByteArrayInputStream getAsByteStream() { // only the data
 		return new ByteArrayInputStream(data);
 	}
 
-	private void allocData() {
-		if (data == null || data.length < len)
-			data = new byte[len];
+	public String toString() {
+		return "chunkid=" + ChunkHelper.toString(idbytes) + " len=" + len;
 	}
+
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java
new file mode 100644
index 0000000..ad788f1
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksList.java
@@ -0,0 +1,174 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngjException;
+
+/**
+ * All chunks that form an image, read or to be written.
+ * <p>
+ * chunks include all chunks, but IDAT is a single pseudo chunk without data
+ **/
+public class ChunksList {
+	// ref: http://www.w3.org/TR/PNG/#table53
+	public static final int CHUNK_GROUP_0_IDHR = 0; // required - single
+	public static final int CHUNK_GROUP_1_AFTERIDHR = 1; // optional - multiple
+	public static final int CHUNK_GROUP_2_PLTE = 2; // optional - single
+	public static final int CHUNK_GROUP_3_AFTERPLTE = 3; // optional - multple
+	public static final int CHUNK_GROUP_4_IDAT = 4; // required (single pseudo chunk)
+	public static final int CHUNK_GROUP_5_AFTERIDAT = 5; // optional - multple
+	public static final int CHUNK_GROUP_6_END = 6; // only 1 chunk - requried
+
+	/**
+	 * All chunks, read (or written)
+	 * 
+	 * But IDAT is a single pseudo chunk without data
+	 */
+	protected List<PngChunk> chunks = new ArrayList<PngChunk>();
+
+	final ImageInfo imageInfo; // only required for writing
+
+	public ChunksList(ImageInfo imfinfo) {
+		this.imageInfo = imfinfo;
+	}
+
+	/**
+	 * Keys of processed (read or writen) chunks
+	 * 
+	 * @return key:chunk id, val: number of occurrences
+	 */
+	public HashMap<String, Integer> getChunksKeys() {
+		HashMap<String, Integer> ck = new HashMap<String, Integer>();
+		for (PngChunk c : chunks) {
+			ck.put(c.id, ck.containsKey(c.id) ? ck.get(c.id) + 1 : 1);
+		}
+		return ck;
+	}
+
+	/**
+	 * Returns a copy of the list (but the chunks are not copied) <b> This should not be used for general metadata
+	 * handling
+	 */
+	public ArrayList<PngChunk> getChunks() {
+		return new ArrayList<PngChunk>(chunks);
+	}
+
+	protected static List<PngChunk> getXById(final List<PngChunk> list, final String id, final String innerid) {
+		if (innerid == null)
+			return ChunkHelper.filterList(list, new ChunkPredicate() {
+				public boolean match(PngChunk c) {
+					return c.id.equals(id);
+				}
+			});
+		else
+			return ChunkHelper.filterList(list, new ChunkPredicate() {
+				public boolean match(PngChunk c) {
+					if (!c.id.equals(id))
+						return false;
+					if (c instanceof PngChunkTextVar && !((PngChunkTextVar) c).getKey().equals(innerid))
+						return false;
+					if (c instanceof PngChunkSPLT && !((PngChunkSPLT) c).getPalName().equals(innerid))
+						return false;
+					return true;
+				}
+			});
+	}
+
+	/**
+	 * Adds chunk in next position. This is used onyl by the pngReader
+	 */
+	public void appendReadChunk(PngChunk chunk, int chunkGroup) {
+		chunk.setChunkGroup(chunkGroup);
+		chunks.add(chunk);
+	}
+
+	/**
+	 * All chunks with this ID
+	 * 
+	 * @param id
+	 * @return List, empty if none
+	 */
+	public List<? extends PngChunk> getById(final String id) {
+		return getById(id, null);
+	}
+
+	/**
+	 * If innerid!=null and the chunk is PngChunkTextVar or PngChunkSPLT, it's filtered by that id
+	 * 
+	 * @param id
+	 * @return innerid Only used for text and SPLT chunks
+	 * @return List, empty if none
+	 */
+	public List<? extends PngChunk> getById(final String id, final String innerid) {
+		return getXById(chunks, id, innerid);
+	}
+
+	/**
+	 * Returns only one chunk
+	 * 
+	 * @param id
+	 * @return First chunk found, null if not found
+	 */
+	public PngChunk getById1(final String id) {
+		return getById1(id, false);
+	}
+
+	/**
+	 * Returns only one chunk or null if nothing found - does not include queued
+	 * <p>
+	 * If more than one chunk is found, then an exception is thrown (failifMultiple=true or chunk is single) or the last
+	 * one is returned (failifMultiple=false)
+	 **/
+	public PngChunk getById1(final String id, final boolean failIfMultiple) {
+		return getById1(id, null, failIfMultiple);
+	}
+
+	/**
+	 * Returns only one chunk or null if nothing found - does not include queued
+	 * <p>
+	 * If more than one chunk (after filtering by inner id) is found, then an exception is thrown (failifMultiple=true
+	 * or chunk is single) or the last one is returned (failifMultiple=false)
+	 **/
+	public PngChunk getById1(final String id, final String innerid, final boolean failIfMultiple) {
+		List<? extends PngChunk> list = getById(id, innerid);
+		if (list.isEmpty())
+			return null;
+		if (list.size() > 1 && (failIfMultiple || !list.get(0).allowsMultiple()))
+			throw new PngjException("unexpected multiple chunks id=" + id);
+		return list.get(list.size() - 1);
+	}
+
+	/**
+	 * Finds all chunks "equivalent" to this one
+	 * 
+	 * @param c2
+	 * @return Empty if nothing found
+	 */
+	public List<PngChunk> getEquivalent(final PngChunk c2) {
+		return ChunkHelper.filterList(chunks, new ChunkPredicate() {
+			public boolean match(PngChunk c) {
+				return ChunkHelper.equivalent(c, c2);
+			}
+		});
+	}
+
+	public String toString() {
+		return "ChunkList: read: " + chunks.size();
+	}
+
+	/**
+	 * for debugging
+	 */
+	public String toStringFull() {
+		StringBuilder sb = new StringBuilder(toString());
+		sb.append("\n Read:\n");
+		for (PngChunk chunk : chunks) {
+			sb.append(chunk).append(" G=" + chunk.getChunkGroup() + "\n");
+		}
+		return sb.toString();
+	}
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java
new file mode 100644
index 0000000..204c4c2
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunksListForWrite.java
@@ -0,0 +1,171 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngjException;
+import jogamp.opengl.util.pngj.PngjOutputException;
+
+public class ChunksListForWrite extends ChunksList {
+
+	/**
+	 * chunks not yet writen - does not include IHDR, IDAT, END, perhaps yes PLTE
+	 */
+	private final List<PngChunk> queuedChunks = new ArrayList<PngChunk>();
+
+	// redundant, just for eficciency
+	private HashMap<String, Integer> alreadyWrittenKeys = new HashMap<String, Integer>();
+
+	public ChunksListForWrite(ImageInfo imfinfo) {
+		super(imfinfo);
+	}
+
+	/**
+	 * Same as getById(), but looking in the queued chunks
+	 */
+	public List<? extends PngChunk> getQueuedById(final String id) {
+		return getQueuedById(id, null);
+	}
+
+	/**
+	 * Same as getById(), but looking in the queued chunks
+	 */
+	public List<? extends PngChunk> getQueuedById(final String id, final String innerid) {
+		return getXById(queuedChunks, id, innerid);
+	}
+
+	/**
+	 * Same as getById1(), but looking in the queued chunks
+	 **/
+	public PngChunk getQueuedById1(final String id, final String innerid, final boolean failIfMultiple) {
+		List<? extends PngChunk> list = getQueuedById(id, innerid);
+		if (list.isEmpty())
+			return null;
+		if (list.size() > 1 && (failIfMultiple || !list.get(0).allowsMultiple()))
+			throw new PngjException("unexpected multiple chunks id=" + id);
+		return list.get(list.size() - 1);
+	}
+
+	/**
+	 * Same as getById1(), but looking in the queued chunks
+	 **/
+	public PngChunk getQueuedById1(final String id, final boolean failIfMultiple) {
+		return getQueuedById1(id, null, failIfMultiple);
+	}
+
+	/**
+	 * Same as getById1(), but looking in the queued chunks
+	 **/
+	public PngChunk getQueuedById1(final String id) {
+		return getQueuedById1(id, false);
+	}
+
+	/**
+	 * Remove Chunk: only from queued
+	 * 
+	 * WARNING: this depends on c.equals() implementation, which is straightforward for SingleChunks. For
+	 * MultipleChunks, it will normally check for reference equality!
+	 */
+	public boolean removeChunk(PngChunk c) {
+		return queuedChunks.remove(c);
+	}
+
+	/**
+	 * Adds chunk to queue
+	 * 
+	 * Does not check for duplicated or anything
+	 * 
+	 * @param c
+	 */
+	public boolean queue(PngChunk c) {
+		queuedChunks.add(c);
+		return true;
+	}
+
+	/**
+	 * this should be called only for ancillary chunks and PLTE (groups 1 - 3 - 5)
+	 **/
+	private static boolean shouldWrite(PngChunk c, int currentGroup) {
+		if (currentGroup == CHUNK_GROUP_2_PLTE)
+			return c.id.equals(ChunkHelper.PLTE);
+		if (currentGroup % 2 == 0)
+			throw new PngjOutputException("bad chunk group?");
+		int minChunkGroup, maxChunkGroup;
+		if (c.getOrderingConstraint().mustGoBeforePLTE())
+			minChunkGroup = maxChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+		else if (c.getOrderingConstraint().mustGoBeforeIDAT()) {
+			maxChunkGroup = ChunksList.CHUNK_GROUP_3_AFTERPLTE;
+			minChunkGroup = c.getOrderingConstraint().mustGoAfterPLTE() ? ChunksList.CHUNK_GROUP_3_AFTERPLTE
+					: ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+		} else {
+			maxChunkGroup = ChunksList.CHUNK_GROUP_5_AFTERIDAT;
+			minChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
+		}
+
+		int preferred = maxChunkGroup;
+		if (c.hasPriority())
+			preferred = minChunkGroup;
+		if (ChunkHelper.isUnknown(c) && c.getChunkGroup() > 0)
+			preferred = c.getChunkGroup();
+		if (currentGroup == preferred)
+			return true;
+		if (currentGroup > preferred && currentGroup <= maxChunkGroup)
+			return true;
+		return false;
+	}
+
+	public int writeChunks(OutputStream os, int currentGroup) {
+		int cont = 0;
+		Iterator<PngChunk> it = queuedChunks.iterator();
+		while (it.hasNext()) {
+			PngChunk c = it.next();
+			if (!shouldWrite(c, currentGroup))
+				continue;
+			if (ChunkHelper.isCritical(c.id) && !c.id.equals(ChunkHelper.PLTE))
+				throw new PngjOutputException("bad chunk queued: " + c);
+			if (alreadyWrittenKeys.containsKey(c.id) && !c.allowsMultiple())
+				throw new PngjOutputException("duplicated chunk does not allow multiple: " + c);
+			c.write(os);
+			chunks.add(c);
+			alreadyWrittenKeys.put(c.id, alreadyWrittenKeys.containsKey(c.id) ? alreadyWrittenKeys.get(c.id) + 1 : 1);
+			c.setChunkGroup(currentGroup);
+			it.remove();
+			cont++;
+		}
+		return cont;
+	}
+
+	/**
+	 * warning: this is NOT a copy, do not modify
+	 */
+	public List<PngChunk> getQueuedChunks() {
+		return queuedChunks;
+	}
+
+	public String toString() {
+		return "ChunkList: written: " + chunks.size() + " queue: " + queuedChunks.size();
+	}
+
+	/**
+	 * for debugging
+	 */
+	public String toStringFull() {
+		StringBuilder sb = new StringBuilder(toString());
+		sb.append("\n Written:\n");
+		for (PngChunk chunk : chunks) {
+			sb.append(chunk).append(" G=" + chunk.getChunkGroup() + "\n");
+		}
+		if (!queuedChunks.isEmpty()) {
+			sb.append(" Queued:\n");
+			for (PngChunk chunk : queuedChunks) {
+				sb.append(chunk).append("\n");
+			}
+
+		}
+		return sb.toString();
+	}
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java
index 2df9fd1..1d63059 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunk.java
@@ -6,26 +6,87 @@ import java.util.HashMap;
 import java.util.Map;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngjException;
+import jogamp.opengl.util.pngj.PngjExceptionInternal;
 
-
-// see http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
+/**
+ * Represents a instance of a PNG chunk.
+ * <p>
+ * See <a
+ * href="http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html">http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks
+ * .html</a> </a>
+ * <p>
+ * Concrete classes should extend {@link PngChunkSingle} or {@link PngChunkMultiple}
+ * <p>
+ * Note that some methods/fields are type-specific (getOrderingConstraint(), allowsMultiple()),<br>
+ * some are 'almost' type-specific (id,crit,pub,safe; the exception is PngUKNOWN), <br>
+ * and the rest are instance-specific
+ */
 public abstract class PngChunk {
 
-	public final String id; // 4 letters
+	/**
+	 * Chunk-id: 4 letters
+	 */
+	public final String id;
+	/**
+	 * Autocomputed at creation time
+	 */
 	public final boolean crit, pub, safe;
-	private int lenori = -1; // merely informational, for read chunks
 
-	private boolean writePriority = false; // for queued chunks
 	protected final ImageInfo imgInfo;
 
-	private int chunkGroup = -1; // chunk group where it was read or writen
+	/**
+	 * Possible ordering constraint for a PngChunk type -only relevant for ancillary chunks. Theoretically, there could
+	 * be more general constraints, but these cover the constraints for standard chunks.
+	 */
+	public enum ChunkOrderingConstraint {
+		/**
+		 * no ordering constraint
+		 */
+		NONE,
+		/**
+		 * Must go before PLTE (and hence, also before IDAT)
+		 */
+		BEFORE_PLTE_AND_IDAT,
+		/**
+		 * Must go after PLTE but before IDAT
+		 */
+		AFTER_PLTE_BEFORE_IDAT,
+		/**
+		 * Must before IDAT (before or after PLTE)
+		 */
+		BEFORE_IDAT,
+		/**
+		 * Does not apply
+		 */
+		NA;
+
+		public boolean mustGoBeforePLTE() {
+			return this == BEFORE_PLTE_AND_IDAT;
+		}
+
+		public boolean mustGoBeforeIDAT() {
+			return this == BEFORE_IDAT || this == BEFORE_PLTE_AND_IDAT || this == AFTER_PLTE_BEFORE_IDAT;
+		}
+
+		public boolean mustGoAfterPLTE() {
+			return this == AFTER_PLTE_BEFORE_IDAT;
+		}
+	}
+
+	private boolean priority = false; // For writing. Queued chunks with high priority will be written as soon as
+										// possible
+
+	protected int chunkGroup = -1; // chunk group where it was read or writen
+	protected int length = -1; // merely informational, for read chunks
+	protected long offset = 0; // merely informational, for read chunks
 
 	/**
-	 * This static map defines which PngChunk class correspond to which ChunkID The client can add other chunks to this
-	 * map statically, before reading
+	 * This static map defines which PngChunk class correspond to which ChunkID
+	 * <p>
+	 * The client can add other chunks to this map statically, before reading an image, calling
+	 * PngChunk.factoryRegister(id,class)
 	 */
-	public final static Map<String, Class<? extends PngChunk>> factoryMap = new HashMap<String, Class<? extends PngChunk>>();
+	private final static Map<String, Class<? extends PngChunk>> factoryMap = new HashMap<String, Class<? extends PngChunk>>();
 	static {
 		factoryMap.put(ChunkHelper.IDAT, PngChunkIDAT.class);
 		factoryMap.put(ChunkHelper.IHDR, PngChunkIHDR.class);
@@ -45,6 +106,32 @@ public abstract class PngChunk {
 		factoryMap.put(ChunkHelper.sRGB, PngChunkSRGB.class);
 		factoryMap.put(ChunkHelper.hIST, PngChunkHIST.class);
 		factoryMap.put(ChunkHelper.sPLT, PngChunkSPLT.class);
+		// extended
+		factoryMap.put(PngChunkOFFS.ID, PngChunkOFFS.class);
+		factoryMap.put(PngChunkSTER.ID, PngChunkSTER.class);
+	}
+
+	/**
+	 * Registers a chunk-id (4 letters) to be associated with a PngChunk class
+	 * <p>
+	 * This method should be called by user code that wants to add some chunks (not implmemented in this library) to the
+	 * factory, so that the PngReader knows about it.
+	 */
+	public static void factoryRegister(String chunkId, Class<? extends PngChunk> chunkClass) {
+		factoryMap.put(chunkId, chunkClass);
+	}
+
+	/**
+	 * True if the chunk-id type is known.
+	 * <p>
+	 * A chunk is known if we recognize its class, according with <code>factoryMap</code>
+	 * <p>
+	 * This is not necessarily the same as being "STANDARD", or being implemented in this library
+	 * <p>
+	 * Unknown chunks will be parsed as instances of {@link PngChunkUNKNOWN}
+	 */
+	public static boolean isKnown(String id) {
+		return factoryMap.containsKey(id);
 	}
 
 	protected PngChunk(String id, ImageInfo imgInfo) {
@@ -55,29 +142,19 @@ public abstract class PngChunk {
 		this.safe = ChunkHelper.isSafeToCopy(id);
 	}
 
-	public abstract ChunkRaw createChunk();
-
-	public abstract void parseFromChunk(ChunkRaw c);
-
-	// override to make deep copy from read data to write
-	public abstract void cloneDataFromRead(PngChunk other);
-
-	@SuppressWarnings("unchecked")
-	public static <T extends PngChunk> T cloneChunk(T chunk, ImageInfo info) {
-		PngChunk cn = factoryFromId(chunk.id, info);
-		if (cn.getClass() != chunk.getClass())
-			throw new PngjException("bad class cloning chunk: " + cn.getClass() + " " + chunk.getClass());
-		cn.cloneDataFromRead(chunk);
-		return (T) cn;
-	}
-
+	/**
+	 * This factory creates the corresponding chunk and parses the raw chunk. This is used when reading.
+	 */
 	public static PngChunk factory(ChunkRaw chunk, ImageInfo info) {
 		PngChunk c = factoryFromId(ChunkHelper.toString(chunk.idbytes), info);
-		c.lenori = chunk.len;
-		c.parseFromChunk(chunk);
+		c.length = chunk.len;
+		c.parseFromRaw(chunk);
 		return c;
 	}
 
+	/**
+	 * Creates one new blank chunk of the corresponding type, according to factoryMap (PngChunkUNKNOWN if not known)
+	 */
 	public static PngChunk factoryFromId(String cid, ImageInfo info) {
 		PngChunk chunk = null;
 		try {
@@ -87,66 +164,110 @@ public abstract class PngChunk {
 				chunk = constr.newInstance(info);
 			}
 		} catch (Exception e) {
-			// this can happend for unkown chunks
+			// this can happen for unkown chunks
 		}
 		if (chunk == null)
 			chunk = new PngChunkUNKNOWN(cid, info);
 		return chunk;
 	}
 
-	protected ChunkRaw createEmptyChunk(int len, boolean alloc) {
+	protected final ChunkRaw createEmptyChunk(int len, boolean alloc) {
 		ChunkRaw c = new ChunkRaw(len, ChunkHelper.toBytes(id), alloc);
 		return c;
 	}
 
-	@Override
-	public String toString() {
-		return "chunk id= " + id + " (" + lenori + ") c=" + getClass().getSimpleName();
+	/**
+	 * Makes a clone (deep copy) calling {@link #cloneDataFromRead(PngChunk)}
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T extends PngChunk> T cloneChunk(T chunk, ImageInfo info) {
+		PngChunk cn = factoryFromId(chunk.id, info);
+		if (cn.getClass() != chunk.getClass())
+			throw new PngjExceptionInternal("bad class cloning chunk: " + cn.getClass() + " " + chunk.getClass());
+		cn.cloneDataFromRead(chunk);
+		return (T) cn;
 	}
 
-	void setPriority(boolean highPrioriy) {
-		writePriority = highPrioriy;
+	/**
+	 * In which "chunkGroup" (see {@link ChunksList}for definition) this chunks instance was read or written.
+	 * <p>
+	 * -1 if not read or written (eg, queued)
+	 */
+	final public int getChunkGroup() {
+		return chunkGroup;
 	}
 
-	void write(OutputStream os) {
-		ChunkRaw c = createChunk();
-		if (c == null)
-			throw new PngjException("null chunk ! creation failed for " + this);
-		c.writeChunk(os);
+	/**
+	 * @see #getChunkGroup()
+	 */
+	final public void setChunkGroup(int chunkGroup) {
+		this.chunkGroup = chunkGroup;
 	}
 
-	public boolean isWritePriority() {
-		return writePriority;
+	public boolean hasPriority() {
+		return priority;
 	}
 
-	/** must be overriden - only relevant for ancillary chunks */
-	public boolean allowsMultiple() {
-		return false; // override if allows multiple ocurrences
+	public void setPriority(boolean priority) {
+		this.priority = priority;
 	}
 
-	/** mustGoBeforeXX/After must be overriden - only relevant for ancillary chunks */
-	public boolean mustGoBeforeIDAT() {
-		return false;
+	final void write(OutputStream os) {
+		ChunkRaw c = createRawChunk();
+		if (c == null)
+			throw new PngjExceptionInternal("null chunk ! creation failed for " + this);
+		c.writeChunk(os);
 	}
 
-	public boolean mustGoBeforePLTE() {
-		return false;
+	public int getLength() {
+		return length;
 	}
 
-	public boolean mustGoAfterPLTE() {
-		return false;
-	}
+	/*
+	 * public void setLength(int length) { this.length = length; }
+	 */
 
-	static boolean isKnown(String id) {
-		return factoryMap.containsKey(id);
+	public long getOffset() {
+		return offset;
 	}
 
-	public int getChunkGroup() {
-		return chunkGroup;
+	public void setOffset(long offset) {
+		this.offset = offset;
 	}
 
-	public void setChunkGroup(int chunkGroup) {
-		this.chunkGroup = chunkGroup;
+	/**
+	 * Creates the physical chunk. This is used when writing (serialization). Each particular chunk class implements its
+	 * own logic.
+	 * 
+	 * @return A newly allocated and filled raw chunk
+	 */
+	public abstract ChunkRaw createRawChunk();
+
+	/**
+	 * Parses raw chunk and fill inside data. This is used when reading (deserialization). Each particular chunk class
+	 * implements its own logic.
+	 */
+	public abstract void parseFromRaw(ChunkRaw c);
+
+	/**
+	 * Makes a copy of the chunk.
+	 * <p>
+	 * This is used when copying chunks from a reader to a writer
+	 * <p>
+	 * It should normally be a deep copy, and after the cloning this.equals(other) should return true
+	 */
+	public abstract void cloneDataFromRead(PngChunk other);
+
+	public abstract boolean allowsMultiple(); // this is implemented in PngChunkMultiple/PngChunSingle
+
+	/**
+	 * see {@link ChunkOrderingConstraint}
+	 */
+	public abstract ChunkOrderingConstraint getOrderingConstraint();
+
+	@Override
+	public String toString() {
+		return "chunk id= " + id + " (len=" + length + " offset=" + offset + ") c=" + getClass().getSimpleName();
 	}
 
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java
index 51bbcb8..4a8502a 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java
@@ -1,14 +1,18 @@
 package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
-/*
+/**
+ * bKGD Chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11bKGD
+ * <p>
+ * this chunk structure depends on the image type
  */
-public class PngChunkBKGD extends PngChunk {
-	// http://www.w3.org/TR/PNG/#11bKGD
-	// this chunk structure depends on the image type
+public class PngChunkBKGD extends PngChunkSingle {
+	public final static String ID = ChunkHelper.bKGD;
 	// only one of these is meaningful
 	private int gray;
 	private int red, green, blue;
@@ -19,43 +23,38 @@ public class PngChunkBKGD extends PngChunk {
 	}
 
 	@Override
-	public boolean mustGoBeforeIDAT() {
-		return true;
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;
 	}
 
 	@Override
-	public boolean mustGoAfterPLTE() {
-		return true;
-	}
-
-	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = null;
 		if (imgInfo.greyscale) {
 			c = createEmptyChunk(2, true);
-			PngHelper.writeInt2tobytes(gray, c.data, 0);
+			PngHelperInternal.writeInt2tobytes(gray, c.data, 0);
 		} else if (imgInfo.indexed) {
 			c = createEmptyChunk(1, true);
 			c.data[0] = (byte) paletteIndex;
 		} else {
 			c = createEmptyChunk(6, true);
-			PngHelper.writeInt2tobytes(red, c.data, 0);
-			PngHelper.writeInt2tobytes(green, c.data, 0);
-			PngHelper.writeInt2tobytes(blue, c.data, 0);
+			PngHelperInternal.writeInt2tobytes(red, c.data, 0);
+			PngHelperInternal.writeInt2tobytes(green, c.data, 0);
+			PngHelperInternal.writeInt2tobytes(blue, c.data, 0);
 		}
 		return c;
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		if (imgInfo.greyscale) {
-			gray = PngHelper.readInt2fromBytes(c.data, 0);
+			gray = PngHelperInternal.readInt2fromBytes(c.data, 0);
 		} else if (imgInfo.indexed) {
 			paletteIndex = (int) (c.data[0] & 0xff);
 		} else {
-			red = PngHelper.readInt2fromBytes(c.data, 0);
-			green = PngHelper.readInt2fromBytes(c.data, 2);
-			blue = PngHelper.readInt2fromBytes(c.data, 4);
+			red = PngHelperInternal.readInt2fromBytes(c.data, 0);
+			green = PngHelperInternal.readInt2fromBytes(c.data, 2);
+			blue = PngHelperInternal.readInt2fromBytes(c.data, 4);
 		}
 	}
 
@@ -119,4 +118,5 @@ public class PngChunkBKGD extends PngChunk {
 			throw new PngjException("only rgb or rgba images support this");
 		return new int[] { red, green, blue };
 	}
+
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java
index 4380761..25a4bf2 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java
@@ -1,12 +1,17 @@
 package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
-/*
+/**
+ * cHRM chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11cHRM
  */
-public class PngChunkCHRM extends PngChunk {
+public class PngChunkCHRM extends PngChunkSingle {
+	public final static String ID = ChunkHelper.cHRM;
+
 	// http://www.w3.org/TR/PNG/#11cHRM
 	private double whitex, whitey;
 	private double redx, redy;
@@ -14,46 +19,41 @@ public class PngChunkCHRM extends PngChunk {
 	private double bluex, bluey;
 
 	public PngChunkCHRM(ImageInfo info) {
-		super(ChunkHelper.cHRM, info);
-	}
-
-	@Override
-	public boolean mustGoBeforeIDAT() {
-		return true;
+		super(ID, info);
 	}
 
 	@Override
-	public boolean mustGoBeforePLTE() {
-		return true;
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = null;
 		c = createEmptyChunk(32, true);
-		PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(whitex), c.data, 0);
-		PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(whitey), c.data, 4);
-		PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(redx), c.data, 8);
-		PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(redy), c.data, 12);
-		PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(greenx), c.data, 16);
-		PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(greeny), c.data, 20);
-		PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(bluex), c.data, 24);
-		PngHelper.writeInt4tobytes(PngHelper.doubleToInt100000(bluey), c.data, 28);
+		PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(whitex), c.data, 0);
+		PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(whitey), c.data, 4);
+		PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(redx), c.data, 8);
+		PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(redy), c.data, 12);
+		PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(greenx), c.data, 16);
+		PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(greeny), c.data, 20);
+		PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(bluex), c.data, 24);
+		PngHelperInternal.writeInt4tobytes(PngHelperInternal.doubleToInt100000(bluey), c.data, 28);
 		return c;
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		if (c.len != 32)
 			throw new PngjException("bad chunk " + c);
-		whitex = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 0));
-		whitey = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 4));
-		redx = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 8));
-		redy = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 12));
-		greenx = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 16));
-		greeny = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 20));
-		bluex = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 24));
-		bluey = PngHelper.intToDouble100000(PngHelper.readInt4fromBytes(c.data, 28));
+		whitex = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 0));
+		whitey = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 4));
+		redx = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 8));
+		redy = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 12));
+		greenx = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 16));
+		greeny = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 20));
+		bluex = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 24));
+		bluey = PngHelperInternal.intToDouble100000(PngHelperInternal.readInt4fromBytes(c.data, 28));
 	}
 
 	@Override
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java
index 184ee9f..7464074 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java
@@ -1,42 +1,42 @@
 package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
-/*
+/**
+ * gAMA chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11gAMA
  */
-public class PngChunkGAMA extends PngChunk {
+public class PngChunkGAMA extends PngChunkSingle {
+	public final static String ID = ChunkHelper.gAMA;
+
 	// http://www.w3.org/TR/PNG/#11gAMA
 	private double gamma;
 
 	public PngChunkGAMA(ImageInfo info) {
-		super(ChunkHelper.gAMA, info);
-	}
-
-	@Override
-	public boolean mustGoBeforeIDAT() {
-		return true;
+		super(ID, info);
 	}
 
 	@Override
-	public boolean mustGoBeforePLTE() {
-		return true;
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT;
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = createEmptyChunk(4, true);
 		int g = (int) (gamma * 100000 + 0.5);
-		PngHelper.writeInt4tobytes(g, c.data, 0);
+		PngHelperInternal.writeInt4tobytes(g, c.data, 0);
 		return c;
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw chunk) {
+	public void parseFromRaw(ChunkRaw chunk) {
 		if (chunk.len != 4)
 			throw new PngjException("bad chunk " + chunk);
-		int g = PngHelper.readInt4fromBytes(chunk.data, 0);
+		int g = PngHelperInternal.readInt4fromBytes(chunk.data, 0);
 		gamma = ((double) g) / 100000.0;
 	}
 
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java
index b0f02ea..6dc3fd9 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java
@@ -1,50 +1,48 @@
 package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
-/*
+/**
+ * hIST chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11hIST <br>
+ * only for palette images
  */
-public class PngChunkHIST extends PngChunk {
-	// http://www.w3.org/TR/PNG/#11hIST
-	// only for palette images
+public class PngChunkHIST extends PngChunkSingle {
+	public final static String ID = ChunkHelper.hIST;
 
 	private int[] hist = new int[0]; // should have same lenght as palette
 
 	public PngChunkHIST(ImageInfo info) {
-		super(ChunkHelper.hIST, info);
+		super(ID, info);
 	}
 
 	@Override
-	public boolean mustGoBeforeIDAT() {
-		return true;
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;
 	}
 
 	@Override
-	public boolean mustGoAfterPLTE() {
-		return true;
-	}
-
-	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		if (!imgInfo.indexed)
 			throw new PngjException("only indexed images accept a HIST chunk");
 		int nentries = c.data.length / 2;
 		hist = new int[nentries];
 		for (int i = 0; i < hist.length; i++) {
-			hist[i] = PngHelper.readInt2fromBytes(c.data, i * 2);
+			hist[i] = PngHelperInternal.readInt2fromBytes(c.data, i * 2);
 		}
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		if (!imgInfo.indexed)
 			throw new PngjException("only indexed images accept a HIST chunk");
 		ChunkRaw c = null;
 		c = createEmptyChunk(hist.length * 2, true);
 		for (int i = 0; i < hist.length; i++) {
-			PngHelper.writeInt2tobytes(hist[i], c.data, i * 2);
+			PngHelperInternal.writeInt2tobytes(hist[i], c.data, i * 2);
 		}
 		return c;
 	}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java
index db1c1ba..399577d 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java
@@ -1,31 +1,32 @@
 package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
+import jogamp.opengl.util.pngj.PngjException;
 
-/*
+/**
+ * iCCP chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11iCCP
  */
-public class PngChunkICCP extends PngChunk {
+public class PngChunkICCP extends PngChunkSingle {
+	public final static String ID = ChunkHelper.iCCP;
+
 	// http://www.w3.org/TR/PNG/#11iCCP
 	private String profileName;
 	private byte[] compressedProfile; // copmression/decopmresion is done in getter/setter
 
 	public PngChunkICCP(ImageInfo info) {
-		super(ChunkHelper.iCCP, info);
-	}
-
-	@Override
-	public boolean mustGoBeforeIDAT() {
-		return true;
+		super(ID, info);
 	}
 
 	@Override
-	public boolean mustGoBeforePLTE() {
-		return true;
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT;
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = createEmptyChunk(profileName.length() + compressedProfile.length + 2, true);
 		System.arraycopy(ChunkHelper.toBytes(profileName), 0, c.data, 0, profileName.length());
 		c.data[profileName.length()] = 0;
@@ -35,12 +36,12 @@ public class PngChunkICCP extends PngChunk {
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw chunk) {
+	public void parseFromRaw(ChunkRaw chunk) {
 		int pos0 = ChunkHelper.posNullByte(chunk.data);
-		profileName = new String(chunk.data, 0, pos0, PngHelper.charsetLatin1);
+		profileName = new String(chunk.data, 0, pos0, PngHelperInternal.charsetLatin1);
 		int comp = (chunk.data[pos0 + 1] & 0xff);
 		if (comp != 0)
-			throw new RuntimeException("bad compression for ChunkTypeICCP");
+			throw new PngjException("bad compression for ChunkTypeICCP");
 		int compdatasize = chunk.data.length - (pos0 + 2);
 		compressedProfile = new byte[compdatasize];
 		System.arraycopy(chunk.data, pos0 + 2, compressedProfile, 0, compdatasize);
@@ -64,7 +65,7 @@ public class PngChunkICCP extends PngChunk {
 	}
 
 	public void setProfileNameAndContent(String name, String profile) {
-		setProfileNameAndContent(name, profile.getBytes(PngHelper.charsetLatin1));
+		setProfileNameAndContent(name, profile.getBytes(PngHelperInternal.charsetLatin1));
 	}
 
 	public String getProfileName() {
@@ -79,7 +80,7 @@ public class PngChunkICCP extends PngChunk {
 	}
 
 	public String getProfileAsString() {
-		return new String(getProfile(), PngHelper.charsetLatin1);
+		return new String(getProfile(), PngHelperInternal.charsetLatin1);
 	}
 
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
index a7cb95d..b816db2 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
@@ -2,21 +2,35 @@ package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
 
-public class PngChunkIDAT extends PngChunk {
+/**
+ * IDAT chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11IDAT
+ * <p>
+ * This is dummy placeholder - we write/read this chunk (actually several) by special code.
+ */
+public class PngChunkIDAT extends PngChunkMultiple {
+	public final static String ID = ChunkHelper.IDAT;
+
 	// http://www.w3.org/TR/PNG/#11IDAT
-	// This is dummy placeholder - we write/read this chunk (actually several)
-	// by special code.
-	public PngChunkIDAT(ImageInfo i) {
-		super(ChunkHelper.IDAT, i);
+	public PngChunkIDAT(ImageInfo i, int len, long offset) {
+		super(ID, i);
+		this.length = len;
+		this.offset = offset;
+	}
+
+	@Override
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.NA;
 	}
 
 	@Override
-	public ChunkRaw createChunk() {// does nothing
+	public ChunkRaw createRawChunk() {// does nothing
 		return null;
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) { // does nothing
+	public void parseFromRaw(ChunkRaw c) { // does nothing
 	}
 
 	@Override
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java
index 0d5b266..fbec564 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java
@@ -2,21 +2,33 @@ package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
 
-public class PngChunkIEND extends PngChunk {
+/**
+ * IEND chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11IEND
+ */
+public class PngChunkIEND extends PngChunkSingle {
+	public final static String ID = ChunkHelper.IEND;
+
 	// http://www.w3.org/TR/PNG/#11IEND
 	// this is a dummy placeholder
 	public PngChunkIEND(ImageInfo info) {
-		super(ChunkHelper.IEND, info);
+		super(ID, info);
+	}
+
+	@Override
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.NA;
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = new ChunkRaw(0, ChunkHelper.b_IEND, false);
 		return c;
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		// this is not used
 	}
 
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIHDR.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIHDR.java
index fcb4150..94bfedd 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIHDR.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIHDR.java
@@ -3,14 +3,20 @@ package jogamp.opengl.util.pngj.chunks;
 import java.io.ByteArrayInputStream;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
 
 /**
- * this is a special chunk!
+ * IHDR chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11IHDR
+ * <p>
+ * This is a special critical Chunk.
  */
-public class PngChunkIHDR extends PngChunk {
+public class PngChunkIHDR extends PngChunkSingle {
+	public final static String ID = ChunkHelper.IHDR;
+
 	private int cols;
 	private int rows;
 	private int bitspc;
@@ -22,16 +28,21 @@ public class PngChunkIHDR extends PngChunk {
 	// http://www.w3.org/TR/PNG/#11IHDR
 	//
 	public PngChunkIHDR(ImageInfo info) {
-		super(ChunkHelper.IHDR, info);
+		super(ID, info);
+	}
+
+	@Override
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.NA;
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = new ChunkRaw(13, ChunkHelper.b_IHDR, true);
 		int offset = 0;
-		PngHelper.writeInt4tobytes(cols, c.data, offset);
+		PngHelperInternal.writeInt4tobytes(cols, c.data, offset);
 		offset += 4;
-		PngHelper.writeInt4tobytes(rows, c.data, offset);
+		PngHelperInternal.writeInt4tobytes(rows, c.data, offset);
 		offset += 4;
 		c.data[offset++] = (byte) bitspc;
 		c.data[offset++] = (byte) colormodel;
@@ -42,18 +53,18 @@ public class PngChunkIHDR extends PngChunk {
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		if (c.len != 13)
 			throw new PngjException("Bad IDHR len " + c.len);
 		ByteArrayInputStream st = c.getAsByteStream();
-		cols = PngHelper.readInt4(st);
-		rows = PngHelper.readInt4(st);
+		cols = PngHelperInternal.readInt4(st);
+		rows = PngHelperInternal.readInt4(st);
 		// bit depth: number of bits per channel
-		bitspc = PngHelper.readByte(st);
-		colormodel = PngHelper.readByte(st);
-		compmeth = PngHelper.readByte(st);
-		filmeth = PngHelper.readByte(st);
-		interlaced = PngHelper.readByte(st);
+		bitspc = PngHelperInternal.readByte(st);
+		colormodel = PngHelperInternal.readByte(st);
+		compmeth = PngHelperInternal.readByte(st);
+		filmeth = PngHelperInternal.readByte(st);
+		interlaced = PngHelperInternal.readByte(st);
 	}
 
 	@Override
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java
index 4e5c7c7..ab52d7c 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java
@@ -4,14 +4,17 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
 
 /**
- * UNTESTED!
+ * iTXt chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11iTXt
  */
 public class PngChunkITXT extends PngChunkTextVar {
+	public final static String ID = ChunkHelper.iTXt;
 
 	private boolean compressed = false;
 	private String langTag = "";
@@ -19,24 +22,24 @@ public class PngChunkITXT extends PngChunkTextVar {
 
 	// http://www.w3.org/TR/PNG/#11iTXt
 	public PngChunkITXT(ImageInfo info) {
-		super(ChunkHelper.iTXt, info);
+		super(ID, info);
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
-		if (val.isEmpty() || key.isEmpty())
-			return null;
+	public ChunkRaw createRawChunk() {
+		if (key.isEmpty())
+			throw new PngjException("Text chunk key must be non empty");
 		try {
 			ByteArrayOutputStream ba = new ByteArrayOutputStream();
-			ba.write(key.getBytes(PngHelper.charsetLatin1));
+			ba.write(ChunkHelper.toBytes(key));
 			ba.write(0); // separator
 			ba.write(compressed ? 1 : 0);
 			ba.write(0); // compression method (always 0)
-			ba.write(langTag.getBytes(PngHelper.charsetUTF8));
+			ba.write(ChunkHelper.toBytes(langTag));
 			ba.write(0); // separator
-			ba.write(translatedTag.getBytes(PngHelper.charsetUTF8));
+			ba.write(ChunkHelper.toBytesUTF8(translatedTag));
 			ba.write(0); // separator
-			byte[] textbytes = val.getBytes(PngHelper.charsetUTF8);
+			byte[] textbytes = ChunkHelper.toBytesUTF8(val);
 			if (compressed) {
 				textbytes = ChunkHelper.compressBytes(textbytes, true);
 			}
@@ -51,7 +54,7 @@ public class PngChunkITXT extends PngChunkTextVar {
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		int nullsFound = 0;
 		int[] nullsIdx = new int[3];
 		for (int i = 0; i < c.data.length; i++) {
@@ -66,20 +69,21 @@ public class PngChunkITXT extends PngChunkTextVar {
 		}
 		if (nullsFound != 3)
 			throw new PngjException("Bad formed PngChunkITXT chunk");
-		key = new String(c.data, 0, nullsIdx[0], PngHelper.charsetLatin1);
+		key = ChunkHelper.toString(c.data, 0, nullsIdx[0]);
 		int i = nullsIdx[0] + 1;
 		compressed = c.data[i] == 0 ? false : true;
 		i++;
 		if (compressed && c.data[i] != 0)
 			throw new PngjException("Bad formed PngChunkITXT chunk - bad compression method ");
-		langTag = new String(c.data, i, nullsIdx[1] - i, PngHelper.charsetLatin1);
-		translatedTag = new String(c.data, nullsIdx[1] + 1, nullsIdx[2] - nullsIdx[1] - 1, PngHelper.charsetUTF8);
+		langTag = new String(c.data, i, nullsIdx[1] - i, PngHelperInternal.charsetLatin1);
+		translatedTag = new String(c.data, nullsIdx[1] + 1, nullsIdx[2] - nullsIdx[1] - 1,
+				PngHelperInternal.charsetUTF8);
 		i = nullsIdx[2] + 1;
 		if (compressed) {
 			byte[] bytes = ChunkHelper.compressBytes(c.data, i, c.data.length - i, false);
-			val = new String(bytes, PngHelper.charsetUTF8);
+			val = ChunkHelper.toStringUTF8(bytes);
 		} else {
-			val = new String(c.data, i, c.data.length - i, PngHelper.charsetUTF8);
+			val = ChunkHelper.toStringUTF8(c.data, i, c.data.length - i);
 		}
 	}
 
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java
new file mode 100644
index 0000000..696edd4
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkMultiple.java
@@ -0,0 +1,27 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+
+/**
+ * PNG chunk type (abstract) that allows multiple instances in same image.
+ */
+public abstract class PngChunkMultiple extends PngChunk {
+
+	protected PngChunkMultiple(String id, ImageInfo imgInfo) {
+		super(id, imgInfo);
+	}
+
+	@Override
+	public final boolean allowsMultiple() {
+		return true;
+	}
+
+	/**
+	 * NOTE: this chunk uses the default Object's equals() hashCode() implementation.
+	 * 
+	 * This is the right thing to do, normally.
+	 * 
+	 * This is important, eg see ChunkList.removeFromList()
+	 */
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkOFFS.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkOFFS.java
new file mode 100644
index 0000000..a3bab49
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkOFFS.java
@@ -0,0 +1,89 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngHelperInternal;
+import jogamp.opengl.util.pngj.PngjException;
+
+/**
+ * oFFs chunk.
+ * <p>
+ * see http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.oFFs
+ */
+public class PngChunkOFFS extends PngChunkSingle {
+	public final static String ID = "oFFs";
+
+	// http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.oFFs
+	private long posX;
+	private long posY;
+	private int units; // 0: pixel 1:micrometer
+
+	public PngChunkOFFS(ImageInfo info) {
+		super(ID, info);
+	}
+
+	@Override
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.BEFORE_IDAT;
+	}
+
+	@Override
+	public ChunkRaw createRawChunk() {
+		ChunkRaw c = createEmptyChunk(9, true);
+		PngHelperInternal.writeInt4tobytes((int) posX, c.data, 0);
+		PngHelperInternal.writeInt4tobytes((int) posY, c.data, 4);
+		c.data[8] = (byte) units;
+		return c;
+	}
+
+	@Override
+	public void parseFromRaw(ChunkRaw chunk) {
+		if (chunk.len != 9)
+			throw new PngjException("bad chunk length " + chunk);
+		posX = PngHelperInternal.readInt4fromBytes(chunk.data, 0);
+		if (posX < 0)
+			posX += 0x100000000L;
+		posY = PngHelperInternal.readInt4fromBytes(chunk.data, 4);
+		if (posY < 0)
+			posY += 0x100000000L;
+		units = PngHelperInternal.readInt1fromByte(chunk.data, 8);
+	}
+
+	@Override
+	public void cloneDataFromRead(PngChunk other) {
+		PngChunkOFFS otherx = (PngChunkOFFS) other;
+		this.posX = otherx.posX;
+		this.posY = otherx.posY;
+		this.units = otherx.units;
+	}
+
+	/**
+	 * 0: pixel, 1:micrometer
+	 */
+	public int getUnits() {
+		return units;
+	}
+
+	/**
+	 * 0: pixel, 1:micrometer
+	 */
+	public void setUnits(int units) {
+		this.units = units;
+	}
+
+	public long getPosX() {
+		return posX;
+	}
+
+	public void setPosX(long posX) {
+		this.posX = posX;
+	}
+
+	public long getPosY() {
+		return posY;
+	}
+
+	public void setPosY(long posY) {
+		this.posY = posY;
+	}
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java
index 47e2c49..b0a1bb8 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java
@@ -1,44 +1,50 @@
 package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
+/**
+ * pHYs chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11pHYs
+ */
+public class PngChunkPHYS extends PngChunkSingle {
+	public final static String ID = ChunkHelper.pHYs;
 
-public class PngChunkPHYS extends PngChunk {
 	// http://www.w3.org/TR/PNG/#11pHYs
 	private long pixelsxUnitX;
 	private long pixelsxUnitY;
 	private int units; // 0: unknown 1:metre
 
 	public PngChunkPHYS(ImageInfo info) {
-		super(ChunkHelper.pHYs, info);
+		super(ID, info);
 	}
 
 	@Override
-	public boolean mustGoBeforeIDAT() {
-		return true;
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.BEFORE_IDAT;
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = createEmptyChunk(9, true);
-		PngHelper.writeInt4tobytes((int) pixelsxUnitX, c.data, 0);
-		PngHelper.writeInt4tobytes((int) pixelsxUnitY, c.data, 4);
+		PngHelperInternal.writeInt4tobytes((int) pixelsxUnitX, c.data, 0);
+		PngHelperInternal.writeInt4tobytes((int) pixelsxUnitY, c.data, 4);
 		c.data[8] = (byte) units;
 		return c;
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw chunk) {
+	public void parseFromRaw(ChunkRaw chunk) {
 		if (chunk.len != 9)
 			throw new PngjException("bad chunk length " + chunk);
-		pixelsxUnitX = PngHelper.readInt4fromBytes(chunk.data, 0);
+		pixelsxUnitX = PngHelperInternal.readInt4fromBytes(chunk.data, 0);
 		if (pixelsxUnitX < 0)
 			pixelsxUnitX += 0x100000000L;
-		pixelsxUnitY = PngHelper.readInt4fromBytes(chunk.data, 4);
+		pixelsxUnitY = PngHelperInternal.readInt4fromBytes(chunk.data, 4);
 		if (pixelsxUnitY < 0)
 			pixelsxUnitY += 0x100000000L;
-		units = PngHelper.readInt1fromByte(chunk.data, 8);
+		units = PngHelperInternal.readInt1fromByte(chunk.data, 8);
 	}
 
 	@Override
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPLTE.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPLTE.java
index 123080b..dbf5e53 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPLTE.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPLTE.java
@@ -3,10 +3,16 @@ package jogamp.opengl.util.pngj.chunks;
 import jogamp.opengl.util.pngj.ImageInfo;
 import jogamp.opengl.util.pngj.PngjException;
 
-/*
- * Palette chunk *this is critical*
+/**
+ * PLTE chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11PLTE
+ * <p>
+ * Critical chunk
  */
-public class PngChunkPLTE extends PngChunk {
+public class PngChunkPLTE extends PngChunkSingle {
+	public final static String ID = ChunkHelper.PLTE;
+
 	// http://www.w3.org/TR/PNG/#11PLTE
 	private int nentries = 0;
 	/**
@@ -15,11 +21,16 @@ public class PngChunkPLTE extends PngChunk {
 	private int[] entries;
 
 	public PngChunkPLTE(ImageInfo info) {
-		super(ChunkHelper.PLTE, info);
+		super(ID, info);
+	}
+
+	@Override
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.NA;
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		int len = 3 * nentries;
 		int[] rgb = new int[3];
 		ChunkRaw c = createEmptyChunk(len, true);
@@ -33,7 +44,7 @@ public class PngChunkPLTE extends PngChunk {
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw chunk) {
+	public void parseFromRaw(ChunkRaw chunk) {
 		setNentries(chunk.len / 3);
 		for (int n = 0, i = 0; n < nentries; n++) {
 			setEntry(n, (int) (chunk.data[i++] & 0xff), (int) (chunk.data[i++] & 0xff), (int) (chunk.data[i++] & 0xff));
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSBIT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSBIT.java
index 6850d26..bc70c6e 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSBIT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSBIT.java
@@ -1,31 +1,31 @@
 package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
-/*
+/**
+ * sBIT chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11sBIT
+ * <p>
+ * this chunk structure depends on the image type
  */
-public class PngChunkSBIT extends PngChunk {
+public class PngChunkSBIT extends PngChunkSingle {
+	public final static String ID = ChunkHelper.sBIT;
 	// http://www.w3.org/TR/PNG/#11sBIT
-	// this chunk structure depends on the image type
 
 	// significant bits
 	private int graysb, alphasb;
 	private int redsb, greensb, bluesb;
 
 	public PngChunkSBIT(ImageInfo info) {
-		super(ChunkHelper.sBIT, info);
+		super(ID, info);
 	}
 
 	@Override
-	public boolean mustGoBeforeIDAT() {
-		return true;
-	}
-
-	@Override
-	public boolean mustGoBeforePLTE() {
-		return true;
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT;
 	}
 
 	private int getLen() {
@@ -36,24 +36,24 @@ public class PngChunkSBIT extends PngChunk {
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		if (c.len != getLen())
 			throw new PngjException("bad chunk length " + c);
 		if (imgInfo.greyscale) {
-			graysb = PngHelper.readInt1fromByte(c.data, 0);
+			graysb = PngHelperInternal.readInt1fromByte(c.data, 0);
 			if (imgInfo.alpha)
-				alphasb = PngHelper.readInt1fromByte(c.data, 1);
+				alphasb = PngHelperInternal.readInt1fromByte(c.data, 1);
 		} else {
-			redsb = PngHelper.readInt1fromByte(c.data, 0);
-			greensb = PngHelper.readInt1fromByte(c.data, 1);
-			bluesb = PngHelper.readInt1fromByte(c.data, 2);
+			redsb = PngHelperInternal.readInt1fromByte(c.data, 0);
+			greensb = PngHelperInternal.readInt1fromByte(c.data, 1);
+			bluesb = PngHelperInternal.readInt1fromByte(c.data, 2);
 			if (imgInfo.alpha)
-				alphasb = PngHelper.readInt1fromByte(c.data, 3);
+				alphasb = PngHelperInternal.readInt1fromByte(c.data, 3);
 		}
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = null;
 		c = createEmptyChunk(getLen(), true);
 		if (imgInfo.greyscale) {
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java
index 953adb7..2ff6583 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java
@@ -4,11 +4,17 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
+/**
+ * sPLT chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11sPLT
+ */
+public class PngChunkSPLT extends PngChunkMultiple {
+	public final static String ID = ChunkHelper.sPLT;
 
-public class PngChunkSPLT extends PngChunk {
 	// http://www.w3.org/TR/PNG/#11sPLT
 
 	private String palName;
@@ -16,35 +22,30 @@ public class PngChunkSPLT extends PngChunk {
 	private int[] palette; // 5 elements per entry
 
 	public PngChunkSPLT(ImageInfo info) {
-		super(ChunkHelper.sPLT, info);
+		super(ID, info);
 	}
 
 	@Override
-	public boolean allowsMultiple() {
-		return true; // allows multiple, but pallete name should be different
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.BEFORE_IDAT;
 	}
 
 	@Override
-	public boolean mustGoBeforeIDAT() {
-		return true;
-	}
-
-	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		try {
 			ByteArrayOutputStream ba = new ByteArrayOutputStream();
-			ba.write(palName.getBytes(PngHelper.charsetLatin1));
+			ba.write(palName.getBytes(PngHelperInternal.charsetLatin1));
 			ba.write(0); // separator
 			ba.write((byte) sampledepth);
 			int nentries = getNentries();
 			for (int n = 0; n < nentries; n++) {
 				for (int i = 0; i < 4; i++) {
 					if (sampledepth == 8)
-						PngHelper.writeByte(ba, (byte) palette[n * 5 + i]);
+						PngHelperInternal.writeByte(ba, (byte) palette[n * 5 + i]);
 					else
-						PngHelper.writeInt2(ba, palette[n * 5 + i]);
+						PngHelperInternal.writeInt2(ba, palette[n * 5 + i]);
 				}
-				PngHelper.writeInt2(ba, palette[n * 5 + 4]);
+				PngHelperInternal.writeInt2(ba, palette[n * 5 + 4]);
 			}
 			byte[] b = ba.toByteArray();
 			ChunkRaw chunk = createEmptyChunk(b.length, false);
@@ -56,7 +57,7 @@ public class PngChunkSPLT extends PngChunk {
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		int t = -1;
 		for (int i = 0; i < c.data.length; i++) { // look for first zero
 			if (c.data[i] == 0) {
@@ -66,8 +67,8 @@ public class PngChunkSPLT extends PngChunk {
 		}
 		if (t <= 0 || t > c.data.length - 2)
 			throw new PngjException("bad sPLT chunk: no separator found");
-		palName = new String(c.data, 0, t, PngHelper.charsetLatin1);
-		sampledepth = PngHelper.readInt1fromByte(c.data, t + 1);
+		palName = new String(c.data, 0, t, PngHelperInternal.charsetLatin1);
+		sampledepth = PngHelperInternal.readInt1fromByte(c.data, t + 1);
 		t += 2;
 		int nentries = (c.data.length - t) / (sampledepth == 8 ? 6 : 10);
 		palette = new int[nentries * 5];
@@ -75,21 +76,21 @@ public class PngChunkSPLT extends PngChunk {
 		ne = 0;
 		for (int i = 0; i < nentries; i++) {
 			if (sampledepth == 8) {
-				r = PngHelper.readInt1fromByte(c.data, t++);
-				g = PngHelper.readInt1fromByte(c.data, t++);
-				b = PngHelper.readInt1fromByte(c.data, t++);
-				a = PngHelper.readInt1fromByte(c.data, t++);
+				r = PngHelperInternal.readInt1fromByte(c.data, t++);
+				g = PngHelperInternal.readInt1fromByte(c.data, t++);
+				b = PngHelperInternal.readInt1fromByte(c.data, t++);
+				a = PngHelperInternal.readInt1fromByte(c.data, t++);
 			} else {
-				r = PngHelper.readInt2fromBytes(c.data, t);
+				r = PngHelperInternal.readInt2fromBytes(c.data, t);
 				t += 2;
-				g = PngHelper.readInt2fromBytes(c.data, t);
+				g = PngHelperInternal.readInt2fromBytes(c.data, t);
 				t += 2;
-				b = PngHelper.readInt2fromBytes(c.data, t);
+				b = PngHelperInternal.readInt2fromBytes(c.data, t);
 				t += 2;
-				a = PngHelper.readInt2fromBytes(c.data, t);
+				a = PngHelperInternal.readInt2fromBytes(c.data, t);
 				t += 2;
 			}
-			f = PngHelper.readInt2fromBytes(c.data, t);
+			f = PngHelperInternal.readInt2fromBytes(c.data, t);
 			t += 2;
 			palette[ne++] = r;
 			palette[ne++] = g;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSRGB.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSRGB.java
index 7745587..e4d77d4 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSRGB.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSRGB.java
@@ -1,12 +1,17 @@
 package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
-/*
+/**
+ * sRGB chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11sRGB
  */
-public class PngChunkSRGB extends PngChunk {
+public class PngChunkSRGB extends PngChunkSingle {
+	public final static String ID = ChunkHelper.sRGB;
+
 	// http://www.w3.org/TR/PNG/#11sRGB
 
 	public static final int RENDER_INTENT_Perceptual = 0;
@@ -17,28 +22,23 @@ public class PngChunkSRGB extends PngChunk {
 	private int intent;
 
 	public PngChunkSRGB(ImageInfo info) {
-		super(ChunkHelper.sRGB, info);
-	}
-
-	@Override
-	public boolean mustGoBeforeIDAT() {
-		return true;
+		super(ID, info);
 	}
 
 	@Override
-	public boolean mustGoBeforePLTE() {
-		return true;
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT;
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		if (c.len != 1)
 			throw new PngjException("bad chunk length " + c);
-		intent = PngHelper.readInt1fromByte(c.data, 0);
+		intent = PngHelperInternal.readInt1fromByte(c.data, 0);
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = null;
 		c = createEmptyChunk(1, true);
 		c.data[0] = (byte) intent;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSTER.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSTER.java
new file mode 100644
index 0000000..4dc5ede
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSTER.java
@@ -0,0 +1,60 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngjException;
+
+/**
+ * sTER chunk.
+ * <p>
+ * see http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.sTER
+ */
+public class PngChunkSTER extends PngChunkSingle {
+	public final static String ID = "sTER";
+
+	// http://www.libpng.org/pub/png/spec/register/pngext-1.3.0-pdg.html#C.sTER
+	private byte mode; // 0: cross-fuse layout 1: diverging-fuse layout
+
+	public PngChunkSTER(ImageInfo info) {
+		super(ID, info);
+	}
+
+	@Override
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.BEFORE_IDAT;
+	}
+
+	@Override
+	public ChunkRaw createRawChunk() {
+		ChunkRaw c = createEmptyChunk(1, true);
+		c.data[0] = (byte) mode;
+		return c;
+	}
+
+	@Override
+	public void parseFromRaw(ChunkRaw chunk) {
+		if (chunk.len != 1)
+			throw new PngjException("bad chunk length " + chunk);
+		mode = chunk.data[0];
+	}
+
+	@Override
+	public void cloneDataFromRead(PngChunk other) {
+		PngChunkSTER otherx = (PngChunkSTER) other;
+		this.mode = otherx.mode;
+	}
+
+	/**
+	 * 0: cross-fuse layout 1: diverging-fuse layout
+	 */
+	public byte getMode() {
+		return mode;
+	}
+
+	/**
+	 * 0: cross-fuse layout 1: diverging-fuse layout
+	 */
+	public void setMode(byte mode) {
+		this.mode = mode;
+	}
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java
new file mode 100644
index 0000000..286f39d
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSingle.java
@@ -0,0 +1,43 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+
+/**
+ * PNG chunk type (abstract) that does not allow multiple instances in same image.
+ */
+public abstract class PngChunkSingle extends PngChunk {
+
+	protected PngChunkSingle(String id, ImageInfo imgInfo) {
+		super(id, imgInfo);
+	}
+
+	public final boolean allowsMultiple() {
+		return false;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((id == null) ? 0 : id.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		PngChunkSingle other = (PngChunkSingle) obj;
+		if (id == null) {
+			if (other.id != null)
+				return false;
+		} else if (!id.equals(other.id))
+			return false;
+		return true;
+	}
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSkipped.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSkipped.java
new file mode 100644
index 0000000..f4c77b4
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSkipped.java
@@ -0,0 +1,41 @@
+package jogamp.opengl.util.pngj.chunks;
+
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.PngjException;
+
+/**
+ * Pseudo chunk type, for chunks that were skipped on reading
+ */
+public class PngChunkSkipped extends PngChunk {
+
+	public PngChunkSkipped(String id, ImageInfo info, int clen) {
+		super(id, info);
+		this.length = clen;
+	}
+
+	@Override
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.NONE;
+	}
+
+	@Override
+	public ChunkRaw createRawChunk() {
+		throw new PngjException("Non supported for a skipped chunk");
+	}
+
+	@Override
+	public void parseFromRaw(ChunkRaw c) {
+		throw new PngjException("Non supported for a skipped chunk");
+	}
+
+	@Override
+	public void cloneDataFromRead(PngChunk other) {
+		throw new PngjException("Non supported for a skipped chunk");
+	}
+
+	@Override
+	public boolean allowsMultiple() {
+		return true;
+	}
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java
index c535fe3..d97cd63 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java
@@ -1,28 +1,40 @@
 package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
+import jogamp.opengl.util.pngj.PngjException;
 
+/**
+ * tEXt chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11tEXt
+ */
 public class PngChunkTEXT extends PngChunkTextVar {
+	public final static String ID = ChunkHelper.tEXt;
+
 	public PngChunkTEXT(ImageInfo info) {
-		super(ChunkHelper.tEXt, info);
+		super(ID, info);
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
-		if (val.isEmpty() || key.isEmpty())
-			return null;
-		byte[] b = (key + "\0" + val).getBytes(PngHelper.charsetLatin1);
+	public ChunkRaw createRawChunk() {
+		if (key.isEmpty())
+			throw new PngjException("Text chunk key must be non empty");
+		byte[] b = (key + "\0" + val).getBytes(PngHelperInternal.charsetLatin1);
 		ChunkRaw chunk = createEmptyChunk(b.length, false);
 		chunk.data = b;
 		return chunk;
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
-		String[] k = (new String(c.data, PngHelper.charsetLatin1)).split("\0");
-		key = k[0];
-		val = k[1];
+	public void parseFromRaw(ChunkRaw c) {
+		int i;
+		for (i = 0; i < c.data.length; i++)
+			if (c.data[i] == 0)
+				break;
+		key = new String(c.data, 0, i, PngHelperInternal.charsetLatin1);
+		i++;
+		val = i < c.data.length ? new String(c.data, i, c.data.length - i, PngHelperInternal.charsetLatin1) : "";
 	}
 
 	@Override
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTIME.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTIME.java
index fa61f62..8f34c78 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTIME.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTIME.java
@@ -3,22 +3,33 @@ package jogamp.opengl.util.pngj.chunks;
 import java.util.Calendar;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
+/**
+ * tIME chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11tIME
+ */
+public class PngChunkTIME extends PngChunkSingle {
+	public final static String ID = ChunkHelper.tIME;
 
-public class PngChunkTIME extends PngChunk {
 	// http://www.w3.org/TR/PNG/#11tIME
 	private int year, mon, day, hour, min, sec;
 
 	public PngChunkTIME(ImageInfo info) {
-		super(ChunkHelper.tIME, info);
+		super(ID, info);
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.NONE;
+	}
+
+	@Override
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = createEmptyChunk(7, true);
-		PngHelper.writeInt2tobytes(year, c.data, 0);
+		PngHelperInternal.writeInt2tobytes(year, c.data, 0);
 		c.data[2] = (byte) mon;
 		c.data[3] = (byte) day;
 		c.data[4] = (byte) hour;
@@ -28,15 +39,15 @@ public class PngChunkTIME extends PngChunk {
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw chunk) {
+	public void parseFromRaw(ChunkRaw chunk) {
 		if (chunk.len != 7)
 			throw new PngjException("bad chunk " + chunk);
-		year = PngHelper.readInt2fromBytes(chunk.data, 0);
-		mon = PngHelper.readInt1fromByte(chunk.data, 2);
-		day = PngHelper.readInt1fromByte(chunk.data, 3);
-		hour = PngHelper.readInt1fromByte(chunk.data, 4);
-		min = PngHelper.readInt1fromByte(chunk.data, 5);
-		sec = PngHelper.readInt1fromByte(chunk.data, 6);
+		year = PngHelperInternal.readInt2fromBytes(chunk.data, 0);
+		mon = PngHelperInternal.readInt1fromByte(chunk.data, 2);
+		day = PngHelperInternal.readInt1fromByte(chunk.data, 3);
+		hour = PngHelperInternal.readInt1fromByte(chunk.data, 4);
+		min = PngHelperInternal.readInt1fromByte(chunk.data, 5);
+		sec = PngHelperInternal.readInt1fromByte(chunk.data, 6);
 	}
 
 	@Override
@@ -69,6 +80,7 @@ public class PngChunkTIME extends PngChunk {
 		min = minx;
 		sec = secx;
 	}
+
 	public int[] getYMDHMS() {
 		return new int[] { year, mon, day, hour, min, sec };
 	}
@@ -78,6 +90,4 @@ public class PngChunkTIME extends PngChunk {
 		return String.format("%04d/%02d/%02d %02d:%02d:%02d", year, mon, day, hour, min, sec);
 	}
 
-	
-
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java
index 9365e5e..1de5c08 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTRNS.java
@@ -1,39 +1,41 @@
 package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
-/*
+/**
+ * tRNS chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11tRNS
+ * <p>
+ * this chunk structure depends on the image type
  */
-public class PngChunkTRNS extends PngChunk {
+public class PngChunkTRNS extends PngChunkSingle {
+	public final static String ID = ChunkHelper.tRNS;
+
 	// http://www.w3.org/TR/PNG/#11tRNS
-	// this chunk structure depends on the image type
-	// only one of these is meaningful
+
+	// only one of these is meaningful, depending on the image type
 	private int gray;
 	private int red, green, blue;
 	private int[] paletteAlpha = new int[] {};
 
 	public PngChunkTRNS(ImageInfo info) {
-		super(ChunkHelper.tRNS, info);
-	}
-
-	@Override
-	public boolean mustGoBeforeIDAT() {
-		return true;
+		super(ID, info);
 	}
 
 	@Override
-	public boolean mustGoAfterPLTE() {
-		return true;
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkRaw createRawChunk() {
 		ChunkRaw c = null;
 		if (imgInfo.greyscale) {
 			c = createEmptyChunk(2, true);
-			PngHelper.writeInt2tobytes(gray, c.data, 0);
+			PngHelperInternal.writeInt2tobytes(gray, c.data, 0);
 		} else if (imgInfo.indexed) {
 			c = createEmptyChunk(paletteAlpha.length, true);
 			for (int n = 0; n < c.len; n++) {
@@ -41,17 +43,17 @@ public class PngChunkTRNS extends PngChunk {
 			}
 		} else {
 			c = createEmptyChunk(6, true);
-			PngHelper.writeInt2tobytes(red, c.data, 0);
-			PngHelper.writeInt2tobytes(green, c.data, 0);
-			PngHelper.writeInt2tobytes(blue, c.data, 0);
+			PngHelperInternal.writeInt2tobytes(red, c.data, 0);
+			PngHelperInternal.writeInt2tobytes(green, c.data, 0);
+			PngHelperInternal.writeInt2tobytes(blue, c.data, 0);
 		}
 		return c;
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		if (imgInfo.greyscale) {
-			gray = PngHelper.readInt2fromBytes(c.data, 0);
+			gray = PngHelperInternal.readInt2fromBytes(c.data, 0);
 		} else if (imgInfo.indexed) {
 			int nentries = c.data.length;
 			paletteAlpha = new int[nentries];
@@ -59,9 +61,9 @@ public class PngChunkTRNS extends PngChunk {
 				paletteAlpha[n] = (int) (c.data[n] & 0xff);
 			}
 		} else {
-			red = PngHelper.readInt2fromBytes(c.data, 0);
-			green = PngHelper.readInt2fromBytes(c.data, 2);
-			blue = PngHelper.readInt2fromBytes(c.data, 4);
+			red = PngHelperInternal.readInt2fromBytes(c.data, 0);
+			green = PngHelperInternal.readInt2fromBytes(c.data, 2);
+			blue = PngHelperInternal.readInt2fromBytes(c.data, 4);
 		}
 	}
 
@@ -118,6 +120,18 @@ public class PngChunkTRNS extends PngChunk {
 	}
 
 	/**
+	 * to use when only one pallete index is set as totally transparent
+	 */
+	public void setIndexEntryAsTransparent(int palAlphaIndex) {
+		if (!imgInfo.indexed)
+			throw new PngjException("only indexed images support this");
+		paletteAlpha = new int[] { palAlphaIndex + 1 };
+		for (int i = 0; i < palAlphaIndex; i++)
+			paletteAlpha[i] = 255;
+		paletteAlpha[palAlphaIndex] = 0;
+	}
+
+	/**
 	 * WARNING: non deep copy
 	 */
 	public int[] getPalletteAlpha() {
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTextVar.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTextVar.java
index 3d92a80..ba3ffc3 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTextVar.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTextVar.java
@@ -3,11 +3,9 @@ package jogamp.opengl.util.pngj.chunks;
 import jogamp.opengl.util.pngj.ImageInfo;
 
 /**
- * superclass for three textual chunks (TEXT, ITXT, ZTXT)
- * 
- * @author Hernan J Gonzalez
+ * Superclass (abstract) for three textual chunks (TEXT, ITXT, ZTXT)
  */
-public abstract class PngChunkTextVar extends PngChunk {
+public abstract class PngChunkTextVar extends PngChunkMultiple {
 	protected String key; // key/val: only for tEXt. lazy computed
 	protected String val;
 
@@ -28,8 +26,8 @@ public abstract class PngChunkTextVar extends PngChunk {
 	}
 
 	@Override
-	public boolean allowsMultiple() {
-		return true;
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.NONE;
 	}
 
 	public static class PngTxtInfo {
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java
index 15a3593..3803428 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java
@@ -2,7 +2,12 @@ package jogamp.opengl.util.pngj.chunks;
 
 import jogamp.opengl.util.pngj.ImageInfo;
 
-public class PngChunkUNKNOWN extends PngChunk { // unkown, custom or not
+/**
+ * Placeholder for UNKNOWN (custom or not) chunks.
+ * <p>
+ * For PngReader, a chunk is unknown if it's not registered in the chunk factory
+ */
+public class PngChunkUNKNOWN extends PngChunkMultiple { // unkown, custom or not
 
 	private byte[] data;
 
@@ -10,25 +15,25 @@ public class PngChunkUNKNOWN extends PngChunk { // unkown, custom or not
 		super(id, info);
 	}
 
-	@Override
-	public boolean allowsMultiple() {
-		return true;
-	}
-
 	private PngChunkUNKNOWN(PngChunkUNKNOWN c, ImageInfo info) {
 		super(c.id, info);
 		System.arraycopy(c.data, 0, data, 0, c.data.length);
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
+	public ChunkOrderingConstraint getOrderingConstraint() {
+		return ChunkOrderingConstraint.NONE;
+	}
+
+	@Override
+	public ChunkRaw createRawChunk() {
 		ChunkRaw p = createEmptyChunk(data.length, false);
 		p.data = this.data;
 		return p;
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		data = c.data;
 	}
 
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java
index fd6c082..64593ea 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java
@@ -4,26 +4,32 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
 import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.PngHelper;
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
-
+/**
+ * zTXt chunk.
+ * <p>
+ * see http://www.w3.org/TR/PNG/#11zTXt
+ */
 public class PngChunkZTXT extends PngChunkTextVar {
+	public final static String ID = ChunkHelper.zTXt;
+
 	// http://www.w3.org/TR/PNG/#11zTXt
 	public PngChunkZTXT(ImageInfo info) {
-		super(ChunkHelper.zTXt, info);
+		super(ID, info);
 	}
 
 	@Override
-	public ChunkRaw createChunk() {
-		if (val.isEmpty() || key.isEmpty())
-			return null;
+	public ChunkRaw createRawChunk() {
+		if (key.isEmpty())
+			throw new PngjException("Text chunk key must be non empty");
 		try {
 			ByteArrayOutputStream ba = new ByteArrayOutputStream();
-			ba.write(key.getBytes(PngHelper.charsetLatin1));
+			ba.write(key.getBytes(PngHelperInternal.charsetLatin1));
 			ba.write(0); // separator
 			ba.write(0); // compression method: 0
-			byte[] textbytes = ChunkHelper.compressBytes(val.getBytes(PngHelper.charsetLatin1), true);
+			byte[] textbytes = ChunkHelper.compressBytes(val.getBytes(PngHelperInternal.charsetLatin1), true);
 			ba.write(textbytes);
 			byte[] b = ba.toByteArray();
 			ChunkRaw chunk = createEmptyChunk(b.length, false);
@@ -35,7 +41,7 @@ public class PngChunkZTXT extends PngChunkTextVar {
 	}
 
 	@Override
-	public void parseFromChunk(ChunkRaw c) {
+	public void parseFromRaw(ChunkRaw c) {
 		int nullsep = -1;
 		for (int i = 0; i < c.data.length; i++) { // look for first zero
 			if (c.data[i] != 0)
@@ -45,12 +51,12 @@ public class PngChunkZTXT extends PngChunkTextVar {
 		}
 		if (nullsep < 0 || nullsep > c.data.length - 2)
 			throw new PngjException("bad zTXt chunk: no separator found");
-		key = new String(c.data, 0, nullsep, PngHelper.charsetLatin1);
+		key = new String(c.data, 0, nullsep, PngHelperInternal.charsetLatin1);
 		int compmet = (int) c.data[nullsep + 1];
 		if (compmet != 0)
 			throw new PngjException("bad zTXt chunk: unknown compression method");
 		byte[] uncomp = ChunkHelper.compressBytes(c.data, nullsep + 2, c.data.length - nullsep - 2, false); // uncompress
-		val = new String(uncomp, PngHelper.charsetLatin1);
+		val = new String(uncomp, PngHelperInternal.charsetLatin1);
 	}
 
 	@Override
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
index a827545..52d1b22 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
@@ -1,68 +1,70 @@
 package jogamp.opengl.util.pngj.chunks;
 
-import jogamp.opengl.util.pngj.PngHelper;
+import java.util.ArrayList;
+import java.util.List;
+
+import jogamp.opengl.util.pngj.PngHelperInternal;
 import jogamp.opengl.util.pngj.PngjException;
 
 /**
  * We consider "image metadata" every info inside the image except for the most basic image info (IHDR chunk - ImageInfo
  * class) and the pixels values.
- * 
+ * <p>
  * This includes the palette (if present) and all the ancillary chunks
- * 
+ * <p>
  * This class provides a wrapper over the collection of chunks of a image (read or to write) and provides some high
  * level methods to access them
- * 
  */
 public class PngMetadata {
-	private final ChunkList chunkList;
+	private final ChunksList chunkList;
 	private final boolean readonly;
 
-	public PngMetadata(ChunkList chunks, boolean readonly) {
+	public PngMetadata(ChunksList chunks) {
 		this.chunkList = chunks;
-		this.readonly = readonly;
+		if (chunks instanceof ChunksListForWrite) {
+			this.readonly = false;
+		} else {
+			this.readonly = true;
+		}
 	}
 
 	/**
 	 * Queues the chunk at the writer
+	 * <p>
+	 * lazyOverwrite: if true, checks if there is a queued "equivalent" chunk and if so, overwrites it. However if that
+	 * not check for already written chunks.
 	 */
-	public boolean setChunk(PngChunk c, boolean overwriteIfPresent) {
+	public void queueChunk(final PngChunk c, boolean lazyOverwrite) {
+		ChunksListForWrite cl = getChunkListW();
 		if (readonly)
 			throw new PngjException("cannot set chunk : readonly metadata");
-		return chunkList.setChunk(c, overwriteIfPresent);
+		if (lazyOverwrite) {
+			ChunkHelper.trimList(cl.getQueuedChunks(), new ChunkPredicate() {
+				public boolean match(PngChunk c2) {
+					return ChunkHelper.equivalent(c, c2);
+				}
+			});
+		}
+		cl.queue(c);
 	}
 
-	
-	/**
-	 * Returns only one chunk or null if nothing found - does not include queued chunks
-	 *
-	 * If more than one chunk (after filtering by inner id) is found, then an exception is thrown (failifMultiple=true)
-	 * or the last one is returned (failifMultiple=false)
-	 * 
-	 * @param id Chunk id
-	 * @param innerid if not null, the chunk is assumed to be PngChunkTextVar or PngChunkSPLT, and filtered by that 'internal id'
-	 * @param failIfMultiple throw exception if more that one
-	 * @return chunk (not cloned)
-	 */
-	public PngChunk getChunk1(String id, String innerid, boolean failIfMultiple) {
-		return chunkList.getChunk1(id, innerid, failIfMultiple);
+	public void queueChunk(final PngChunk c) {
+		queueChunk(c, true);
 	}
 
-	/**
-	 *  Same as  getChunk1(id,  innerid=null, failIfMultiple=true);
-	 */
-	public PngChunk getChunk1(String id) {
-		return chunkList.getChunk1(id);
+	private ChunksListForWrite getChunkListW() {
+		return (ChunksListForWrite) chunkList;
 	}
 
 	// ///// high level utility methods follow ////////////
 
 	// //////////// DPI
 
-	/** 
-	 * returns -1 if not found or dimension unknown 
-	 **/
+	/**
+	 * returns -1 if not found or dimension unknown
+	 */
 	public double[] getDpi() {
-		PngChunk c = getChunk1(ChunkHelper.pHYs, null, true);
+		PngChunk c = chunkList.getById1(ChunkHelper.pHYs, true);
 		if (c == null)
 			return new double[] { -1, -1 };
 		else
@@ -76,31 +78,68 @@ public class PngMetadata {
 	public void setDpi(double x, double y) {
 		PngChunkPHYS c = new PngChunkPHYS(chunkList.imageInfo);
 		c.setAsDpi2(x, y);
-		setChunk(c, true);
+		queueChunk(c);
 	}
 
 	// //////////// TIME
 
-	public void setTimeNow(int secsAgo) {
+	/**
+	 * Creates a time chunk with current time, less secsAgo seconds
+	 * <p>
+	 * 
+	 * @return Returns the created-queued chunk, just in case you want to examine or modify it
+	 */
+	public PngChunkTIME setTimeNow(int secsAgo) {
 		PngChunkTIME c = new PngChunkTIME(chunkList.imageInfo);
 		c.setNow(secsAgo);
-		setChunk(c, true);
+		queueChunk(c);
+		return c;
+	}
+
+	public PngChunkTIME setTimeNow() {
+		return setTimeNow(0);
 	}
 
-	public void setTimeYMDHMS(int yearx, int monx, int dayx, int hourx, int minx, int secx) {
+	/**
+	 * Creates a time chunk with diven date-time
+	 * <p>
+	 * 
+	 * @return Returns the created-queued chunk, just in case you want to examine or modify it
+	 */
+	public PngChunkTIME setTimeYMDHMS(int yearx, int monx, int dayx, int hourx, int minx, int secx) {
 		PngChunkTIME c = new PngChunkTIME(chunkList.imageInfo);
 		c.setYMDHMS(yearx, monx, dayx, hourx, minx, secx);
-		setChunk(c, true);
+		queueChunk(c, true);
+		return c;
+	}
+
+	/**
+	 * null if not found
+	 */
+	public PngChunkTIME getTime() {
+		return (PngChunkTIME) chunkList.getById1(ChunkHelper.tIME);
 	}
 
 	public String getTimeAsString() {
-		PngChunk c = getChunk1(ChunkHelper.tIME, null, true);
-		return c != null ? ((PngChunkTIME) c).getAsString() : "";
+		PngChunkTIME c = getTime();
+		return c == null ? "" : c.getAsString();
 	}
 
 	// //////////// TEXT
 
-	public void setText(String k, String val, boolean useLatin1, boolean compress) {
+	/**
+	 * Creates a text chunk and queue it.
+	 * <p>
+	 * 
+	 * @param k
+	 *            : key (latin1)
+	 * @param val
+	 *            (arbitrary, should be latin1 if useLatin1)
+	 * @param useLatin1
+	 * @param compress
+	 * @return Returns the created-queued chunks, just in case you want to examine, touch it
+	 */
+	public PngChunkTextVar setText(String k, String val, boolean useLatin1, boolean compress) {
 		if (compress && !useLatin1)
 			throw new PngjException("cannot compress non latin text");
 		PngChunkTextVar c;
@@ -115,21 +154,80 @@ public class PngMetadata {
 			((PngChunkITXT) c).setLangtag(k); // we use the same orig tag (this is not quite right)
 		}
 		c.setKeyVal(k, val);
-		setChunk(c, true);
+		queueChunk(c, true);
+		return c;
 	}
 
-	public void setText(String k, String val) {
-		setText(k, val, false, val.length() > 400);
+	public PngChunkTextVar setText(String k, String val) {
+		return setText(k, val, false, false);
 	}
 
-	/** tries all text chunks - returns null if not found */
+	/**
+	 * gets all text chunks with a given key
+	 * <p>
+	 * returns null if not found
+	 * <p>
+	 * Warning: this does not check the "lang" key of iTxt
+	 */
+	@SuppressWarnings("unchecked")
+	public List<? extends PngChunkTextVar> getTxtsForKey(String k) {
+		@SuppressWarnings("rawtypes")
+		List c = new ArrayList();
+		c.addAll(chunkList.getById(ChunkHelper.tEXt, k));
+		c.addAll(chunkList.getById(ChunkHelper.zTXt, k));
+		c.addAll(chunkList.getById(ChunkHelper.iTXt, k));
+		return c;
+	}
+
+	/**
+	 * Returns empty if not found, concatenated (with newlines) if multiple! - and trimmed
+	 * <p>
+	 * Use getTxtsForKey() if you don't want this behaviour
+	 */
 	public String getTxtForKey(String k) {
-		PngChunk c = getChunk1(ChunkHelper.tEXt, k, true);
-		if (c == null)
-			c = getChunk1(ChunkHelper.zTXt, k, true);
-		if (c == null)
-			c = getChunk1(ChunkHelper.iTXt, k, true);
-		return c != null ? ((PngChunkTextVar) c).getVal() : null;
+		List<? extends PngChunkTextVar> li = getTxtsForKey(k);
+		if (li.isEmpty())
+			return "";
+		StringBuilder t = new StringBuilder();
+		for (PngChunkTextVar c : li)
+			t.append(c.getVal()).append("\n");
+		return t.toString().trim();
+	}
+
+	/**
+	 * Returns the palette chunk, if present
+	 * 
+	 * @return null if not present
+	 */
+	public PngChunkPLTE getPLTE() {
+		return (PngChunkPLTE) chunkList.getById1(PngChunkPLTE.ID);
+	}
+
+	/**
+	 * Creates a new empty palette chunk, queues it for write and return it to the caller, who should fill its entries
+	 */
+	public PngChunkPLTE createPLTEChunk() {
+		PngChunkPLTE plte = new PngChunkPLTE(chunkList.imageInfo);
+		queueChunk(plte);
+		return plte;
+	}
+
+	/**
+	 * Returns the TRNS chunk, if present
+	 * 
+	 * @return null if not present
+	 */
+	public PngChunkTRNS getTRNS() {
+		return (PngChunkTRNS) chunkList.getById1(PngChunkTRNS.ID);
+	}
+
+	/**
+	 * Creates a new empty TRNS chunk, queues it for write and return it to the caller, who should fill its entries
+	 */
+	public PngChunkTRNS createTRNSChunk() {
+		PngChunkTRNS trns = new PngChunkTRNS(chunkList.imageInfo);
+		queueChunk(trns);
+		return trns;
 	}
 
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/package.html b/src/jogl/classes/jogamp/opengl/util/pngj/package.html
index 209b39c..0b0e2c8 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/package.html
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/package.html
@@ -1,11 +1,10 @@
 <html>
 <body bgcolor="white">
 <p>
-Contains the main classes for the PNGJ library.<p>
-Client code should rarely need more than the public members of this package.
+PNGJ main package
 </p>
 <p>
-See also the <code>nosandbox</code> package if available.
+Client code should rarely need more than the public members of this package.
 </p>
 </body>
 </html>
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
index 99064b1..4444e9d 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
@@ -65,10 +65,11 @@ public class WGLGLCapabilities extends GLCapabilities {
       setAccumAlphaBits(pfd.getCAccumAlphaBits());
       setDepthBits(pfd.getCDepthBits());
       setStencilBits(pfd.getCStencilBits());
-      setDoubleBuffered((pfd.getDwFlags() & GDI.PFD_DOUBLEBUFFER) != 0);
-      setStereo((pfd.getDwFlags() & GDI.PFD_STEREO) != 0);
-      setHardwareAccelerated((pfd.getDwFlags() & GDI.PFD_GENERIC_FORMAT) == 0
-                          || (pfd.getDwFlags() & GDI.PFD_GENERIC_ACCELERATED) != 0);
+      final int dwFlags = pfd.getDwFlags();
+      setDoubleBuffered((dwFlags & GDI.PFD_DOUBLEBUFFER) != 0);
+      setStereo((dwFlags & GDI.PFD_STEREO) != 0);
+      setHardwareAccelerated((dwFlags & GDI.PFD_GENERIC_FORMAT) == 0
+                          || (dwFlags & GDI.PFD_GENERIC_ACCELERATED) != 0);
       // n/a with non ARB/GDI method:
       //       multisample
       //       opaque
@@ -76,6 +77,42 @@ public class WGLGLCapabilities extends GLCapabilities {
 
       return true;
   }
+    
+  public static final String PFD2String(PIXELFORMATDESCRIPTOR pfd, int pfdID) {
+      final int dwFlags = pfd.getDwFlags();
+      StringBuffer sb = new StringBuffer();
+      boolean sep = false;
+      
+      if( 0 != (GDI.PFD_DRAW_TO_WINDOW & dwFlags ) ) {
+          sep = true;
+          sb.append("window");
+      }
+      if( 0 != (GDI.PFD_DRAW_TO_BITMAP & dwFlags ) ) {
+          if(sep) { sb.append(CSEP); } sep=true;
+          sb.append("bitmap");
+      }
+      if( 0 != (GDI.PFD_SUPPORT_OPENGL & dwFlags ) ) {
+          if(sep) { sb.append(CSEP); } sep=true;
+          sb.append("opengl");
+      }
+      if( 0 != (GDI.PFD_DOUBLEBUFFER & dwFlags ) ) {
+          if(sep) { sb.append(CSEP); } sep=true;
+          sb.append("dblbuf");
+      }
+      if( 0 != (GDI.PFD_STEREO & dwFlags ) ) {
+          if(sep) { sb.append(CSEP); } sep=true;
+          sb.append("stereo");
+      }
+      if( 0 == (GDI.PFD_GENERIC_FORMAT & dwFlags ) || 0 == (GDI.PFD_GENERIC_ACCELERATED & dwFlags ) ) {
+          if(sep) { sb.append(CSEP); } sep=true;
+          sb.append("hw-accel");
+      }        
+      return "PFD[id = "+pfdID+" (0x"+Integer.toHexString(pfdID)+
+              "), colorBits "+pfd.getCColorBits()+", rgba "+pfd.getCRedBits()+ESEP+pfd.getCGreenBits()+ESEP+pfd.getCBlueBits()+ESEP+pfd.getCAlphaBits()+
+              ", accum-rgba "+pfd.getCAccumRedBits()+ESEP+pfd.getCAccumGreenBits()+ESEP+pfd.getCAccumBlueBits()+ESEP+pfd.getCAccumAlphaBits()+
+              ", dp/st/ms: "+pfd.getCDepthBits()+ESEP+pfd.getCStencilBits()+ESEP+"0"+
+              ", flags: "+sb.toString();
+  }
 
   public boolean setValuesByARB(final IntBuffer iattribs, final int niattribs, final IntBuffer iresults) {
       arb_pixelformat = 1;
@@ -122,19 +159,13 @@ public class WGLGLCapabilities extends GLCapabilities {
                   }
 
                   if (res == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) {
-                      setPbufferFloatingPointBuffers(true);
+                      return false; // not supported
                   }
 
                   // normal RGBA FB: WGLExt.WGL_TYPE_RGBA_ARB
                   // ignore unknown results here
                   break;
 
-              case WGLExt.WGL_FLOAT_COMPONENTS_NV:
-                  if (res != 0) {
-                      setPbufferFloatingPointBuffers(true);
-                  }
-                  break;
-
               case WGLExt.WGL_RED_BITS_ARB:
                   setRedBits(res);
                   break;
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
deleted file mode 100644
index 51341a0..0000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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 jogamp.opengl.windows.wgl;
-
-import javax.media.opengl.*;
-
-public class WindowsBitmapWGLContext extends WindowsWGLContext {
-  public WindowsBitmapWGLContext(WindowsBitmapWGLDrawable drawable,
-                                   GLContext shareWith) {
-    super(drawable, shareWith);
-  }
-
-  @Override
-  public int getOffscreenContextPixelDataType() {
-      return GL.GL_UNSIGNED_BYTE;
-  }
-
-  @Override
-  public int getOffscreenContextReadBuffer() {
-    // On Windows these contexts are always single-buffered
-    return GL.GL_FRONT;
-  }
-
-  @Override
-  public boolean offscreenImageNeedsVerticalFlip() {
-    // We can take care of this in the DIB creation (see below)
-    return false;
-  }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
index cf6f43b..909a017 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
@@ -40,16 +40,19 @@
 
 package jogamp.opengl.windows.wgl;
 
+import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.NativeSurface;
 import javax.media.nativewindow.MutableSurface;
 import javax.media.opengl.GLCapabilitiesImmutable;
 import javax.media.opengl.GLContext;
 import javax.media.opengl.GLDrawableFactory;
 import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
 
 import jogamp.nativewindow.windows.BITMAPINFO;
 import jogamp.nativewindow.windows.BITMAPINFOHEADER;
 import jogamp.nativewindow.windows.GDI;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
 
 import com.jogamp.common.nio.PointerBuffer;
 
@@ -57,8 +60,28 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
   private long origbitmap;
   private long hbitmap;
 
-  protected WindowsBitmapWGLDrawable(GLDrawableFactory factory, NativeSurface target) {
-    super(factory, target, false);
+  private WindowsBitmapWGLDrawable(GLDrawableFactory factory, NativeSurface comp) {
+    super(factory, comp, false);
+  }
+  
+  protected static WindowsBitmapWGLDrawable create(GLDrawableFactory factory, NativeSurface comp) {
+    final WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)comp.getGraphicsConfiguration();
+    final AbstractGraphicsDevice aDevice = config.getScreen().getDevice();
+    if( !GLProfile.isAvailable(aDevice, GLProfile.GL2) ) {
+        throw new GLException("GLProfile GL2 n/a on "+aDevice+" but required for Windows BITMAP");
+    }
+    final GLProfile glp = GLProfile.get(GLProfile.GL2);
+    final GLCapabilitiesImmutable capsChosen0 = (GLCapabilitiesImmutable)config.getChosenCapabilities();
+    // RGB555 and also alpha channel is experienced to fail on some Windows machines
+    final GLCapabilitiesImmutable capsChosen1 = GLGraphicsConfigurationUtil.clipRGBAGLCapabilities(capsChosen0, false /* allowRGB555 */, false /* allowAlpha */);
+    final GLCapabilitiesImmutable capsChosen2 = GLGraphicsConfigurationUtil.fixGLProfile(capsChosen1, glp);
+    if( capsChosen0 != capsChosen2 ) {
+        config.setChosenCapabilities(capsChosen2);
+        if(DEBUG) {
+            System.err.println("WindowsBitmapWGLDrawable: "+capsChosen0+" -> "+capsChosen2);
+        }
+    }
+    return new WindowsBitmapWGLDrawable(factory, comp);
   }
 
   @Override
@@ -72,34 +95,42 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
 
   @Override
   public GLContext createContext(GLContext shareWith) {
-    return new WindowsBitmapWGLContext(this, shareWith);
+    return new WindowsWGLContext(this, shareWith);
   }
 
+  @Override
+  public boolean isGLOriented() {
+      return false;
+  }
+  
   private void createBitmap() {
     int werr;
-    NativeSurface ns = getNativeSurface();
+    final NativeSurface ns = getNativeSurface();
     if(DEBUG) {
-        System.err.println("WindowsBitmapWGLDrawable (1): "+ns);
+        System.err.println(getThreadName()+": WindowsBitmapWGLDrawable (1): "+ns);
     }
-    WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
-    GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getRequestedCapabilities();
-    int width = getWidth();
-    int height = getHeight();
+    final WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
+    final GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable)config.getChosenCapabilities();
+    final int width = getWidth();
+    final int height = getHeight();
 
     //
     // 1. Create DIB Section
     //
-    BITMAPINFO info = BITMAPINFO.create();
-    BITMAPINFOHEADER header = info.getBmiHeader();
-    int bitsPerPixel = (capabilities.getRedBits() +
-                        capabilities.getGreenBits() +
-                        capabilities.getBlueBits() +
-                        capabilities.getAlphaBits());
+    final BITMAPINFO info = BITMAPINFO.create();
+    final BITMAPINFOHEADER header = info.getBmiHeader();
+    final int bitsPerPixelIn = capsChosen.getRedBits() +
+                               capsChosen.getGreenBits() +
+                               capsChosen.getBlueBits();
+    final int bitsPerPixel;
+    // Note: For BITMAP 32 bpp, the high-byte is _not_ used and hence maximum color is RGB888!
+    // Note: For BITAMP a biBitCount value other than 24 (RGB888) usually does not work!
+    bitsPerPixel = 24; // RGB888 only!
     header.setBiSize(BITMAPINFOHEADER.size());
     header.setBiWidth(width);
-    // NOTE: negating the height causes the DIB to be in top-down row
-    // order rather than bottom-up; ends up being correct during pixel
-    // readback
+    // NOTE: Positive height causes the DIB's origin at bottom-left (OpenGL),
+    // a negative height causes the DIB's origin at top-left (Java AWT, Windows, ..).
+    // We use !OpenGL origin to remove the need for vertical flip, see 'isGLOriented()' above.
     header.setBiHeight(-1 * height);
     header.setBiPlanes((short) 1);
     header.setBiBitCount((short) bitsPerPixel);
@@ -108,21 +139,21 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
     header.setBiClrUsed(0);
     header.setBiClrImportant(0);
     header.setBiCompression(GDI.BI_RGB);
-    int byteNum = width * height * ( bitsPerPixel >> 3 ) ;
+    final int byteNum = width * height * ( bitsPerPixel >> 3 ) ;
     header.setBiSizeImage(byteNum);
 
-    PointerBuffer pb = PointerBuffer.allocateDirect(1);
+    final PointerBuffer pb = PointerBuffer.allocateDirect(1);
     hbitmap = GDI.CreateDIBSection(0, info, GDI.DIB_RGB_COLORS, pb, 0, 0);
     werr = GDI.GetLastError();
     if(DEBUG) {
         long p = ( pb.capacity() > 0 ) ? pb.get(0) : 0;
         System.err.println("WindowsBitmapWGLDrawable: pb sz/ptr "+pb.capacity() + ", "+toHexString(p));
         System.err.println("WindowsBitmapWGLDrawable: " + width+"x"+height +
-                            ", bpp " + bitsPerPixel +
+                            ", bpp " + bitsPerPixelIn + " -> " + bitsPerPixel +
                             ", bytes " + byteNum +
                             ", header sz " + BITMAPINFOHEADER.size() +
                             ", DIB ptr num " + pb.capacity()+
-                            ", "+capabilities+
+                            ", "+capsChosen+
                             ", werr "+werr);
     }
     if (hbitmap == 0) {
@@ -141,7 +172,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
     }
     ((MutableSurface)ns).setSurfaceHandle(hdc);
     if(DEBUG) {
-        System.err.println("WindowsBitmapWGLDrawable (2): "+ns);
+        System.err.println(getThreadName()+": WindowsBitmapWGLDrawable (2): "+ns);
     }
 
     if ((origbitmap = GDI.SelectObject(hdc, hbitmap)) == 0) {
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
index f6cc295..a589377 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
@@ -56,8 +56,7 @@ import jogamp.nativewindow.windows.GDI;
 import jogamp.opengl.GLContextShareSet;
 
 public class WindowsExternalWGLContext extends WindowsWGLContext {
-  private GLContext lastContext;
-
+    
   private WindowsExternalWGLContext(Drawable drawable, long ctx, WindowsWGLGraphicsConfiguration cfg) {
     super(drawable, null);
     this.contextHandle = ctx;
@@ -65,7 +64,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
       System.err.println(getThreadName() + ": Created external OpenGL context " + toHexString(ctx) + " for " + this);
     }
     GLContextShareSet.contextCreated(this);
-    setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT);  // use GL_VERSION
+    setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false);  // use GL_VERSION
     getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
   }
 
@@ -106,25 +105,6 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
   }
 
   @Override
-  public int makeCurrent() throws GLException {
-    // Save last context if necessary to allow external GLContexts to
-    // talk to other GLContexts created by this library
-    GLContext cur = getCurrent();
-    if (cur != null && cur != this) {
-      lastContext = cur;
-      setCurrent(null);
-    }
-    return super.makeCurrent();
-  }
-
-  @Override
-  public void release() throws GLException {
-    super.release();
-    setCurrent(lastContext);
-    lastContext = null;
-  }
-
-  @Override
   protected void makeCurrentImpl() throws GLException {
   }
 
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java
deleted file mode 100644
index aef55ef..0000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2003 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.
- *
- * 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 jogamp.opengl.windows.wgl;
-
-import javax.media.opengl.*;
-
-public class WindowsOnscreenWGLContext extends WindowsWGLContext {
-  public WindowsOnscreenWGLContext(WindowsOnscreenWGLDrawable drawable,
-                                  GLContext shareWith) {
-    super(drawable, shareWith);
-  }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java
index ddbb29d..61fb787 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java
@@ -51,7 +51,7 @@ public class WindowsOnscreenWGLDrawable extends WindowsWGLDrawable {
 
   @Override
   public GLContext createContext(GLContext shareWith) {
-    return new WindowsOnscreenWGLContext(this, shareWith);
+    return new WindowsWGLContext(this, shareWith);
   }
 
 }
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
deleted file mode 100644
index 7dda6a1..0000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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 jogamp.opengl.windows.wgl;
-
-import javax.media.opengl.*;
-
-import com.jogamp.opengl.GLExtensions;
-
-import jogamp.opengl.GLContextImpl;
-
-public class WindowsPbufferWGLContext extends WindowsWGLContext {
-  // State for render-to-texture and render-to-texture-rectangle support
-  private boolean rtt;       // render-to-texture?
-  private boolean hasRTT;    // render-to-texture extension available?
-  private boolean rect;      // render-to-texture-rectangle?
-  private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV
-  private int texture;       // actual texture object
-
-  protected WindowsPbufferWGLContext(WindowsPbufferWGLDrawable drawable,
-                                 GLContext shareWith) {
-    super(drawable, shareWith);
-  }
-
-  @Override
-  public void bindPbufferToTexture() {
-    if (!rtt) {
-      throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " +
-                            "specified in its GLCapabilities");
-    }
-    GL gl = getGL();
-    WGLExt wglExt = getWGLExt();
-    gl.glBindTexture(textureTarget, texture);
-    if (rtt && hasRTT) {
-      if (!wglExt.wglBindTexImageARB(((WindowsPbufferWGLDrawable)drawable).getPbufferHandle(), WGLExt.WGL_FRONT_LEFT_ARB)) {
-        throw new GLException("Binding of pbuffer to texture failed: " + wglGetLastError());
-      }
-    }
-    // FIXME: comment is wrong now
-    // Note that if the render-to-texture extension is not supported,
-    // we perform a glCopyTexImage2D in swapBuffers().
-  }
-
-  @Override
-  public void releasePbufferFromTexture() {
-    if (!rtt) {
-      throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " +
-                            "specified in its GLCapabilities");
-    }
-    if (rtt && hasRTT) {
-      WGLExt wglExt = getWGLExt();
-      if (!wglExt.wglReleaseTexImageARB(((WindowsPbufferWGLDrawable)drawable).getPbufferHandle(), WGLExt.WGL_FRONT_LEFT_ARB)) {
-        throw new GLException("Releasing of pbuffer from texture failed: " + wglGetLastError());
-      }
-    }
-  }
-
-  @Override
-  protected boolean createImpl(GLContextImpl shareWith) {
-    boolean res = super.createImpl(shareWith);
-    if(res) {
-      GLCapabilitiesImmutable capabilities = drawable.getChosenGLCapabilities();
-
-      // Initialize render-to-texture support if requested
-      GL gl = getGL();
-      rtt  = capabilities.getPbufferRenderToTexture();
-      rect = gl.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle();
-
-      if (rtt) {
-        if (DEBUG) {
-          System.err.println("Initializing render-to-texture support");
-        }
-
-        if (!gl.isExtensionAvailable("WGL_ARB_render_texture")) {
-          System.err.println("WindowsPbufferWGLContext: WARNING: WGL_ARB_render_texture extension not " +
-                             "supported; implementing render_to_texture support using slow texture readback");
-        } else {
-          hasRTT = true;
-
-          if (rect && !gl.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) {
-            System.err.println("WindowsPbufferWGLContext: WARNING: GL_NV_texture_rectangle extension not " +
-                               "supported; skipping requested render_to_texture_rectangle support for pbuffer");
-            rect = false;
-          }
-          if (rect) {
-            if (DEBUG) {
-              System.err.println("  Using render-to-texture-rectangle");
-            }
-            textureTarget = GL2GL3.GL_TEXTURE_RECTANGLE_ARB;
-          } else {
-            if (DEBUG) {
-              System.err.println("  Using vanilla render-to-texture");
-            }
-            textureTarget = GL.GL_TEXTURE_2D;
-          }
-          int[] tmp = new int[1];
-          gl.glGenTextures(1, tmp, 0);
-          texture = tmp[0];
-          gl.glBindTexture(textureTarget, texture);
-          gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
-          gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
-          gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
-          gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
-          gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0);
-        }
-      }
-    }
-    return res;
-  }
-
-  @Override
-  public int getFloatingPointMode() {
-    return ((WindowsPbufferWGLDrawable)drawable).getFloatingPointMode();
-  }
-
-  private static String wglGetLastError() {
-    return WindowsWGLDrawableFactory.wglGetLastError();
-  }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
index 7a512c8..217ca18 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
@@ -47,7 +47,6 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.NativeSurface;
 import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.MutableSurface;
-import javax.media.opengl.GL;
 import javax.media.opengl.GLCapabilitiesImmutable;
 import javax.media.opengl.GLContext;
 import javax.media.opengl.GLDrawableFactory;
@@ -60,15 +59,12 @@ import jogamp.nativewindow.windows.GDI;
 import jogamp.opengl.GLDrawableImpl;
 import jogamp.opengl.GLGraphicsConfigurationUtil;
 import jogamp.opengl.windows.wgl.WindowsWGLDrawableFactory.SharedResource;
-// import javax.media.opengl.GLPbuffer;
 
 public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
   private WGLExt cachedWGLExt; // cached WGLExt instance from parent GLCanvas,
                                // needed to destroy pbuffer
   private long buffer; // pbuffer handle
 
-  private int floatMode;
-
   protected WindowsPbufferWGLDrawable(GLDrawableFactory factory, NativeSurface target) {
     super(factory, target, false);
   }
@@ -84,7 +80,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
 
   @Override
   public GLContext createContext(GLContext shareWith) {
-    return new WindowsPbufferWGLContext(this, shareWith);
+    return new WindowsWGLContext(this, shareWith);
   }
 
   protected void destroyPbuffer() {
@@ -115,13 +111,9 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
     return buffer;
   }
 
-  public int getFloatingPointMode() {
-    return floatMode;
-  }
-
   private void createPbuffer() {
     WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration();
-    SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(config.getScreen().getDevice());
+    SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResourceImpl(config.getScreen().getDevice());
     NativeSurface sharedSurface = sharedResource.getDrawable().getNativeSurface();
     if (NativeSurface.LOCK_SURFACE_NOT_READY >= sharedSurface.lockSurface()) {
       throw new NativeWindowException("Could not lock (sharedSurface): "+this);
@@ -131,7 +123,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
         WGLExt wglExt = ((WindowsWGLContext)sharedResource.getContext()).getWGLExt();
 
         if (DEBUG) {
-            System.out.println("Pbuffer config: " + config);
+            System.out.println(getThreadName()+": Pbuffer config: " + config);
         }
 
         final int winattrPbuffer = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(false /* onscreen */, false /* fbo */, true /* pbuffer */, false /* bitmap */);
@@ -146,8 +138,8 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
         final AbstractGraphicsDevice device = config.getScreen().getDevice();
 
         if (DEBUG) {
-          System.out.println("Pbuffer parentHdc = " + toHexString(sharedHdc));
-          System.out.println("Pbuffer chosenCaps: " + chosenCaps);
+          System.out.println(getThreadName()+": Pbuffer parentHdc = " + toHexString(sharedHdc));
+          System.out.println(getThreadName()+": Pbuffer chosenCaps: " + chosenCaps);
         }
 
         if(!WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(chosenCaps,
@@ -155,17 +147,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
           throw new GLException("Pbuffer-related extensions not supported");
         }
 
-        floatMode = floatModeTmp[0];
-        boolean rtt      = chosenCaps.getPbufferRenderToTexture();
-        boolean rect     = chosenCaps.getPbufferRenderToTextureRectangle();
-        boolean useFloat = chosenCaps.getPbufferFloatingPointBuffers();
-        // boolean ati      = false;
-
-        /**
-        if (useFloat) {
-          ati = (floatMode == GLPbuffer.ATI_FLOAT);
-        } */
-
         final IntBuffer pformats = Buffers.newDirectIntBuffer(WindowsWGLGraphicsConfiguration.MAX_PFORMATS);
         final IntBuffer nformatsTmp = Buffers.newDirectIntBuffer(1);
         if (!wglExt.wglChoosePixelFormatARB(sharedHdc,
@@ -173,7 +154,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
                                             pformats, nformatsTmp)) {
           throw new GLException("pbuffer creation error: wglChoosePixelFormat() failed");
         }
-        final int nformats = nformatsTmp.get(0);
+        final int nformats = Math.min(nformatsTmp.get(0), WindowsWGLGraphicsConfiguration.MAX_PFORMATS);
         if (nformats <= 0) {
           throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format");
         }
@@ -198,24 +179,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
               // Create the p-buffer.
               niattribs = 0;
 
-              if (rtt) {
-                iattributes.put(niattribs++, WGLExt.WGL_TEXTURE_FORMAT_ARB);
-                if (useFloat) {
-                  iattributes.put(niattribs++, WGLExt.WGL_TEXTURE_FLOAT_RGB_NV);
-                } else {
-                  iattributes.put(niattribs++, WGLExt.WGL_TEXTURE_RGBA_ARB);
-                }
-
-                iattributes.put(niattribs++, WGLExt.WGL_TEXTURE_TARGET_ARB);
-                iattributes.put(niattribs++, rect ? WGLExt.WGL_TEXTURE_RECTANGLE_NV : WGLExt.WGL_TEXTURE_2D_ARB);
-
-                iattributes.put(niattribs++, WGLExt.WGL_MIPMAP_TEXTURE_ARB);
-                iattributes.put(niattribs++, GL.GL_FALSE);
-
-                iattributes.put(niattribs++, WGLExt.WGL_PBUFFER_LARGEST_ARB); // exact
-                iattributes.put(niattribs++, GL.GL_FALSE);
-              }
-
               iattributes.put(niattribs++, 0);
 
               tmpBuffer = wglExt.wglCreatePbufferARB(sharedHdc, format, getWidth(), getHeight(), iattributes);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index 57f1652..94153d9 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
@@ -56,6 +56,7 @@ import com.jogamp.common.nio.Buffers;
 import com.jogamp.gluegen.runtime.ProcAddressTable;
 import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
 import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
 
 import jogamp.nativewindow.windows.GDI;
 import jogamp.opengl.GLContextImpl;
@@ -218,7 +219,6 @@ public class WindowsWGLContext extends GLContextImpl {
     };
 
     if ( major > 3 || major == 3 && minor >= 2  ) {
-        // FIXME: Verify with a None drawable binding (default framebuffer)
         attribs[idx_profile+0]  = WGLExt.WGL_CONTEXT_PROFILE_MASK_ARB;
         if( ctBwdCompat ) {
             attribs[idx_profile+1]  = WGLExt.WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
@@ -269,58 +269,82 @@ public class WindowsWGLContext extends GLContextImpl {
    */
   @Override
   protected boolean createImpl(GLContextImpl shareWith) {
-    AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
-    AbstractGraphicsDevice device = config.getScreen().getDevice();
-    WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl();
-    WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device);
-    GLCapabilitiesImmutable glCaps = drawable.getChosenGLCapabilities();
+    final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
+    final AbstractGraphicsDevice device = config.getScreen().getDevice();
+    final WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl();
+    final WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContext(device);
+    final GLCapabilitiesImmutable glCaps = drawable.getChosenGLCapabilities();
 
     isGLReadDrawableAvailable(); // trigger setup wglGLReadDrawableAvailable
 
+    if (DEBUG) {
+        System.err.println(getThreadName() + ": createImpl: START "+glCaps+", share "+shareWith);
+    }
+    
     // Windows can set up sharing of display lists after creation time
-    long share = 0;
-    if (null != shareWith) {
-      share = shareWith.getHandle();
-      if (share == 0) {
-        throw new GLException("GLContextShareSet returned an invalid OpenGL context");
-      }
+    long share;
+    if ( null != shareWith ) {
+        share = shareWith.getHandle();
+        if (share == 0) {
+            throw new GLException("GLContextShareSet returned an invalid OpenGL context");
+        }
+    } else {
+        share = 0;
     }
 
     boolean createContextARBTried = false;
 
-    // utilize the shared context's GLXExt in case it was using the ARB method and it already exists
-    if( null!=sharedContext && sharedContext.isCreatedWithARBMethod() ) {
-        contextHandle = createContextARB(share, true);
+    // utilize the shared context's GLXExt in case it was using the ARB method and it already exists ; exclude BITMAP
+    if( null != sharedContext && sharedContext.isCreatedWithARBMethod() && !glCaps.isBitmap() ) {
+        if ( sharedContext.getRendererQuirks().exist( GLRendererQuirks.NeedCurrCtx4ARBCreateContext ) ) {
+            if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
+                throw new GLException("Could not make Shared Context current: "+sharedContext);
+            }
+            contextHandle = createContextARB(share, true);
+            sharedContext.release();
+            if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+                throw new GLException("Cannot make previous verified context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError());
+            }
+        } else {
+            contextHandle = createContextARB(share, true);
+        }
         createContextARBTried = true;
-        if (DEBUG && 0!=contextHandle) {
+        if ( DEBUG && 0 != contextHandle ) {
             System.err.println(getThreadName() + ": createImpl: OK (ARB, using sharedContext) share "+share);
         }
     }
 
-    long temp_ctx = 0;
-    if(0==contextHandle) {
+    final long temp_ctx;
+    if( 0 == contextHandle ) {
         // To use WGL_ARB_create_context, we have to make a temp context current,
         // so we are able to use GetProcAddress
         temp_ctx = WGL.wglCreateContext(drawable.getHandle());
-        if (temp_ctx == 0) {
+        if ( 0 == temp_ctx ) {
           throw new GLException("Unable to create temp OpenGL context for device context " + toHexString(drawable.getHandle()));
         }
-        if (!WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx)) {
+        if ( !WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx) ) {
             throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: "+GDI.GetLastError());
         }
-        setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT);  // use GL_VERSION
+        setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false);  // use GL_VERSION
         WGL.wglMakeCurrent(0, 0); // release temp context
 
-        if( !createContextARBTried) {
+        if( !createContextARBTried ) {
             // is*Available calls are valid since setGLFunctionAvailability(..) was called
-            final boolean isProcCreateContextAttribsARBAvailable = isFunctionAvailable("wglCreateContextAttribsARB");
-            final boolean isExtARBCreateContextAvailable = isExtensionAvailable("WGL_ARB_create_context");
+            final boolean isProcCreateContextAttribsARBAvailable;
+            final boolean isExtARBCreateContextAvailable;
+            if( !glCaps.isBitmap() ) { // exclude ARB if BITMAP
+                isProcCreateContextAttribsARBAvailable = isFunctionAvailable("wglCreateContextAttribsARB");
+                isExtARBCreateContextAvailable = isExtensionAvailable("WGL_ARB_create_context");
+            } else {
+                isProcCreateContextAttribsARBAvailable = false;
+                isExtARBCreateContextAvailable = false;
+            }
             if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable ) {
                 // initial ARB context creation
                 contextHandle = createContextARB(share, true);
                 createContextARBTried=true;
                 if (DEBUG) {
-                    if(0!=contextHandle) {
+                    if( 0 != contextHandle ) {
                         System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+share);
                     } else {
                         System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+share);
@@ -331,11 +355,13 @@ public class WindowsWGLContext extends GLContextImpl {
                                    ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable);
             }
         }
+    } else {
+        temp_ctx = 0;
     }
 
-    if(0!=contextHandle) {
+    if( 0 != contextHandle ) {
         share = 0; // mark as shared thx to the ARB create method
-        if(0!=temp_ctx) {
+        if( 0 != temp_ctx ) {
             WGL.wglMakeCurrent(0, 0);
             WGL.wglDeleteContext(temp_ctx);
             if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
@@ -343,10 +369,10 @@ public class WindowsWGLContext extends GLContextImpl {
             }
         }
     } else {
-        if(glCaps.getGLProfile().isGL3()) {
+        if( glCaps.getGLProfile().isGL3() ) {
           WGL.wglMakeCurrent(0, 0);
           WGL.wglDeleteContext(temp_ctx);
-          throw new GLException("WindowsWGLContext.createContext ctx !ARB, context > GL2 requested "+getGLVersion());
+          throw new GLException(getThreadName()+": WindowsWGLContex.createContextImpl ctx !ARB, profile > GL2 requested (OpenGL >= 3.0.1). Requested: "+glCaps.getGLProfile()+", current: "+getGLVersion());
         }
         if(DEBUG) {
           System.err.println("WindowsWGLContext.createContext failed, fall back to !ARB context "+getGLVersion());
@@ -354,15 +380,15 @@ public class WindowsWGLContext extends GLContextImpl {
 
         // continue with temp context for GL < 3.0
         contextHandle = temp_ctx;
-        if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+        if ( !wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
             WGL.wglMakeCurrent(0, 0);
             WGL.wglDeleteContext(contextHandle);
             throw new GLException("Error making old context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError());
         }
-        if(0!=share) {
+        if( 0 != share ) {
             // Only utilize the classic GDI 'wglShareLists' shared context method
             // for traditional non ARB context.
-            if (!WGL.wglShareLists(share, contextHandle)) {
+            if ( !WGL.wglShareLists(share, contextHandle) ) {
                 throw new GLException("wglShareLists(" + toHexString(share) +
                                       ", " + toHexString(contextHandle) + ") failed: werr " + GDI.GetLastError());
             }
@@ -379,7 +405,11 @@ public class WindowsWGLContext extends GLContextImpl {
   protected void  makeCurrentImpl() throws GLException {
     if (WGL.wglGetCurrentContext() != contextHandle) {
       if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
-        throw new GLException("Error making context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError() + ", " + this);
+        throw new GLException("Error making context " + toHexString(contextHandle) + 
+                              " current on Thread " + getThreadName() +
+                              ", drawableWrite " + toHexString(drawable.getHandle()) +
+                              ", drawableRead "+ toHexString(drawableRead.getHandle()) +
+                              ", werr: " + GDI.GetLastError() + ", " + this);
       }
     }
   }
@@ -536,29 +566,4 @@ public class WindowsWGLContext extends GLContextImpl {
   public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
     return getWGLExt().wglAllocateMemoryNV(arg0, arg1, arg2, arg3);
   }
-
-  @Override
-  public int getOffscreenContextPixelDataType() {
-    throw new GLException("Should not call this");
-  }
-
-  public int getOffscreenContextReadBuffer() {
-    throw new GLException("Should not call this");
-  }
-
-  @Override
-  public boolean offscreenImageNeedsVerticalFlip() {
-    throw new GLException("Should not call this");
-  }
-
-  @Override
-  public void bindPbufferToTexture() {
-    throw new GLException("Should not call this");
-  }
-
-  @Override
-  public void releasePbufferFromTexture() {
-    throw new GLException("Should not call this");
-  }
-
 }
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java
index 3b3f0c1..8b8cb20 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java
@@ -67,7 +67,7 @@ public abstract class WindowsWGLDrawable extends GLDrawableImpl {
         WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
         config.updateGraphicsConfiguration(getFactory(), ns, null);
         if (DEBUG) {
-          System.err.println("WindowsWGLDrawable.setRealized(true): "+config);
+          System.err.println(getThreadName()+": WindowsWGLDrawable.setRealized(true): "+config);
         }
     }
   }
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index c6bc61a..45edda5 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -41,7 +41,10 @@
 package jogamp.opengl.windows.wgl;
 
 import java.nio.Buffer;
+
 import java.nio.ShortBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -53,7 +56,6 @@ import javax.media.nativewindow.DefaultGraphicsScreen;
 import javax.media.nativewindow.NativeSurface;
 import javax.media.nativewindow.ProxySurface;
 import javax.media.nativewindow.UpstreamSurfaceHook;
-import javax.media.opengl.GL;
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLCapabilitiesChooser;
 import javax.media.opengl.GLCapabilitiesImmutable;
@@ -75,13 +77,11 @@ import jogamp.opengl.GLDynamicLookupHelper;
 import jogamp.opengl.GLGraphicsConfigurationUtil;
 import jogamp.opengl.SharedResourceRunner;
 
-import com.jogamp.common.JogampRuntimeException;
 import com.jogamp.common.nio.PointerBuffer;
-import com.jogamp.common.os.Platform;
 import com.jogamp.common.util.ReflectionUtil;
-import com.jogamp.common.util.VersionNumber;
 import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
 import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
 
 public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
   private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null;
@@ -90,19 +90,24 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
     super();
 
     synchronized(WindowsWGLDrawableFactory.class) {
-        if(null==windowsWGLDynamicLookupHelper) {
-            DesktopGLDynamicLookupHelper tmp = null;
-            try {
-                tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo());
-            } catch (GLException gle) {
-                if(DEBUG) {
-                    gle.printStackTrace();
+        if( null == windowsWGLDynamicLookupHelper ) {
+            windowsWGLDynamicLookupHelper = AccessController.doPrivileged(new PrivilegedAction<DesktopGLDynamicLookupHelper>() {
+                public DesktopGLDynamicLookupHelper run() {
+                    DesktopGLDynamicLookupHelper tmp;
+                    try {
+                        tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo());
+                        if(null!=tmp && tmp.isLibComplete()) {
+                            WGL.getWGLProcAddressTable().reset(tmp);
+                        }
+                    } catch (Exception ex) {
+                        tmp = null;
+                        if(DEBUG) {
+                            ex.printStackTrace();
+                        }
+                    }
+                    return tmp;
                 }
-            }
-            if(null!=tmp && tmp.isLibComplete()) {
-                windowsWGLDynamicLookupHelper = tmp;
-                WGL.getWGLProcAddressTable().reset(windowsWGLDynamicLookupHelper);
-            }
+            } );
         }
     }
 
@@ -116,7 +121,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
             try {
               ReflectionUtil.callStaticMethod("jogamp.opengl.windows.wgl.awt.WindowsAWTWGLGraphicsConfigurationFactory",
                                               "registerFactory", null, null, getClass().getClassLoader());
-            } catch (JogampRuntimeException jre) { /* n/a .. */ }
+            } catch (Exception jre) { /* n/a .. */ }
         }
 
         sharedMap = new HashMap<String, SharedResourceRunner.Resource>();
@@ -175,7 +180,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
             long pid = GDI.GetCurrentProcess();
             if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) {
                 if(DEBUG) {
-                    System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName());
+                    System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + getThreadName());
                     // Thread.dumpStack();
                 }
                 processAffinityChanges = pid;
@@ -195,35 +200,25 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
                                                        " this PID 0x" + Long.toHexString(pid) );
             }
             if(DEBUG) {
-                System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName());
+                System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + getThreadName());
             }
             GDI.SetProcessAffinityMask(pid, sysMask.get(0));
         }
     }
   }
 
-  /**
-   * http://msdn.microsoft.com/en-us/library/ms724832%28v=vs.85%29.aspx
-   * Windows XP    5.1
-   */
-  static final VersionNumber winXPVersionNumber = new VersionNumber ( 5, 1, 0);
-
   static class SharedResource implements SharedResourceRunner.Resource {
+      private final boolean hasARBPixelFormat;
+      private final boolean hasARBMultisample;
+      private final boolean hasARBPBuffer;
+      private final boolean hasARBReadDrawable;
       private WindowsGraphicsDevice device;
       private AbstractGraphicsScreen screen;
       private GLDrawableImpl drawable;
       private GLContextImpl context;
-      private boolean hasARBPixelFormat;
-      private boolean hasARBMultisample;
-      private boolean hasARBPBuffer;
-      private boolean hasARBReadDrawable;
-      private String vendor;
-      private boolean isVendorATI;
-      private boolean isVendorNVIDIA;
-      private boolean needsCurrenContext4ARBPFDQueries;
-
+      
       SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, GLDrawableImpl draw, GLContextImpl ctx,
-                     boolean arbPixelFormat, boolean arbMultisample, boolean arbPBuffer, boolean arbReadDrawable, String glVendor) {
+                     boolean arbPixelFormat, boolean arbMultisample, boolean arbPBuffer, boolean arbReadDrawable) {
           device = dev;
           screen = scrn;
           drawable = draw;
@@ -232,28 +227,13 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
           hasARBMultisample = arbMultisample;
           hasARBPBuffer = arbPBuffer;
           hasARBReadDrawable = arbReadDrawable;
-          vendor = glVendor;
-          if(null != vendor) {
-              isVendorNVIDIA = vendor.startsWith("NVIDIA") ;
-              isVendorATI = vendor.startsWith("ATI") ;
-          }
-
-            if ( isVendorATI() ) {
-              final VersionNumber winVersion = Platform.getOSVersionNumber();
-              final boolean isWinXPOrLess = winVersion.compareTo(winXPVersionNumber) <= 0;
-              if(DEBUG) {
-                  System.err.println("needsCurrenContext4ARBPFDQueries: "+winVersion+" <= "+winXPVersionNumber+" = "+isWinXPOrLess+" - "+Platform.getOSVersion());
-              }
-              needsCurrenContext4ARBPFDQueries = isWinXPOrLess;
-            } else {
-            if(DEBUG) {
-                  System.err.println("needsCurrenContext4ARBPFDQueries: false");
-              }
-              needsCurrenContext4ARBPFDQueries = false;
-          }
       }
 
       @Override
+      public final boolean isValid() {
+          return null != context;
+      }
+      @Override
       final public AbstractGraphicsDevice getDevice() { return device; }
       @Override
       final public AbstractGraphicsScreen getScreen() { return screen; }
@@ -261,25 +241,15 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
       final public GLDrawableImpl getDrawable() { return drawable; }
       @Override
       final public GLContextImpl getContext() { return context; }
+      @Override
+      public GLRendererQuirks getRendererQuirks() {
+          return null != context ? context.getRendererQuirks() : null;      
+      }
 
       final boolean hasARBPixelFormat() { return hasARBPixelFormat; }
       final boolean hasARBMultisample() { return hasARBMultisample; }
       final boolean hasARBPBuffer() { return hasARBPBuffer; }
       final boolean hasReadDrawable() { return hasARBReadDrawable; }
-
-      final String vendor() { return vendor; }
-      final boolean isVendorATI() { return isVendorATI; }
-      final boolean isVendorNVIDIA() { return isVendorNVIDIA; }
-
-      /**
-       * Solves bug #480
-       *
-       * TODO: Validate if bug is actually relates to the 'old' ATI Windows driver for old GPU's like X300 etc
-       * and unrelated to the actual Windows version !
-       *
-       * @return true if GL_VENDOR is ATI _and_ platform is Windows version XP or less!
-       */
-      final boolean needsCurrentContext4ARBPFDQueries() { return needsCurrenContext4ARBPFDQueries; }
   }
 
   class SharedResourceImplementation implements SharedResourceRunner.Implementation {
@@ -309,6 +279,11 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
         }
 
         @Override
+        public boolean isDeviceSupported(String connection) {
+            return true;
+        }
+        
+        @Override
         public SharedResourceRunner.Resource createSharedResource(String connection) {
             final WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT);
             sharedDevice.lock();
@@ -330,7 +305,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
                 boolean hasARBMultisample;
                 boolean hasARBPBuffer;
                 boolean hasARBReadDrawableAvailable;
-                String vendor;
                 sharedContext.makeCurrent();
                 try {
                     hasARBPixelFormat = sharedContext.isExtensionAvailable(WGL_ARB_pixel_format);
@@ -338,7 +312,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
                     hasARBPBuffer = sharedContext.isExtensionAvailable(GLExtensions.ARB_pbuffer);
                     hasARBReadDrawableAvailable = sharedContext.isExtensionAvailable(WGL_ARB_make_current_read) &&
                                             sharedContext.isFunctionAvailable(wglMakeContextCurrent);
-                    vendor = sharedContext.getGL().glGetString(GL.GL_VENDOR);
                 } finally {
                     sharedContext.release();
                 }
@@ -350,11 +323,10 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
                     System.err.println("multisample:   " + hasARBMultisample);
                     System.err.println("pbuffer:       " + hasARBPBuffer);
                     System.err.println("readDrawable:  " + hasARBReadDrawableAvailable);
-                    System.err.println("vendor:        " + vendor);
                 }
                 return new SharedResource(sharedDevice, absScreen, sharedDrawable, sharedContext,
                                           hasARBPixelFormat, hasARBMultisample,
-                                          hasARBPBuffer, hasARBReadDrawableAvailable, vendor);
+                                          hasARBPBuffer, hasARBReadDrawableAvailable);
             } catch (Throwable t) {
                 throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+connection, t);
             } finally {
@@ -420,51 +392,18 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
   }
 
   @Override
-  protected final boolean createSharedResource(AbstractGraphicsDevice device) {
-    try {
-        SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
-        if(null!=sr) {
-          return null != sr.getContext();
-        }
-    } catch (GLException gle) {
-        if(DEBUG) {
-            System.err.println("Catched Exception while WindowsWGL Shared Resource initialization");
-            gle.printStackTrace();
-        }
-    }
-    return false;
-  }
-
-  @Override
-  protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
-    SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
-    if(null!=sr) {
-      return sr.getContext();
-    }
-    return null;
-  }
-
-  @Override
-  protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
-    SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
-    if(null!=sr) {
-        return sr.getDevice();
-    }
-    return null;
+  protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice device) {
+    return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
   }
 
-  protected WindowsWGLDrawable getOrCreateSharedDrawable(AbstractGraphicsDevice device) {
-    SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
+  protected final WindowsWGLDrawable getOrCreateSharedDrawable(AbstractGraphicsDevice device) {
+    SharedResourceRunner.Resource sr = getOrCreateSharedResourceImpl(device);
     if(null!=sr) {
         return (WindowsWGLDrawable) sr.getDrawable();
     }
     return null;
   }
 
-  SharedResource getOrCreateSharedResource(AbstractGraphicsDevice device) {
-    return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
-  }
-
   @Override
   protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
     return WindowsWGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device);
@@ -486,7 +425,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
     AbstractGraphicsConfiguration config = target.getGraphicsConfiguration();
     GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
     if(!chosenCaps.isPBuffer()) {
-        return new WindowsBitmapWGLDrawable(this, target);
+        return WindowsBitmapWGLDrawable.create(this, target);
     }
 
     // PBuffer GLDrawable Creation
@@ -497,7 +436,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
      * Similar to ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277,
      * we need to have a context current on the same Display to create a PBuffer.
      */
-    final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
+    final SharedResource sr = getOrCreateSharedResourceImpl(device);
     if(null!=sr) {
         GLContext lastContext = GLContext.getCurrent();
         if (lastContext != null) {
@@ -523,7 +462,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
    *           and -1 if undefined yet, ie no shared device exist at this point.
    */
   public final int isReadDrawableAvailable(AbstractGraphicsDevice device) {
-    SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice);
+    SharedResource sr = getOrCreateSharedResourceImpl( ( null != device ) ? device : defaultDevice );
     if(null!=sr) {
         return sr.hasReadDrawable() ? 1 : 0 ;
     }
@@ -532,7 +471,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
 
   @Override
   public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
-    SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice);
+    SharedResource sr = getOrCreateSharedResourceImpl( ( null != device ) ? device : defaultDevice );
     if(null!=sr) {
         return sr.hasARBPBuffer();
     }
@@ -613,17 +552,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
     return detail;
   }
 
-  @Override
-  public final boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
-    return false;
-  }
-
-  @Override
-  public final GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
-    throws GLException {
-    throw new GLException("Unimplemented on this platform");
-  }
-
   //------------------------------------------------------
   // Gamma-related functionality
   //
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java
index a553bd4..7ec6c50 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java
@@ -31,13 +31,13 @@ package jogamp.opengl.windows.wgl;
 import jogamp.opengl.*;
 import java.util.*;
 
-public class WindowsWGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo  {
+public final class WindowsWGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo  {
     protected WindowsWGLDynamicLibraryBundleInfo() {
         super();
     }
 
     @Override
-    public List<List<String>> getToolLibNames() {
+    public final List<List<String>> getToolLibNames() {
         final List<List<String>> libsList = new ArrayList<List<String>>();
         final List<String> libsGL = new ArrayList<String>();
         libsGL.add("OpenGL32");
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
index 70da113..42b9230 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
@@ -46,21 +46,18 @@ import javax.media.opengl.GLCapabilitiesImmutable;
 import javax.media.opengl.GLCapabilitiesChooser;
 import javax.media.opengl.GLDrawableFactory;
 import javax.media.opengl.GLException;
-import javax.media.opengl.GLPbuffer;
 import javax.media.opengl.GLProfile;
 
 import com.jogamp.common.nio.Buffers;
 import com.jogamp.nativewindow.MutableGraphicsConfiguration;
-import com.jogamp.opengl.GLExtensions;
 
 import jogamp.nativewindow.windows.DWM_BLURBEHIND;
 import jogamp.nativewindow.windows.GDI;
+import jogamp.nativewindow.windows.GDIUtil;
 import jogamp.nativewindow.windows.MARGINS;
 import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
-import jogamp.opengl.GLContextImpl;
 import jogamp.opengl.GLGraphicsConfigurationUtil;
 
- at SuppressWarnings("deprecation")
 public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {    
     protected static final int MAX_PFORMATS = 256;
     protected static final int MAX_ATTRIBS  = 256;
@@ -102,7 +99,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
         }
         WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory;
         AbstractGraphicsDevice device = screen.getDevice();
-        WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+        WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
         boolean hasARB = null != sharedResource && sharedResource.hasARBPixelFormat();
 
         WGLGLCapabilities caps = null;
@@ -170,13 +167,13 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
                                   " for device context " + toHexString(hdc) +
                                   ": error code " + GDI.GetLastError());
         }
-        if(!caps.isBackgroundOpaque()) {
+        if( !caps.isBackgroundOpaque() ) {
             final long hwnd = GDI.WindowFromDC(hdc);
             DWM_BLURBEHIND bb = DWM_BLURBEHIND.create();
-            bb.setDwFlags(GDI.DWM_BB_ENABLE);
-            bb.setFEnable(1);
+            bb.setDwFlags(GDI.DWM_BB_ENABLE| GDI.DWM_BB_TRANSITIONONMAXIMIZED);
+            bb.setFEnable( 1 );
             boolean ok = GDI.DwmEnableBlurBehindWindow(hwnd, bb);
-            if(ok) {
+            if( ok ) {
                 MARGINS m = MARGINS.create();
                 m.setCxLeftWidth(-1);
                 m.setCxRightWidth(-1);
@@ -185,7 +182,9 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
                 ok = GDI.DwmExtendFrameIntoClientArea(hwnd, m);
             }
             if(DEBUG) {
-                System.err.println("translucency enabled on wnd: 0x"+Long.toHexString(hwnd)+" - ok: "+ok);
+                final boolean isUndecorated = GDIUtil.IsUndecorated(hwnd);
+                final boolean isChild = GDIUtil.IsChild(hwnd);
+                System.err.println("translucency enabled on wnd: 0x"+Long.toHexString(hwnd)+" - isUndecorated "+isUndecorated+", isChild "+isChild+", ok: "+ok);
             }
         }
         if (DEBUG) {
@@ -254,15 +253,6 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
             iattributes.put(niattribs++, WGLExt.WGL_SAMPLE_BUFFERS_ARB);
             iattributes.put(niattribs++, WGLExt.WGL_SAMPLES_ARB);
         }
-            
-        if(sharedResource.hasARBPBuffer()) {
-            GLContextImpl sharedCtx = sharedResource.getContext();
-            if(null != sharedCtx && sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer)) {
-                // pbo float buffer
-                iattributes.put(niattribs++, WGLExt.WGL_FLOAT_COMPONENTS_NV); // nvidia
-            }
-        }
-
         return niattribs;
     }
     
@@ -358,7 +348,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
             }
             return null;
         }
-        final int numFormats = numFormatsTmp.get(0);
+        final int numFormats = Math.min(numFormatsTmp.get(0), WindowsWGLGraphicsConfiguration.MAX_PFORMATS);
         final int[] pformats;
         if( 0 < numFormats ) {
             pformats = new int[numFormats];
@@ -508,85 +498,8 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
             iattributes.put(niattribs++, caps.getNumSamples());
         }
 
-        boolean rtt      = caps.getPbufferRenderToTexture();
-        boolean rect     = caps.getPbufferRenderToTextureRectangle();
-        boolean useFloat = caps.getPbufferFloatingPointBuffers();
-        boolean ati      = false;
-        boolean nvidia   = false;
-        if ( usePBuffer ) {
-          // Check some invariants and set up some state
-          if (rect && !rtt) {
-            throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified");
-          }
-
-          GLContextImpl sharedCtx = sharedResource.getContext();
-          if (rect) {
-            if (!sharedCtx.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) {
-              throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension");
-            }
-          }
-
-          if (useFloat) {
-            // Prefer NVidia extension over ATI
-            nvidia = sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer);
-            if(nvidia) {
-              floatMode[0] = GLPbuffer.NV_FLOAT;
-            } else {
-                ati = sharedCtx.isExtensionAvailable("WGL_ATI_pixel_format_float");
-                if(ati) {
-                    floatMode[0] = GLPbuffer.ATI_FLOAT;
-                } else {
-                    throw new GLException("Floating-point pbuffers not supported by this hardware");                    
-                }
-            }
-            
-            if (DEBUG) {
-              System.err.println("Using " + (ati ? "ATI" : ( nvidia ? "NVidia" : "NONE" ) ) + " floating-point extension");
-            }
-          }
-
-          // See whether we need to change the pixel type to support ATI's
-          // floating-point pbuffers
-          if (useFloat && ati) {
-            if (rtt) {
-              throw new GLException("Render-to-floating-point-texture not supported on ATI hardware");
-            } else {
-              iattributes.put(niattribs++, WGLExt.WGL_PIXEL_TYPE_ARB);
-              iattributes.put(niattribs++, WGLExt.WGL_TYPE_RGBA_FLOAT_ARB);
-            }
-          } else {
-            if (!rtt) {
-              // Currently we don't support non-truecolor visuals in the
-              // GLCapabilities, so we don't offer the option of making
-              // color-index pbuffers.
-              iattributes.put(niattribs++, WGLExt.WGL_PIXEL_TYPE_ARB);
-              iattributes.put(niattribs++, WGLExt.WGL_TYPE_RGBA_ARB);
-            }
-          }
-
-          if (useFloat && nvidia) {
-            iattributes.put(niattribs++, WGLExt.WGL_FLOAT_COMPONENTS_NV);
-            iattributes.put(niattribs++, GL.GL_TRUE);
-          }
-
-          if (rtt) {
-            if (useFloat) {
-              assert(!ati);
-              assert(nvidia);
-              if (!rect) {
-                throw new GLException("Render-to-floating-point-texture only supported on NVidia hardware with render-to-texture-rectangle");
-              }
-              iattributes.put(niattribs++, WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
-              iattributes.put(niattribs++, GL.GL_TRUE);
-            } else {
-              iattributes.put(niattribs++, rect ? WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : WGLExt.WGL_BIND_TO_TEXTURE_RGB_ARB);
-              iattributes.put(niattribs++, GL.GL_TRUE);
-            }
-          }
-        } else {
-          iattributes.put(niattribs++, WGLExt.WGL_PIXEL_TYPE_ARB);
-          iattributes.put(niattribs++, WGLExt.WGL_TYPE_RGBA_ARB);
-        }
+        iattributes.put(niattribs++, WGLExt.WGL_PIXEL_TYPE_ARB);
+        iattributes.put(niattribs++, WGLExt.WGL_TYPE_RGBA_ARB);
         iattributes.put(niattribs++, 0);
 
         return true;
@@ -681,15 +594,28 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
         if(null == pfd) {
             return null;
         }
-        if ((pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) {
+        if ( (pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) {
             return null;
         }
         final int allDrawableTypeBits = PFD2DrawableTypeBits(pfd);
         final int drawableTypeBits = winattrmask & allDrawableTypeBits;
 
         if( 0 == drawableTypeBits ) {
+            if(DEBUG) {
+                System.err.println("Drop [drawableType mismatch]: " + WGLGLCapabilities.PFD2String(pfd, pfdID));
+            }
             return null;
         }
+        if( GLGraphicsConfigurationUtil.BITMAP_BIT == drawableTypeBits ) {
+            // BITMAP exclusive PFD SafeGuard: Only accept BITMAP compatible color formats!
+            final int pfdColorBits = pfd.getCColorBits(); 
+            if ( pfdColorBits != 24 || 0 < pfd.getCAlphaBits() ) { // Allowed: RGB888 && !alpha
+                if(DEBUG) {
+                    System.err.println("Drop [color bits excl BITMAP]: " + WGLGLCapabilities.PFD2String(pfd, pfdID));
+                }
+                return null;
+            }
+        }
 
         final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp);
         res.setValuesByGDI();
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
index 7b3bc3a..3d093b9 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
@@ -51,6 +51,7 @@ import javax.media.opengl.GLException;
 import javax.media.opengl.GLProfile;
 
 import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.GLRendererQuirks;
 
 import jogamp.nativewindow.windows.GDI;
 import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
@@ -114,21 +115,23 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
     }
 
     protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(WindowsWGLDrawableFactory factory, AbstractGraphicsDevice device) {
-        final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+        final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
         if(null == sharedResource) {
             throw new GLException("Shared resource for device n/a: "+device);
         }
         final GLDrawableImpl sharedDrawable = sharedResource.getDrawable();
-        final GLContext sharedContext = sharedResource.getContext();
         final GLProfile glp = GLProfile.getDefault(device);
 
         List<GLCapabilitiesImmutable> availableCaps = null;
         
-        if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) {
+        final GLContext sharedContext;
+        if ( factory.hasRendererQuirk(device, GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries) ) {
+            sharedContext = sharedResource.getContext();
             if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
                 throw new GLException("Could not make Shared Context current: "+device);
             }
         } else {
+            sharedContext = null;
             sharedDrawable.lockSurface();
         }
         try {
@@ -139,11 +142,15 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
             if (sharedResource.hasARBPixelFormat()) {
                 availableCaps = WindowsWGLGraphicsConfigurationFactory.getAvailableGLCapabilitiesARB(sharedResource, sharedResource.getDevice(), glp, hdc);
             }
-            if( null == availableCaps || availableCaps.isEmpty() ) {
-                availableCaps = getAvailableGLCapabilitiesGDI(device, glp, hdc);
+            final boolean hasARBCaps = null != availableCaps && !availableCaps.isEmpty() ;
+            final List<GLCapabilitiesImmutable> availableCapsGDI = getAvailableGLCapabilitiesGDI(device, glp, hdc, hasARBCaps);
+            if( !hasARBCaps ) {
+                availableCaps = availableCapsGDI;
+            } else {
+                availableCaps.addAll(availableCapsGDI);
             }
         } finally {
-            if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) {
+            if ( null != sharedContext ) {
                 sharedContext.release();    
             } else {
                 sharedDrawable.unlockSurface();
@@ -156,18 +163,20 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
         return availableCaps;
     }
 
-    static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, GLProfile glProfile, long hdc) {
+    private static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, GLProfile glProfile, long hdc) {
         final int pfdIDCount = WindowsWGLGraphicsConfiguration.wglARBPFDIDCount((WindowsWGLContext)sharedResource.getContext(), hdc);
         final int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFDIDs(pfdIDCount);
-        return WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedResource, device, glProfile, hdc, pformats, GLGraphicsConfigurationUtil.ALL_BITS);
+        return WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedResource, device, glProfile, hdc, pformats, 
+                GLGraphicsConfigurationUtil.ALL_BITS & ~GLGraphicsConfigurationUtil.BITMAP_BIT); // w/o BITMAP
     }
 
-    static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesGDI(AbstractGraphicsDevice device, GLProfile glProfile, long hdc) {
+    private static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesGDI(AbstractGraphicsDevice device, GLProfile glProfile, long hdc, boolean bitmapOnly) {
         int[] pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc);
         int numFormats = pformats.length;
         List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(numFormats);
         for (int i = 0; i < numFormats; i++) {
-            final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], GLGraphicsConfigurationUtil.ALL_BITS);
+            final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], 
+                 bitmapOnly ? GLGraphicsConfigurationUtil.BITMAP_BIT : GLGraphicsConfigurationUtil.ALL_BITS );
             if(null != caps) {
                 bucket.add(caps);
             }
@@ -275,16 +284,23 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
             System.err.println("user chosen caps " + config.getChosenCapabilities());
         }
         AbstractGraphicsDevice device = config.getScreen().getDevice();
-        WindowsWGLDrawableFactory.SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(device);
-        GLContext sharedContext = null;
-        if (null != sharedResource && sharedResource.needsCurrentContext4ARBPFDQueries()) {
+        WindowsWGLDrawableFactory.SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResourceImpl(device);
+        final GLContext sharedContext;
+        if ( factory.hasRendererQuirk(device, GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries) ) {
             sharedContext = sharedResource.getContext();
             if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
                 throw new GLException("Could not make Shared Context current: "+device);
             }
+        } else {
+            sharedContext = null;
         }
         try {
-            if( !updateGraphicsConfigurationARB((WindowsWGLDrawableFactory)factory, config, chooser, hdc, extHDC, pfdIDs) ) {
+            final GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+            boolean done = false;
+            if( capsChosen.getHardwareAccelerated() && !capsChosen.isBitmap() ) {
+                done = updateGraphicsConfigurationARB((WindowsWGLDrawableFactory)factory, config, chooser, hdc, extHDC, pfdIDs);
+            }
+            if( !done ) {
                 updateGraphicsConfigurationGDI(config, chooser, hdc, extHDC, pfdIDs);
             }
         } finally {
@@ -297,7 +313,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
     private static boolean updateGraphicsConfigurationARB(WindowsWGLDrawableFactory factory, WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser,
                                                           long hdc, boolean extHDC, int[] pformats) {
         final AbstractGraphicsDevice device = config.getScreen().getDevice();
-        final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+        final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
 
         if (null == sharedResource) {
             if (DEBUG) {
@@ -314,7 +330,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
 
         final GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
         final boolean isOpaque = capsChosen.isBackgroundOpaque() && GDI.DwmIsCompositionEnabled();
-        final int winattrbits = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen);
+        final int winattrbits = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen) & ~GLGraphicsConfigurationUtil.BITMAP_BIT; // w/o BITMAP
         final GLProfile glProfile = capsChosen.getGLProfile();
         
         final int pfdIDCount = WindowsWGLGraphicsConfiguration.wglARBPFDIDCount((WindowsWGLContext)sharedResource.getContext(), hdc);
@@ -483,7 +499,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
 
             List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
             for (int i = 0; i < pformats.length; i++) {
-                final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], winattrmask);
+                final WGLGLCapabilities caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], winattrmask);
                 if(null != caps) {
                     availableCaps.add(caps);
                     if(DEBUG) {
@@ -527,7 +543,8 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
             }
             pixelFormatCaps = (WGLGLCapabilities) availableCaps.get(chosenIndex);
             if (DEBUG) {
-                System.err.println("chosen pfdID (GDI): chosenIndex "+ chosenIndex + ", caps " + pixelFormatCaps);
+                System.err.println("chosen pfdID (GDI): chosenIndex "+ chosenIndex + ", caps " + pixelFormatCaps + 
+                                   " (" + WGLGLCapabilities.PFD2String(pixelFormatCaps.getPFD(), pixelFormatCaps.getPFDID()) +")");
             }
         }
 
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
index bebb4e6..72e84b0 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
@@ -58,13 +58,12 @@ import com.jogamp.common.nio.Buffers;
 import com.jogamp.nativewindow.x11.X11GraphicsScreen;
 
 public class X11ExternalGLXContext extends X11GLXContext {
-  private GLContext lastContext;
 
   private X11ExternalGLXContext(Drawable drawable, long ctx) {
     super(drawable, null);
     this.contextHandle = ctx;
     GLContextShareSet.contextCreated(this);
-    setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT);
+    setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false);
     getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
   }
 
@@ -118,25 +117,6 @@ public class X11ExternalGLXContext extends X11GLXContext {
   }
 
   @Override
-  public int makeCurrent() throws GLException {
-    // Save last context if necessary to allow external GLContexts to
-    // talk to other GLContexts created by this library
-    GLContext cur = getCurrent();
-    if (cur != null && cur != this) {
-      lastContext = cur;
-      setCurrent(null);
-    }
-    return super.makeCurrent();
-  }
-
-  @Override
-  public void release() throws GLException {
-    super.release();
-    setCurrent(lastContext);
-    lastContext = null;
-  }
-
-  @Override
   protected void makeCurrentImpl() throws GLException {
   }
 
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index 76e0bc1..c37bcee 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -53,6 +53,7 @@ import javax.media.opengl.GLContext;
 import javax.media.opengl.GLException;
 import javax.media.opengl.GLProfile;
 
+import jogamp.nativewindow.x11.X11Lib;
 import jogamp.nativewindow.x11.X11Util;
 import jogamp.opengl.GLContextImpl;
 import jogamp.opengl.GLDrawableImpl;
@@ -65,7 +66,7 @@ import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
 import com.jogamp.nativewindow.x11.X11GraphicsDevice;
 import com.jogamp.opengl.GLExtensions;
 
-public abstract class X11GLXContext extends GLContextImpl {
+public class X11GLXContext extends GLContextImpl {
   private static final Map<String, String> functionNameMap;
   private static final Map<String, String> extensionNameMap;
   private GLXExt _glXExt;
@@ -145,6 +146,13 @@ public abstract class X11GLXContext extends GLContextImpl {
     isGLXVersionGreaterEqualOneThree = null != glXServerVersion ? glXServerVersion.compareTo(X11GLXDrawableFactory.versionOneThree) >= 0 : false;
     return isGLXVersionGreaterEqualOneThree;
   }
+  protected final void forceGLXVersionOneOne() {
+    glXServerVersion = X11GLXDrawableFactory.versionOneOne;
+    isGLXVersionGreaterEqualOneThree = false;
+    if(DEBUG) {
+        System.err.println("X11GLXContext.forceGLXVersionNumber: "+glXServerVersion);
+    }
+  }
 
   @Override
   public final boolean isGLReadDrawableAvailable() {
@@ -166,7 +174,7 @@ public abstract class X11GLXContext extends GLContextImpl {
             throw new InternalError("Given readDrawable but no driver support");
         }
     } catch (RuntimeException re) {
-        if(DEBUG || TRACE_SWITCH) {
+        if( DEBUG_TRACE_SWITCH ) {
           System.err.println(getThreadName()+": Warning: X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+
             "dpy "+toHexString(dpy)+
             ", write "+toHexString(writeDrawable)+
@@ -246,6 +254,7 @@ public abstract class X11GLXContext extends GLContextImpl {
         // critical path, a remote display might not support this command,
         // hence we need to catch the X11 Error within this block.
         X11Util.setX11ErrorHandler(true, DEBUG ? false : true); // make sure X11 error handler is set
+        X11Lib.XSync(display, false);
         ctx = _glXExt.glXCreateContextAttribsARB(display, config.getFBConfig(), share, direct, attribs);
     } catch (RuntimeException re) {
         if(DEBUG) {
@@ -281,34 +290,37 @@ public abstract class X11GLXContext extends GLContextImpl {
     final X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl();
     final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
     final AbstractGraphicsDevice device = config.getScreen().getDevice();
-    final X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContextImpl(device);
+    final X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContext(device);
     long display = device.getHandle();
 
-    long share = 0;
-    if (shareWith != null) {
-      share = shareWith.getHandle();
-      if (share == 0) {
-        throw new GLException("GLContextShareSet returned an invalid OpenGL context");
-      }
-      direct = GLX.glXIsDirect(display, share);
+    final long share;
+    if ( null != shareWith ) {
+        share = shareWith.getHandle();
+        if (share == 0) {
+            throw new GLException("GLContextShareSet returned an invalid OpenGL context");
+        }
+        direct = GLX.glXIsDirect(display, share);
+    } else {
+        share = 0;
     }
 
-    GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
-    GLProfile glp = glCaps.getGLProfile();
+    final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+    final GLProfile glp = glCaps.getGLProfile();
 
-    if(config.getFBConfigID()<0) {
-        // not able to use FBConfig
+    if( !config.hasFBConfig() ) {
+        // not able to use FBConfig -> GLX 1.1
+        forceGLXVersionOneOne();
         if(glp.isGL3()) {
           throw new GLException(getThreadName()+": Unable to create OpenGL >= 3.1 context");
         }
         contextHandle = GLX.glXCreateContext(display, config.getXVisualInfo(), share, direct);
-        if (contextHandle == 0) {
+        if ( 0 == contextHandle ) {
           throw new GLException(getThreadName()+": Unable to create context(0)");
         }
-        if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+        if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
           throw new GLException(getThreadName()+": Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
         }
-        setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+        setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION
         isDirect = GLX.glXIsDirect(display, contextHandle);
         if (DEBUG) {
             System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+share+", direct "+isDirect+"/"+direct);
@@ -319,26 +331,26 @@ public abstract class X11GLXContext extends GLContextImpl {
     boolean createContextARBTried = false;
 
     // utilize the shared context's GLXExt in case it was using the ARB method and it already exists
-    if(null!=sharedContext && sharedContext.isCreatedWithARBMethod()) {
+    if( null != sharedContext && sharedContext.isCreatedWithARBMethod() ) {
         contextHandle = createContextARB(share, direct);
         createContextARBTried = true;
-        if (DEBUG && 0!=contextHandle) {
+        if ( DEBUG && 0 != contextHandle ) {
             System.err.println(getThreadName() + ": createContextImpl: OK (ARB, using sharedContext) share "+share);
         }
     }
 
-    long temp_ctx = 0;
-    if(0==contextHandle) {
+    final long temp_ctx;
+    if( 0 == contextHandle ) {
         // To use GLX_ARB_create_context, we have to make a temp context current,
         // so we are able to use GetProcAddress
         temp_ctx = GLX.glXCreateNewContext(display, config.getFBConfig(), GLX.GLX_RGBA_TYPE, share, direct);
-        if (temp_ctx == 0) {
+        if ( 0 == temp_ctx ) {
             throw new GLException(getThreadName()+": Unable to create temp OpenGL context(1)");
         }
-        if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx)) {
+        if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx) ) {
           throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable);
         }
-        setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+        setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION
         glXMakeContextCurrent(display, 0, 0, 0); // release temp context
         if( !createContextARBTried ) {
             // is*Available calls are valid since setGLFunctionAvailability(..) was called
@@ -349,7 +361,7 @@ public abstract class X11GLXContext extends GLContextImpl {
                 contextHandle = createContextARB(share, direct);
                 createContextARBTried=true;
                 if (DEBUG) {
-                    if(0!=contextHandle) {
+                    if( 0 != contextHandle ) {
                         System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+share);
                     } else {
                         System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+share);
@@ -360,21 +372,23 @@ public abstract class X11GLXContext extends GLContextImpl {
                                    ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable);
             }
         }
+    } else {
+        temp_ctx = 0;
     }
 
-    if(0!=contextHandle) {
-        if(0!=temp_ctx) {
+    if( 0 != contextHandle ) {
+        if( 0 != temp_ctx ) {
             glXMakeContextCurrent(display, 0, 0, 0);
             GLX.glXDestroyContext(display, temp_ctx);
-            if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+            if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
                 throw new GLException(getThreadName()+": Cannot make previous verified context current");
             }
         }
     } else {
-        if(glp.isGL3()) {
+        if( glp.isGL3() ) {
           glXMakeContextCurrent(display, 0, 0, 0);
           GLX.glXDestroyContext(display, temp_ctx);
-          throw new GLException(getThreadName()+": X11GLXContext.createContextImpl ctx !ARB, context > GL2 requested - requested: "+glp+", current: "+getGLVersion()+", ");
+          throw new GLException(getThreadName()+": X11GLXContext.createContextImpl ctx !ARB, profile > GL2 requested (OpenGL >= 3.0.1). Requested: "+glp+", current: "+getGLVersion());
         }
         if(DEBUG) {
           System.err.println(getThreadName()+": X11GLXContext.createContextImpl failed, fall back to !ARB context "+getGLVersion());
@@ -382,7 +396,7 @@ public abstract class X11GLXContext extends GLContextImpl {
 
         // continue with temp context for GL <= 3.0
         contextHandle = temp_ctx;
-        if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+        if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) {
           glXMakeContextCurrent(display, 0, 0, 0);
           GLX.glXDestroyContext(display, temp_ctx);
           throw new GLException(getThreadName()+": Error making context(1) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
@@ -403,9 +417,14 @@ public abstract class X11GLXContext extends GLContextImpl {
   protected void makeCurrentImpl() throws GLException {
     long dpy = drawable.getNativeSurface().getDisplayHandle();
 
-    if (GLX.glXGetCurrentContext() != contextHandle) {        
+    if (GLX.glXGetCurrentContext() != contextHandle) {
         if (!glXMakeContextCurrent(dpy, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
-            throw new GLException(getThreadName()+": Error making context current: "+this);
+            throw new GLException("Error making context " + toHexString(contextHandle) + 
+                                  " current on Thread " + getThreadName() +
+                                  " with display " + toHexString(dpy) +
+                                  ", drawableWrite " + toHexString(drawable.getHandle()) +
+                                  ", drawableRead "+ toHexString(drawableRead.getHandle()) +
+                                  " - " + this);
         }
     }
   }
@@ -619,30 +638,6 @@ public abstract class X11GLXContext extends GLContextImpl {
   }
 
   @Override
-  public int getOffscreenContextPixelDataType() {
-    throw new GLException("Should not call this");
-  }
-
-  public int getOffscreenContextReadBuffer() {
-    throw new GLException("Should not call this");
-  }
-
-  @Override
-  public boolean offscreenImageNeedsVerticalFlip() {
-    throw new GLException("Should not call this");
-  }
-
-  @Override
-  public void bindPbufferToTexture() {
-    throw new GLException("Should not call this");
-  }
-
-  @Override
-  public void releasePbufferFromTexture() {
-    throw new GLException("Should not call this");
-  }
-
-  @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
     sb.append(getClass().getSimpleName());
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java
index 8c64277..155c00c 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java
@@ -63,7 +63,7 @@ public abstract class X11GLXDrawable extends GLDrawableImpl {
         config.updateGraphicsConfiguration();
 
         if (DEBUG) {
-          System.err.println("X11GLXDrawable.setRealized(true): "+config);
+          System.err.println(getThreadName()+": X11GLXDrawable.setRealized(true): "+config);
         }
     }
   }
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index e38aabe..b3b02e2 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -39,6 +39,8 @@ package jogamp.opengl.x11.glx;
 
 import java.nio.Buffer;
 import java.nio.ShortBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -73,6 +75,7 @@ import jogamp.opengl.SharedResourceRunner;
 import com.jogamp.common.util.VersionNumber;
 import com.jogamp.nativewindow.x11.X11GraphicsDevice;
 import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+import com.jogamp.opengl.GLRendererQuirks;
 
 public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
 
@@ -90,19 +93,24 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
     super();
 
     synchronized(X11GLXDrawableFactory.class) {
-        if(null==x11GLXDynamicLookupHelper) {
-            DesktopGLDynamicLookupHelper tmp = null;
-            try {
-                tmp = new DesktopGLDynamicLookupHelper(new X11GLXDynamicLibraryBundleInfo());
-            } catch (GLException gle) {
-                if(DEBUG) {
-                    gle.printStackTrace();
+        if( null == x11GLXDynamicLookupHelper ) {
+            x11GLXDynamicLookupHelper = AccessController.doPrivileged(new PrivilegedAction<DesktopGLDynamicLookupHelper>() {
+                public DesktopGLDynamicLookupHelper run() {
+                    DesktopGLDynamicLookupHelper tmp;
+                    try {
+                        tmp = new DesktopGLDynamicLookupHelper(new X11GLXDynamicLibraryBundleInfo());
+                        if(null!=tmp && tmp.isLibComplete()) {
+                            GLX.getGLXProcAddressTable().reset(tmp);
+                        }
+                    } catch (Exception ex) {
+                        tmp = null;
+                        if(DEBUG) {
+                            ex.printStackTrace();
+                        }
+                    }
+                    return tmp;
                 }
-            }
-            if(null!=tmp && tmp.isLibComplete()) {
-                x11GLXDynamicLookupHelper = tmp;
-                GLX.getGLXProcAddressTable().reset(x11GLXDynamicLookupHelper);
-            }
+            } );
         }
     }
 
@@ -156,17 +164,17 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
   private HashMap<String /* connection */, SharedResourceRunner.Resource> sharedMap;
 
   static class SharedResource implements SharedResourceRunner.Resource {
+      private final String glXServerVendorName;
+      private final boolean isGLXServerVendorATI;
+      private final boolean isGLXServerVendorNVIDIA;
+      private final VersionNumber glXServerVersion;
+      private final boolean glXServerVersionOneOneCapable;
+      private final boolean glXServerVersionOneThreeCapable;
+      private final boolean glXMultisampleAvailable;
       X11GraphicsDevice device;
       X11GraphicsScreen screen;
       GLDrawableImpl drawable;
       GLContextImpl context;
-      String glXServerVendorName;
-      boolean isGLXServerVendorATI;
-      boolean isGLXServerVendorNVIDIA;
-      VersionNumber glXServerVersion;
-      boolean glXServerVersionOneOneCapable;
-      boolean glXServerVersionOneThreeCapable;
-      boolean glXMultisampleAvailable;
 
       SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn,
                      GLDrawableImpl draw, GLContextImpl ctx,
@@ -184,6 +192,10 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
           glXMultisampleAvailable = glXServerMultisampleAvail;
       }
       @Override
+      public final boolean isValid() {
+          return null != context;
+      }
+      @Override
       final public AbstractGraphicsDevice getDevice() { return device; }
       @Override
       final public AbstractGraphicsScreen getScreen() { return screen; }
@@ -191,6 +203,10 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
       final public GLDrawableImpl getDrawable() { return drawable; }
       @Override
       final public GLContextImpl getContext() { return context; }
+      @Override
+      public GLRendererQuirks getRendererQuirks() {
+          return null != context ? context.getRendererQuirks() : null;      
+      }
 
       final String getGLXVendorName() { return glXServerVendorName; }
       final boolean isGLXVendorATI() { return isGLXServerVendorATI; }
@@ -228,18 +244,31 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
         }
 
         @Override
+        public boolean isDeviceSupported(String connection) {
+            final boolean res;
+            final X11GraphicsDevice x11Device = new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
+            x11Device.lock();
+            try {
+                res = GLXUtil.isGLXAvailableOnServer(x11Device);
+            } finally {
+                x11Device.unlock();
+                x11Device.close();
+            }
+            if(DEBUG) {
+                System.err.println("GLX "+(res ? "is" : "not")+" available on device/server: "+x11Device);
+            }
+            return res;
+        }
+        
+        @Override
         public SharedResourceRunner.Resource createSharedResource(String connection) {
             final X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
             sharedDevice.lock();
             try {
                 final X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, sharedDevice.getDefaultScreen());
                 
-                if(!GLXUtil.isGLXAvailableOnServer(sharedDevice)) {
-                    throw new GLException("GLX not available on device/server: "+sharedDevice);
-                }
                 GLXUtil.initGLXClientDataSingleton(sharedDevice);
                 final String glXServerVendorName = GLX.glXQueryServerString(sharedDevice.getHandle(), 0, GLX.GLX_VENDOR);
-                final VersionNumber glXServerVersion = GLXUtil.getGLXServerVersionNumber(sharedDevice);
                 final boolean glXServerMultisampleAvailable = GLXUtil.isMultisampleAvailable(GLX.glXQueryServerString(sharedDevice.getHandle(), 0, GLX.GLX_EXTENSIONS));
                 
                 final GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
@@ -250,7 +279,14 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
                 final GLCapabilitiesImmutable caps = new GLCapabilities(glp);
                 final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, caps, caps, null, 64, 64));
                 sharedDrawable.setRealized(true);
-                
+                final X11GLCapabilities chosenCaps =  (X11GLCapabilities) sharedDrawable.getChosenGLCapabilities();
+                final boolean glxForcedOneOne = !chosenCaps.hasFBConfig();
+                final VersionNumber glXServerVersion;
+                if( glxForcedOneOne ) {
+                    glXServerVersion = versionOneOne;
+                } else {
+                    glXServerVersion = GLXUtil.getGLXServerVersionNumber(sharedDevice);
+                }
                 final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null);
                 if (null == sharedContext) {
                     throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable);
@@ -263,12 +299,15 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
                 } finally {
                     sharedContext.release();
                 }
+                if( sharedContext.hasRendererQuirk( GLRendererQuirks.DontCloseX11Display ) ) {
+                    X11Util.markAllDisplaysUnclosable();
+                }
                 if (DEBUG) {
                     System.err.println("SharedDevice:  " + sharedDevice);
                     System.err.println("SharedScreen:  " + sharedScreen);
                     System.err.println("SharedContext: " + sharedContext + ", madeCurrent " + madeCurrent);
                     System.err.println("GLX Server Vendor:      " + glXServerVendorName);
-                    System.err.println("GLX Server Version:     " + glXServerVersion);
+                    System.err.println("GLX Server Version:     " + glXServerVersion + ", forced "+glxForcedOneOne);
                     System.err.println("GLX Server Multisample: " + glXServerMultisampleAvailable);
                     System.err.println("GLX Client Vendor:      " + GLXUtil.getClientVendorName());
                     System.err.println("GLX Client Version:     " + GLXUtil.getClientVersionNumber());
@@ -339,51 +378,18 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
   }
 
   @Override
-  protected final boolean createSharedResource(AbstractGraphicsDevice device) {
-    try {
-        SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
-        if(null!=sr) {
-          return null != sr.getContext();
-        }
-    } catch (GLException gle) {
-        if(DEBUG) {
-            System.err.println("Catched Exception while X11GLX Shared Resource initialization");
-            gle.printStackTrace();
-        }
-    }
-    return false;
-  }
-
-  @Override
-  protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
-    SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
-    if(null!=sr) {
-      return sr.getContext();
-    }
-    return null;
-  }
-
-  @Override
-  protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
-    SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
-    if(null!=sr) {
-        return sr.getDevice();
-    }
-    return null;
+  protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice device) {
+    return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
   }
 
   protected final long getOrCreateSharedDpy(AbstractGraphicsDevice device) {
-    SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
+    final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
     if(null!=sr) {
         return sr.getDevice().getHandle();
     }
     return 0;
   }
 
-  SharedResource getOrCreateSharedResource(AbstractGraphicsDevice device) {
-    return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
-  }
-
   @Override
   protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
     return X11GLXGraphicsConfigurationFactory.getAvailableCapabilities(this, device);
@@ -553,17 +559,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
     return X11ExternalGLXDrawable.create(this, null);
   }
 
-  @Override
-  public final boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
-    return false;
-  }
-
-  @Override
-  public final GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
-    throws GLException {
-    throw new GLException("Unimplemented on this platform");
-  }
-
   //----------------------------------------------------------------------
   // Gamma-related functionality
   //
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java
index 108c157..f25f7ae 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java
@@ -31,13 +31,13 @@ package jogamp.opengl.x11.glx;
 import jogamp.opengl.*;
 import java.util.*;
 
-public class X11GLXDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo  {
+public final class X11GLXDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo  {
     protected X11GLXDynamicLibraryBundleInfo() {
         super();
     }
 
     @Override
-    public List<List<String>> getToolLibNames() {
+    public final List<List<String>> getToolLibNames() {
         final List<List<String>> libsList = new ArrayList<List<String>>();
         final List<String> libsGL = new ArrayList<String>();
         
@@ -60,15 +60,6 @@ public class X11GLXDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundl
         return libsList;
     }    
     
-    /** 
-     * This respects old DRI requirements:<br>
-     * <pre>
-     * http://dri.sourceforge.net/doc/DRIuserguide.html
-     * </pre>
-     */
-    @Override
-    public boolean shallLinkGlobal() { return true; }
-
     @Override
     public final List<String> getToolGetProcAddressFuncNameList() {
         List<String> res = new ArrayList<String>();
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
index 12ce223..c23bd53 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
@@ -79,6 +79,9 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
     public final int  getFBConfigID() {
         return ((X11GLCapabilities)capabilitiesChosen).getFBConfigID();
     }
+    public final boolean hasFBConfig() {
+        return ((X11GLCapabilities)capabilitiesChosen).hasFBConfig();
+    }
 
     void updateGraphicsConfiguration() {
         final CapabilitiesImmutable aChosenCaps = getChosenCapabilities();
@@ -225,17 +228,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
           res.put(idx++, GLX.GLX_SAMPLES);
           res.put(idx++, caps.getNumSamples());
         }
-        if (caps.isPBuffer()) {
-          if (caps.getPbufferFloatingPointBuffers()) {
-            String glXExtensions = GLX.glXQueryExtensionsString(display, screen);
-            if (glXExtensions == null ||
-                glXExtensions.indexOf("GLX_NV_float_buffer") < 0) {
-              throw new GLException("Floating-point pbuffers on X11 currently require NVidia hardware: "+glXExtensions);
-            }
-            res.put(idx++, GLXExt.GLX_FLOAT_COMPONENTS_NV);
-            res.put(idx++, GL.GL_TRUE);
-          }
-        }
         res.put(idx++, 0);
         return res;
   }
@@ -341,10 +333,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
     res.setDepthBits     (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE,       tmp));
     res.setStencilBits   (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE,     tmp));
     
-    try { 
-        res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp) != GL.GL_FALSE);
-    } catch (Exception e) {}
-
     return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); 
   }
 
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
index e62dcad..a7c7d3f 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
@@ -124,7 +124,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
     }
 
     protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(X11GLXDrawableFactory factory, AbstractGraphicsDevice device) {
-        X11GLXDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+        X11GLXDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
         if(null == sharedResource) {
             throw new GLException("Shared resource for device n/a: "+device);
         }
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java
deleted file mode 100644
index 460dc10..0000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2003 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.
- *
- * 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 jogamp.opengl.x11.glx;
-
-import javax.media.opengl.*;
-
-public class X11OnscreenGLXContext extends X11GLXContext {
-
-    public X11OnscreenGLXContext(X11OnscreenGLXDrawable drawable, GLContext shareWith) {
-        super(drawable, shareWith);
-    }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
index c15065c..9da1892 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
@@ -56,7 +56,7 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
     glXWindow=0;
     useGLXWindow=false;
     if(realized) {
-        updateHandle();
+        createHandle();
     }
   }
 
@@ -82,7 +82,7 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
   }
 
   @Override
-  protected final void updateHandle() {
+  protected final void createHandle() {
     if(USE_GLXWINDOW) {
         X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
         if(config.getFBConfig()>=0) {
@@ -104,6 +104,6 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
 
   @Override
   public GLContext createContext(GLContext shareWith) {
-    return new X11OnscreenGLXContext(this, shareWith);
+    return new X11GLXContext(this, shareWith);
   }
 }
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java
deleted file mode 100644
index a34e050..0000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2003 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.
- *
- * 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 jogamp.opengl.x11.glx;
-
-import javax.media.opengl.*;
-
-public class X11PbufferGLXContext extends X11GLXContext {
-
-  public X11PbufferGLXContext(X11PbufferGLXDrawable drawable, GLContext shareWith) {
-    super(drawable, shareWith);
-  }
-
-  @Override
-  public void bindPbufferToTexture() {
-    // FIXME: figure out how to implement this
-    throw new GLException("Not yet implemented");
-  }
-
-  @Override
-  public void releasePbufferFromTexture() {
-    // FIXME: figure out how to implement this
-    throw new GLException("Not yet implemented");
-  }
-
-
-  @Override
-  public int getFloatingPointMode() {
-    return ((X11PbufferGLXDrawable)drawable).getFloatingPointMode();
-  }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
index 28db2ad..0e771fd 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
@@ -46,11 +46,9 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.AbstractGraphicsScreen;
 import javax.media.nativewindow.NativeSurface;
 import javax.media.nativewindow.MutableSurface;
-import javax.media.opengl.GLCapabilitiesImmutable;
 import javax.media.opengl.GLContext;
 import javax.media.opengl.GLDrawableFactory;
 import javax.media.opengl.GLException;
-import javax.media.opengl.GLPbuffer;
 
 import com.jogamp.common.nio.Buffers;
 
@@ -73,7 +71,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
 
   @Override
   public GLContext createContext(GLContext shareWith) {
-    return new X11PbufferGLXContext(this, shareWith);
+    return new X11GLXContext(this, shareWith);
   }
 
   protected void destroyPbuffer() {
@@ -82,6 +80,9 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
       GLX.glXDestroyPbuffer(ns.getDisplayHandle(), ns.getSurfaceHandle());
     }
     ((MutableSurface)ns).setSurfaceHandle(0);
+    if (DEBUG) {
+        System.err.println(getThreadName()+": Destroyed pbuffer " + this);
+    }
   }
 
   private void createPbuffer() {
@@ -92,23 +93,13 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
       final long display = aDevice.getHandle();
 
       if (DEBUG) {
-        System.out.println("Pbuffer config: " + config);
+        System.out.println(getThreadName()+": Pbuffer config: " + config);
       }
 
       if (display==0) {
         throw new GLException("Null display");
       }
 
-      GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
-
-      if (chosenCaps.getPbufferRenderToTexture()) {
-        throw new GLException("Render-to-texture pbuffers not supported yet on X11");
-      }
-
-      if (chosenCaps.getPbufferRenderToTextureRectangle()) {
-        throw new GLException("Render-to-texture-rectangle pbuffers not supported yet on X11");
-      }
-
       // Create the p-buffer.
       int niattribs = 0;
       IntBuffer iattributes = Buffers.newDirectIntBuffer(7);
@@ -131,12 +122,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
       ms.setSurfaceHandle(pbuffer);
 
       if (DEBUG) {
-        System.err.println("Created pbuffer " + this);
+        System.err.println(getThreadName()+": Created pbuffer " + this);
       }
   }
-
-  public int getFloatingPointMode() {
-    // Floating-point pbuffers currently require NVidia hardware on X11
-    return GLPbuffer.NV_FLOAT;
-  }
 }
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
deleted file mode 100644
index 96d0f18..0000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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 jogamp.opengl.x11.glx;
-
-import javax.media.opengl.*;
-
-public class X11PixmapGLXContext extends X11GLXContext {
-
-  public X11PixmapGLXContext(X11PixmapGLXDrawable drawable,
-                               GLContext shareWith) {
-    super(drawable, shareWith);
-  }
-
-  @Override
-  public int getOffscreenContextPixelDataType() {
-    GL gl = getGL();
-    return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
-  }
-
-  @Override
-  public int getOffscreenContextReadBuffer() {
-    GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities();
-    if (caps.getDoubleBuffered()) {
-      return GL.GL_BACK;
-    }
-    return GL.GL_FRONT;
-  }
-
-  @Override
-  public boolean offscreenImageNeedsVerticalFlip() {
-    // There doesn't seem to be a way to do this in the construction
-    // of the Pixmap or GLXPixmap
-    return true;
-  }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
index 0462772..c1388db 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
@@ -69,7 +69,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
 
   @Override
   public GLContext createContext(GLContext shareWith) {
-    return new X11PixmapGLXContext(this, shareWith);
+    return new X11GLXContext(this, shareWith);
   }
 
   private void createPixmap() {
@@ -95,7 +95,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
     }
     ((MutableSurface)ns).setSurfaceHandle(drawable);
     if (DEBUG) {
-        System.err.println("Created pixmap " + toHexString(pixmap) +
+        System.err.println(getThreadName()+": Created pixmap " + toHexString(pixmap) +
                            ", GLXPixmap " + toHexString(drawable) +
                            ", display " + toHexString(dpy));
     }
@@ -109,7 +109,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
 
     long drawable = ns.getSurfaceHandle();
     if (DEBUG) {
-        System.err.println("Destroying pixmap " + toHexString(pixmap) +
+        System.err.println(getThreadName()+": Destroying pixmap " + toHexString(pixmap) +
                            ", GLXPixmap " + toHexString(drawable) +
                            ", display " + toHexString(display));
     }
diff --git a/src/jogl/native/JoglCommon.c b/src/jogl/native/JoglCommon.c
index d9f5edd..62dd8ef 100644
--- a/src/jogl/native/JoglCommon.c
+++ b/src/jogl/native/JoglCommon.c
@@ -149,3 +149,25 @@ Java_jogamp_opengl_GLContextImpl_glGetStringInt(JNIEnv *env, jclass _unused, jin
   return (*env)->NewStringUTF(env, _res);
 }
 
+/*
+ * Class:     jogamp_opengl_GLContextImpl
+ * Method:    glGetIntegervInt
+ * Signature: (ILjava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL 
+Java_jogamp_opengl_GLContextImpl_glGetIntegervInt(JNIEnv *env, jclass _unused, jint pname, jobject params, jint params_byte_offset, jlong procAddress) {
+  typedef void (KHRONOS_APIENTRY*_local_PFNGLGETINTEGERVPROC)(unsigned int pname, int * params);
+
+  _local_PFNGLGETINTEGERVPROC ptr_glGetIntegerv;
+  int * _params_ptr = NULL;
+  if ( NULL != params ) {
+    _params_ptr = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, params, NULL) ) + params_byte_offset);
+  }
+  ptr_glGetIntegerv = (_local_PFNGLGETINTEGERVPROC) (intptr_t) procAddress;
+  assert(ptr_glGetIntegerv != NULL);
+  (* ptr_glGetIntegerv) ((unsigned int) pname, (int *) _params_ptr);
+  if ( NULL != params ) {
+    (*env)->ReleasePrimitiveArrayCritical(env, params, _params_ptr, 0);
+  }
+}
+
diff --git a/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c b/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c
index 7fb64da..28e9e85 100644
--- a/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c
+++ b/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c
@@ -638,7 +638,7 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNex
                 const AVRational time_base = pAV->pVStream->time_base;
                 const int64_t pts = pAV->pVFrame->pkt_pts;
                 if(AV_NOPTS_VALUE != pts) { // discard invalid PTS ..
-                    pAV->vPTS = pts * my_av_q2i32(1000, time_base);
+                    pAV->vPTS = (pts * (int64_t) 1000 * (int64_t) time_base.num) / (int64_t) time_base.den ;
 
                     #if 0
                     printf("PTS %d = %ld * ( ( 1000 * %ld ) / %ld ) '1000 * time_base', time_base = %lf\n",
@@ -689,14 +689,16 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_seek0
     FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr));
     int64_t pos0 = pAV->vPTS;
     int64_t pts0 = pAV->pVFrame->pkt_pts;
-    int64_t pts1 = (int64_t) pos1 / my_av_q2i32(1000, pAV->pVStream->time_base);
+    int64_t pts1 = (int64_t) (pos1 * (int64_t) pAV->pVStream->time_base.den)
+                             / (1000 * (int64_t) pAV->pVStream->time_base.num);
     int flags = 0;
     if(pos1 < pos0) {
         flags |= AVSEEK_FLAG_BACKWARD;
     }
     fprintf(stderr, "SEEK: pre  : u %ld, p %ld -> u %ld, p %ld\n", pos0, pts0, pos1, pts1);
     sp_av_seek_frame(pAV->pFormatCtx, pAV->vid, pts1, flags);
-    pAV->vPTS = pAV->pVFrame->pkt_pts * my_av_q2i32(1000, pAV->pVStream->time_base);
+    pAV->vPTS = (int64_t) (pAV->pVFrame->pkt_pts * (int64_t) 1000 * (int64_t) pAV->pVStream->time_base.num)
+                / (int64_t) pAV->pVStream->time_base.den;
     fprintf(stderr, "SEEK: post : u %ld, p %ld\n", pAV->vPTS, pAV->pVFrame->pkt_pts);
     return pAV->vPTS;
 }
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
index 6ebf400..046171e 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
@@ -1,6 +1,7 @@
 #import "MacOSXWindowSystemInterface.h"
 #import <QuartzCore/QuartzCore.h>
 #import <pthread.h>
+#import "NativeWindowProtocols.h"
 #include "timespec.h"
 
 #import <OpenGL/glext.h>
@@ -41,6 +42,8 @@ extern GLboolean glIsVertexArray (GLuint array);
 //
 // #define DBG_PERF 1
 
+// #define DBG_LIFECYCLE 1
+
 /**
  * Capture setView(NULL), which produces a 'invalid drawable' message
  *
@@ -52,6 +55,10 @@ extern GLboolean glIsVertexArray (GLuint array);
 - (id)initWithFormat:(NSOpenGLPixelFormat *)format shareContext:(NSOpenGLContext *)share;
 - (void)setView:(NSView *)view;
 - (void)update;
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+#endif
 - (void)dealloc;
 
 @end
@@ -60,44 +67,97 @@ extern GLboolean glIsVertexArray (GLuint array);
 
 - (id)initWithFormat:(NSOpenGLPixelFormat *)format shareContext:(NSOpenGLContext *)share
 {
-    DBG_PRINT("MyNSOpenGLContext.initWithFormat.0: format %p, share %p\n", format, share);
+    DBG_PRINT("MyNSOpenGLContext::initWithFormat.0: format %p, share %p\n", format, share);
     MyNSOpenGLContext * o = [super initWithFormat:format shareContext:share];
-    DBG_PRINT("MyNSOpenGLContext.initWithFormat.X: new %p\n", o);
+    DBG_PRINT("MyNSOpenGLContext::initWithFormat.X: new %p\n", o);
     return o;
 }
 
 - (void)setView:(NSView *)view
 {
-    DBG_PRINT("MyNSOpenGLContext.setView: this.0 %p, view %p\n", self, view);
+    DBG_PRINT("MyNSOpenGLContext::setView: this.0 %p, view %p\n", self, view);
+    // NSLog(@"MyNSOpenGLContext::setView: %@",[NSThread callStackSymbols]);
     if(NULL != view) {
         [super setView:view];
+    } else {
+        [self clearDrawable];
     }
-    DBG_PRINT("MyNSOpenGLContext.setView.X\n");
+    DBG_PRINT("MyNSOpenGLContext::setView.X\n");
 }
 
 - (void)update
 {
-    DBG_PRINT("MyNSOpenGLContext.update: this.0 %p, view %p\n", self, [self view]);
+    DBG_PRINT("MyNSOpenGLContext::update: this.0 %p, view %p\n", self, [self view]);
     [super update];
-    DBG_PRINT("MyNSOpenGLContext.update.X\n");
+    DBG_PRINT("MyNSOpenGLContext::update.X\n");
+}
+
+#ifdef DBG_LIFECYCLE
+
+- (id)retain
+{
+    DBG_PRINT("MyNSOpenGLContext::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+    // NSLog(@"MyNSOpenGLContext::retain: %@",[NSThread callStackSymbols]);
+    id o = [super retain];
+    DBG_PRINT("MyNSOpenGLContext::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+    return o;
 }
 
+- (oneway void)release
+{
+    DBG_PRINT("MyNSOpenGLContext::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+    [super release];
+    // DBG_PRINT("MyNSOpenGLContext::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+#endif
+
+#ifdef VERBOSE_ON
+    #define CGLRETAINCOUNT(c) (NULL!=c?(int)CGLGetContextRetainCount(c):-1)
+#else
+    #define CGLRETAINCOUNT(c)
+#endif
+
 - (void)dealloc
 {
-    DBG_PRINT("MyNSOpenGLContext.dealloc: this.0 %p\n", self);
+    /**
+     * The explicit CGLContext destruction below
+     * ensures that it is not left behind.
+     * Tests show that w/o these gymnastics, the CGLContext is not freed immediately after calling dealloc.
+     * The retain, release and dealloc ensures [super dealloc] won't message 'invalid context'.
+     */
+    CGLContextObj cglCtx = [self CGLContextObj];
+
+    DBG_PRINT("MyNSOpenGLContext::dealloc.0 %p (refcnt %d) - CGL-Ctx %p\n", self, (int)[self retainCount], cglCtx, CGLRETAINCOUNT(cglCtx));
+    // NSLog(@"MyNSOpenGLContext::dealloc: %@",[NSThread callStackSymbols]);
+
+    [self clearDrawable];
+    DBG_PRINT("MyNSOpenGLContext::dealloc.1 %d\n", CGLRETAINCOUNT(cglCtx));
+    if( NULL != cglCtx ) {
+        CGLRetainContext( cglCtx );
+        DBG_PRINT("MyNSOpenGLContext::dealloc.2 %d\n", CGLRETAINCOUNT(cglCtx));
+    }
     [super dealloc];
-    DBG_PRINT("MyNSOpenGLContext.dealloc.X: %p\n", self);
+    DBG_PRINT("MyNSOpenGLContext::dealloc.3 %d\n", CGLRETAINCOUNT(cglCtx));
+    if( NULL != cglCtx ) {
+        CGLReleaseContext( cglCtx );
+        DBG_PRINT("MyNSOpenGLContext::dealloc.4 %d\n", CGLRETAINCOUNT(cglCtx));
+        CGLDestroyContext( cglCtx );
+        DBG_PRINT("MyNSOpenGLContext::dealloc.5 %d\n", CGLRETAINCOUNT(cglCtx));
+    }
+    DBG_PRINT("MyNSOpenGLContext::dealloc.X\n");
 }
 
 @end
 
- at interface MyNSOpenGLLayer: NSOpenGLLayer
+ at interface MyNSOpenGLLayer: NSOpenGLLayer <NWDedicatedSize>
 {
 @private
     GLfloat gl_texCoords[8];
+    NSOpenGLContext* glContext;
+    Bool isGLEnabled;
 
 @protected
-    NSOpenGLContext* parentCtx;
     GLuint gl3ShaderProgramName;
     GLuint vboBufVert;
     GLuint vboBufTexCoord;
@@ -106,8 +166,8 @@ extern GLboolean glIsVertexArray (GLuint array);
     NSOpenGLPixelFormat* parentPixelFmt;
     int texWidth;
     int texHeight;
-    int newTexWidth;
-    int newTexHeight;
+    volatile int dedicatedWidth;
+    volatile int dedicatedHeight;
     volatile NSOpenGLPixelBuffer* pbuffer;
     volatile GLuint textureID;
     volatile NSOpenGLPixelBuffer* newPBuffer;
@@ -136,25 +196,38 @@ extern GLboolean glIsVertexArray (GLuint array);
        texWidth: (int) texWidth 
        texHeight: (int) texHeight;
 
-- (Bool) validateTexSizeWithNewSize;
-- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight;
+- (void)releaseLayer;
+- (void)deallocPBuffer;
+- (void)disableAnimation;
+- (void)pauseAnimation:(Bool)pause;
+- (void)setSwapInterval:(int)interval;
+- (void)tick;
+- (void)waitUntilRenderSignal: (long) to_micros;
+- (Bool)isGLSourceValid;
+
+- (void) setGLEnabled: (Bool) enable;
+- (Bool) validateTexSizeWithDedicatedSize;
 - (void) setTextureID: (int) _texID;
 
 - (Bool) isSamePBuffer: (NSOpenGLPixelBuffer*) p;
 - (void) setNewPBuffer: (NSOpenGLPixelBuffer*)p;
 - (void) applyNewPBuffer;
 
+- (void)setDedicatedSize:(CGSize)size; // @NWDedicatedSize
+- (void) setFrame:(CGRect) frame;
+- (id<CAAction>)actionForKey:(NSString *)key ;
 - (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask;
 - (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat;
-- (void)disableAnimation;
-- (void)pauseAnimation:(Bool)pause;
-- (void)deallocPBuffer;
-- (void)releaseLayer;
+- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
+        forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp;
+- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
+        forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp;
+
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+#endif
 - (void)dealloc;
-- (void)setSwapInterval:(int)interval;
-- (void)tick;
-- (void)waitUntilRenderSignal: (long) to_micros;
-- (Bool)isGLSourceValid;
 
 @end
 
@@ -194,7 +267,7 @@ static const GLfloat gl_verts[] = {
 
 @implementation MyNSOpenGLLayer
 
-- (id) setupWithContext: (NSOpenGLContext*) _parentCtx
+- (id) setupWithContext: (NSOpenGLContext*) parentCtx
        gl3ShaderProgramName: (GLuint) _gl3ShaderProgramName
        pixelFormat: (NSOpenGLPixelFormat*) _parentPixelFmt
        pbuffer: (NSOpenGLPixelBuffer*) p
@@ -215,20 +288,21 @@ static const GLfloat gl_verts[] = {
             gl_texCoords[i] = 0.0f;
         }
     }
-    parentCtx = _parentCtx;
+    parentPixelFmt = [_parentPixelFmt retain]; // until destruction
+    glContext = [[MyNSOpenGLContext alloc] initWithFormat:parentPixelFmt shareContext:parentCtx];
     gl3ShaderProgramName = _gl3ShaderProgramName;
     vboBufVert = 0;
     vboBufTexCoord = 0;
     vertAttrLoc = 0;
     texCoordAttrLoc = 0;
-    parentPixelFmt = _parentPixelFmt;
     swapInterval = 1; // defaults to on (as w/ new GL profiles)
     swapIntervalCounter = 0;
     timespec_now(&lastWaitTime);
     shallDraw = NO;
-    newTexWidth = _texWidth;
-    newTexHeight = _texHeight;
-    [self validateTexSizeWithNewSize];
+    isGLEnabled = YES;
+    dedicatedWidth = _texWidth;
+    dedicatedHeight = _texHeight;
+    [self validateTexSizeWithDedicatedSize];
     [self setTextureID: texID];
 
     newPBuffer = NULL;
@@ -265,10 +339,11 @@ static const GLfloat gl_verts[] = {
         }
     }
     if(NULL != displayLink) {
-        cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [parentCtx CGLContextObj], [parentPixelFmt CGLPixelFormatObj]);
+        CVReturn cvres;
+        DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.1: setup DisplayLink %p\n", displayLink);
+        cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [glContext CGLContextObj], [parentPixelFmt CGLPixelFormatObj]);
         if(kCVReturnSuccess != cvres) {
             DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres);
-            displayLink = NULL;
         }
     }
     if(NULL != displayLink) {
@@ -290,34 +365,29 @@ static const GLfloat gl_verts[] = {
 #ifdef VERBOSE_ON
     CGRect lRect = [self bounds];
     if(NULL != pbuffer) {
-        DBG_PRINT("MyNSOpenGLLayer::init (pbuffer) %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d, bounds: %lf/%lf %lfx%lf (refcnt %d)\n", 
-            self, parentCtx, parentPixelFmt, pbuffer, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight,
-            lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]);
+        DBG_PRINT("MyNSOpenGLLayer::init (pbuffer) %p, pctx %p, pfmt %p, pbuffer %p, ctx %p, opaque %d, pbuffer %dx%d -> tex %dx%d, bounds: %lf/%lf %lfx%lf, displayLink %p (refcnt %d)\n", 
+            self, parentCtx, parentPixelFmt, pbuffer, glContext, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight,
+            lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, displayLink, (int)[self retainCount]);
     } else {
-        DBG_PRINT("MyNSOpenGLLayer::init (texture) %p, ctx %p, pfmt %p, opaque %d, tex[id %d, %dx%d], bounds: %lf/%lf %lfx%lf (refcnt %d)\n", 
-            self, parentCtx, parentPixelFmt, opaque, (int)textureID, texWidth, texHeight,
-            lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]);
+        DBG_PRINT("MyNSOpenGLLayer::init (texture) %p, pctx %p, pfmt %p, ctx %p, opaque %d, tex[id %d, %dx%d], bounds: %lf/%lf %lfx%lf, displayLink %p (refcnt %d)\n", 
+            self, parentCtx, parentPixelFmt, glContext, opaque, (int)textureID, texWidth, texHeight,
+            lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, displayLink, (int)[self retainCount]);
     }
 #endif
     return self;
 }
 
-- (Bool) validateTexSizeWithNewSize
+- (void) setGLEnabled: (Bool) enable
 {
-    return [self validateTexSize: newTexWidth texHeight: newTexHeight];
+    DBG_PRINT("MyNSOpenGLLayer::setGLEnabled: %p, %d -> %d\n", self, (int)isGLEnabled, (int)enable);
+    isGLEnabled = enable;
 }
 
-- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight
+- (Bool) validateTexSizeWithDedicatedSize
 {
-    if(_texHeight != texHeight || _texWidth != texWidth) {
-        texWidth = _texWidth;
-        texHeight = _texHeight;
-        CGRect lRect = [self bounds];
-        lRect.origin.x = 0;
-        lRect.origin.y = 0;
-        lRect.size.width = texWidth;
-        lRect.size.height = texHeight;
-        [self setFrame: lRect];
+    if( dedicatedHeight != texHeight || dedicatedWidth != texWidth ) {
+        texWidth = dedicatedWidth;
+        texHeight = dedicatedHeight;
 
         GLfloat texCoordWidth, texCoordHeight;
         if(NULL != pbuffer) {
@@ -339,6 +409,12 @@ static const GLfloat gl_verts[] = {
         gl_texCoords[5] = texCoordHeight;
         gl_texCoords[4] = texCoordWidth;
         gl_texCoords[6] = texCoordWidth;
+#ifdef VERBOSE_ON
+        CGRect lRect = [self bounds];
+        DBG_PRINT("MyNSOpenGLLayer::validateTexSize %p -> tex %dx%d, bounds: %lf/%lf %lfx%lf\n", 
+            self, texWidth, texHeight,
+            lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height);
+#endif
         return YES;
     } else {
         return NO;
@@ -407,26 +483,9 @@ static const GLfloat gl_verts[] = {
     }
 }
 
-- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask
-{
-    DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask: %p (refcnt %d) - parent-pfmt %p -> new-pfmt %p\n", 
-        self, (int)[self retainCount], parentPixelFmt, parentPixelFmt);
-    return parentPixelFmt;
-}
-
-- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat
-{
-    DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.0: %p (refcnt %d) - pfmt %p, parent %p\n",
-        self, (int)[self retainCount], pixelFormat, parentCtx);
-    NSOpenGLContext * nctx = [[MyNSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:parentCtx];
-    DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.X: new-ctx %p\n", nctx);
-    return nctx;
-}
-
 - (void)disableAnimation
 {
-    DBG_PRINT("MyNSOpenGLLayer::disableAnimation: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink);
-    pthread_mutex_lock(&renderLock);
+    DBG_PRINT("MyNSOpenGLLayer::disableAnimation.0: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink);
     [self setAsynchronous: NO];
     if(NULL != displayLink) {
 #ifdef HAS_CADisplayLink
@@ -438,34 +497,62 @@ static const GLfloat gl_verts[] = {
 #endif
         displayLink = NULL;
     }
-    pthread_mutex_unlock(&renderLock);
+    DBG_PRINT("MyNSOpenGLLayer::disableAnimation.X: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink);
 }
 
 - (void)releaseLayer
 {
     DBG_PRINT("MyNSOpenGLLayer::releaseLayer.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
-    pthread_mutex_lock(&renderLock);
+    [self setGLEnabled: NO];
     [self disableAnimation];
+    pthread_mutex_lock(&renderLock);
     [self deallocPBuffer];
-    [[self openGLContext] release];
-    [self release];
-    DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+    if( NULL != glContext ) {
+        [glContext release];
+        glContext = NULL;
+    }
+    if( NULL != parentPixelFmt ) {
+        [parentPixelFmt release];
+        parentPixelFmt = NULL;
+    }
     pthread_mutex_unlock(&renderLock);
+    [self release];
+    DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p\n", self);
+}
+
+#ifdef DBG_LIFECYCLE
+
+- (id)retain
+{
+    DBG_PRINT("MyNSOpenGLLayer::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+    // NSLog(@"MyNSOpenGLLayer::retain: %@",[NSThread callStackSymbols]);
+    id o = [super retain];
+    DBG_PRINT("MyNSOpenGLLayer::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+    return o;
 }
 
+- (oneway void)release
+{
+    DBG_PRINT("MyNSOpenGLLayer::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+    // NSLog(@"MyNSOpenGLLayer::release: %@",[NSThread callStackSymbols]);
+    [super release];
+    // DBG_PRINT("MyNSOpenGLLayer::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+#endif
+
 - (void)dealloc
 {
     DBG_PRINT("MyNSOpenGLLayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
     // NSLog(@"MyNSOpenGLLayer::dealloc: %@",[NSThread callStackSymbols]);
-
-    pthread_mutex_lock(&renderLock);
     [self disableAnimation];
+    pthread_mutex_lock(&renderLock);
     [self deallocPBuffer];
     pthread_mutex_unlock(&renderLock);
     pthread_cond_destroy(&renderSignal);
     pthread_mutex_destroy(&renderLock);
     [super dealloc];
-    DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self);
+    // DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self);
 }
 
 - (Bool)isGLSourceValid
@@ -473,26 +560,50 @@ static const GLfloat gl_verts[] = {
     return NULL != pbuffer || NULL != newPBuffer || 0 != textureID ;
 }
 
-- (void)resizeWithOldSuperlayerSize:(CGSize)size
- {
-    CGRect lRectS = [[self superlayer] bounds];
+// @NWDedicatedSize
+- (void)setDedicatedSize:(CGSize)size {
+    DBG_PRINT("MyNSOpenGLLayer::setDedicatedSize: %p, texSize %dx%d <- %lfx%lf\n",
+        self, texWidth, texHeight, size.width, size.height);
+    
+    dedicatedWidth = size.width;
+    dedicatedHeight = size.height;
+
+    CGRect rect = CGRectMake(0, 0, dedicatedWidth, dedicatedHeight); 
+    [super setFrame: rect];
+}
 
-    DBG_PRINT("MyNSOpenGLLayer::resizeWithOldSuperlayerSize: %p, texSize %dx%d, bounds: %lfx%lf -> %lfx%lf (refcnt %d)\n", 
-        self, texWidth, texHeight, size.width, size.height, lRectS.size.width, lRectS.size.height, (int)[self retainCount]);
+- (void) setFrame:(CGRect) frame {
+    CGRect rect = CGRectMake(0, 0, dedicatedWidth, dedicatedHeight); 
+    [super setFrame: rect];
+}
 
-    newTexWidth = lRectS.size.width;
-    newTexHeight = lRectS.size.height;
-    shallDraw = [self isGLSourceValid];
-    SYNC_PRINT("<SZ %dx%d>", newTexWidth, newTexHeight);
+- (id<CAAction>)actionForKey:(NSString *)key
+{
+    DBG_PRINT("MyNSOpenGLLayer::actionForKey.0 %p key %s -> NIL\n", self, [key UTF8String]);
+    return nil;
+    // return [super actionForKey: key];
+}
 
-    [super resizeWithOldSuperlayerSize: size];
+- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask
+{
+    DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask: %p (refcnt %d) - parent-pfmt %p -> new-pfmt %p\n", 
+        self, (int)[self retainCount], parentPixelFmt, parentPixelFmt);
+    // We simply take over ownership of parent PixelFormat until releaseLayer..
+    return parentPixelFmt;
+}
+
+- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat
+{
+    DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat.0: %p (refcnt %d) - pfmt %p, ctx %p, DisplayLink %p\n",
+        self, (int)[self retainCount], pixelFormat, glContext, displayLink);
+    return glContext;
 }
 
 - (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat 
         forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
 {
-    SYNC_PRINT("<? %d>", (int)shallDraw);
-    return shallDraw;
+    SYNC_PRINT("<? %d, %d>", (int)shallDraw, (int)isGLEnabled);
+    return shallDraw && isGLEnabled;
 }
 
 - (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat 
@@ -502,7 +613,7 @@ static const GLfloat gl_verts[] = {
     SYNC_PRINT("<* ");
     // NSLog(@"MyNSOpenGLLayer::DRAW: %@",[NSThread callStackSymbols]);
 
-    if( shallDraw && ( NULL != pbuffer || NULL != newPBuffer || 0 != textureID ) ) {
+    if( isGLEnabled && shallDraw && ( NULL != pbuffer || NULL != newPBuffer || 0 != textureID ) ) {
         [context makeCurrentContext];
 
         if( NULL != newPBuffer ) { // volatile OK
@@ -511,7 +622,10 @@ static const GLfloat gl_verts[] = {
 
         GLenum textureTarget;
 
-        Bool texSizeChanged = [self validateTexSizeWithNewSize];
+        Bool texSizeChanged = [self validateTexSizeWithDedicatedSize];
+        if( texSizeChanged ) {
+            [context update];
+        }
 
         if( NULL != pbuffer ) {
             if( texSizeChanged && 0 != textureID ) {
@@ -704,46 +818,39 @@ static const GLfloat gl_verts[] = {
 
 - (void)waitUntilRenderSignal: (long) to_micros
 {
-    BOOL ready = NO;
-    int wr = 0;
+    struct timespec t0, to_until;
+    BOOL tooLate;
+    int wr;
+    if( 0 >= to_micros ) {
+        to_micros = 16666 + 1000; // defaults to 1/60s + 1ms
+        NSLog(@"MyNSOpenGLContext::waitUntilRenderSignal: to_micros was zero, using defaults");
+    }
     pthread_mutex_lock(&renderLock);
-    SYNC_PRINT("{W %ld us", to_micros);
-    do {
-        if(0 >= swapInterval) {
-            ready = YES;
-        }
-        if(NO == ready) {
-            #ifdef DBG_SYNC
-                struct timespec t0, t1, td, td2;
-                timespec_now(&t0);
-            #endif
-            if(0 < to_micros) {
-                struct timespec to_abs = lastWaitTime;
-                timespec_addmicros(&to_abs, to_micros);
-                #ifdef DBG_SYNC
-                    timespec_subtract(&td, &to_abs, &t0);
-                    fprintf(stderr, ", (%ld) / ", timespec_milliseconds(&td));
-                #endif
-                wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_abs);
-                #ifdef DBG_SYNC
-                    timespec_now(&t1);
-                    timespec_subtract(&td, &t1, &t0);
-                    timespec_subtract(&td2, &t1, &lastWaitTime);
-                    fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
-                #endif
-            } else {
-                pthread_cond_wait (&renderSignal, &renderLock);
-                #ifdef DBG_SYNC
-                    timespec_now(&t1);
-                    timespec_subtract(&td, &t1, &t0);
-                    timespec_subtract(&td2, &t1, &lastWaitTime);
-                    fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
-                #endif
-            }
-            ready = YES;
+    timespec_now(&t0);
+    to_until = lastWaitTime;
+    timespec_addmicros(&to_until, to_micros);
+    tooLate = timespec_compare(&to_until, &t0) < 0;
+    #ifdef DBG_SYNC
+        struct timespec td_until;
+        timespec_subtract(&td_until, &to_until, &t0);
+        SYNC_PRINT("{W %ld ms, to %ld ms, late %d", to_micros/1000, timespec_milliseconds(&td_until), tooLate);
+    #endif
+    if( 0 < swapInterval ) {
+        if( tooLate ) {
+            // adjust!
+            to_until = t0;
+            timespec_addmicros(&to_until, to_micros);
         }
-    } while (NO == ready && 0 == wr) ;
-    SYNC_PRINT("-%d-%d-%d}", shallDraw, wr, ready);
+        wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_until);
+        #ifdef DBG_SYNC
+            struct timespec t1, td, td2;
+            timespec_now(&t1);
+            timespec_subtract(&td, &t1, &t0);
+            timespec_subtract(&td2, &t1, &lastWaitTime);
+            fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
+        #endif
+    }
+    SYNC_PRINT("-%d-%d}\n", shallDraw, wr);
     timespec_now(&lastWaitTime);
     pthread_mutex_unlock(&renderLock);
 }
@@ -751,32 +858,34 @@ static const GLfloat gl_verts[] = {
 @end
 
 NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, int gl3ShaderProgramName, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight) {
-  // This simply crashes after dealloc() has been called .. ie. ref-count -> 0 too early ?
-  // However using alloc/init, actual dealloc happens at JAWT destruction, hence too later IMHO.
-  // return [[MyNSOpenGLLayer layer] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID
-  //                                                      opaque: opaque texWidth: texWidth texHeight: texHeight];
-
   return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx gl3ShaderProgramName: (GLuint)gl3ShaderProgramName pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID
                                                               opaque: opaque texWidth: texWidth texHeight: texHeight];
 }
+ 
+void setNSOpenGLLayerEnabled(NSOpenGLLayer* layer, Bool enable) {
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
+    [l setGLEnabled: enable];
+    [pool release];
+}
 
 void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval) {
-    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
     [l setSwapInterval: interval];
     [pool release];
 }
 
 void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros) {
-    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
     [l waitUntilRenderSignal: to_micros];
     [pool release];
 }
 
 void setNSOpenGLLayerNeedsDisplayFBO(NSOpenGLLayer* layer, uint32_t texID) {
-    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
     Bool shallDraw;
 
     // volatile OK
@@ -798,8 +907,8 @@ void setNSOpenGLLayerNeedsDisplayFBO(NSOpenGLLayer* layer, uint32_t texID) {
 }
 
 void setNSOpenGLLayerNeedsDisplayPBuffer(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p) {
-    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
     Bool shallDraw;
 
     if( NO == [l isSamePBuffer: p] ) {
@@ -824,17 +933,18 @@ void setNSOpenGLLayerNeedsDisplayPBuffer(NSOpenGLLayer* layer, NSOpenGLPixelBuff
 }
 
 void releaseNSOpenGLLayer(NSOpenGLLayer* layer) {
-    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-    DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l);
+    MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer;
 
-    if ( [NSThread isMainThread] == YES ) {
-        [l releaseLayer];
-    } else { 
-        [l performSelectorOnMainThread:@selector(releaseLayer) withObject:nil waitUntilDone:NO];
-    }
+    [CATransaction begin];
+    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
 
+    DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l);
+    [l releaseLayer];
     DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.X: %p\n", l);
+
+    [CATransaction commit];
+
     [pool release];
 }
 
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
index 48807ee..d4d3dda 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m
@@ -501,6 +501,28 @@ NSView* getNSView(NSOpenGLContext* ctx) {
   return view;
 }
 
+static Bool lockViewIfReady(NSView *view) {
+    Bool viewReady = false;
+
+    if (view != nil) {
+        if ([view lockFocusIfCanDraw] == NO) {
+            DBG_PRINT("lockViewIfReady.1 [view lockFocusIfCanDraw] failed\n");
+        } else {
+            NSRect frame = [view frame];
+            if ((frame.size.width == 0) || (frame.size.height == 0)) {
+                [view unlockFocus];
+                DBG_PRINT("lockViewIfReady.2 view.frame size %dx%d\n", (int)frame.size.width, (int)frame.size.height);
+            } else {
+                DBG_PRINT("lockViewIfReady.X ready and locked\n");
+                viewReady = true;
+            }
+        }
+    } else {
+        DBG_PRINT("lockViewIfReady.3 nil view\n");
+    }
+    return viewReady;
+}
+
 NSOpenGLContext* createContext(NSOpenGLContext* share,
                     NSView* view,
                     Bool incompleteView,
@@ -515,55 +537,29 @@ NSOpenGLContext* createContext(NSOpenGLContext* share,
     DBG_PRINT("createContext.0: share %p, view %p, incompleteView %d, pixfmt %p, opaque %d\n",
         share, view, (int)incompleteView, fmt, opaque);
 
-    if (view != nil) {
-        Bool viewReady = true;
+    Bool viewReadyAndLocked = incompleteView ? false : lockViewIfReady(view);
 
-        if(!incompleteView) {
-            if ([view lockFocusIfCanDraw] == NO) {
-                DBG_PRINT("createContext.1 [view lockFocusIfCanDraw] failed\n");
-                viewReady = false;
-            }
-        }
-        if(viewReady) {
-            NSRect frame = [view frame];
-            if ((frame.size.width == 0) || (frame.size.height == 0)) {
-                if(!incompleteView) {
-                    [view unlockFocus];
-                }
-                DBG_PRINT("createContext.2 view.frame size %dx%d\n", (int)frame.size.width, (int)frame.size.height);
-                viewReady = false;
-            }
-        }
-
-        if (!viewReady)
-        {
-            if (viewNotReady != NULL)
-            {
-                *viewNotReady = 1;
-            }
+    if (nil != viewNotReady) {
+        *viewNotReady = 1;
+    }
 
-            // the view is not ready yet
-            DBG_PRINT("createContext.X: view not ready yet\n");
-            [pool release];
-            return NULL;
-        }
+    if (nil != view && !incompleteView && !viewReadyAndLocked) {
+        DBG_PRINT("createContext.X: Assumed complete view not ready yet\n");
+        [pool release];
+        return NULL;
     }
-    
+
     NSOpenGLContext* ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:share];
         
-    if (ctx != nil) {
-      if (view != nil) {
+    if ( nil != ctx && nil != view ) {
         if(!opaque) {
             GLint zeroOpacity = 0;
             [ctx setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity];
         }
-        if(!incompleteView) {
-            DBG_PRINT("createContext.3.0: setView\n");
+        if( viewReadyAndLocked ) {
             [ctx setView:view];
-            DBG_PRINT("createContext.3.X: setView\n");
             [view unlockFocus];        
         }
-      }
     }
 
     DBG_PRINT("createContext.X: ctx: %p\n", ctx);
@@ -571,6 +567,32 @@ NSOpenGLContext* createContext(NSOpenGLContext* share,
     return ctx;
 }
 
+void setContextView(NSOpenGLContext* ctx, NSView* view) {
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    if ( nil != ctx ) {
+        if ( nil != view ) {
+            Bool viewReadyAndLocked = lockViewIfReady(view);
+            DBG_PRINT("setContextView.0: ctx %p, view %p: setView: %d\n", ctx, view, viewReadyAndLocked);
+            if( viewReadyAndLocked ) {
+                [ctx setView:view];
+                [view unlockFocus];        
+            }
+        }
+        DBG_PRINT("setContextView.X\n");
+    }
+    [pool release];
+}
+
+void clearDrawable(NSOpenGLContext* ctx) {
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    if ( nil != ctx ) {
+        DBG_PRINT("clearDrawable.0: %p\n", ctx);
+        [ctx clearDrawable];
+        DBG_PRINT("clearDrawable.X\n");
+    }
+    [pool release];
+}
+
 Bool makeCurrentContext(NSOpenGLContext* ctx) {
 #if 0
   // we issue the CGL Lock from Java upfront!
@@ -719,7 +741,7 @@ void setContextTextureImageToPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer*
 Bool isNSOpenGLPixelBuffer(uint64_t object) {
   NSObject *nsObj = (NSObject*) (intptr_t) object;
   DBG_PRINT("isNSOpenGLPixelBuffer.0: obj %p\n", object);
-  Bool res = [nsObj isMemberOfClass:[NSOpenGLPixelBuffer class]];
+  Bool res = [nsObj isKindOfClass:[NSOpenGLPixelBuffer class]];
   DBG_PRINT("isNSOpenGLPixelBuffer.X: res %d\n", (int)res);
   return res;
 }
diff --git a/src/jogl/native/timespec.c b/src/jogl/native/timespec.c
index 50f0ca8..a69f463 100644
--- a/src/jogl/native/timespec.c
+++ b/src/jogl/native/timespec.c
@@ -75,3 +75,8 @@ long timespec_milliseconds(struct timespec *a)
 {
     return a->tv_sec*1000 + a->tv_nsec/1000000;
 }
+
+long timespec_microseconds(struct timespec *a) 
+{
+    return a->tv_sec*1000000 + a->tv_nsec/1000;
+}
diff --git a/src/jogl/native/timespec.h b/src/jogl/native/timespec.h
index f900bfa..a621562 100644
--- a/src/jogl/native/timespec.h
+++ b/src/jogl/native/timespec.h
@@ -17,4 +17,7 @@ void timespec_subtract(struct timespec *r, struct timespec *a, struct timespec *
 /** convert the timespec into milliseconds (may overflow) */
 long timespec_milliseconds(struct timespec *a);
 
+/** convert the timespec into microseconds (may overflow) */
+long timespec_microseconds(struct timespec *a);
+
 #endif /* _timespec_h */
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/MutableGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/MutableGraphicsConfiguration.java
index 2d5af86..eaad513 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/MutableGraphicsConfiguration.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/MutableGraphicsConfiguration.java
@@ -37,7 +37,14 @@ public class MutableGraphicsConfiguration extends DefaultGraphicsConfiguration {
         super(screen, capsChosen, capsRequested);
     }
 
+    @Override
     public void setChosenCapabilities(CapabilitiesImmutable caps) {
         super.setChosenCapabilities(caps);
     }
+    
+    @Override
+    public void setScreen(AbstractGraphicsScreen screen) {
+        super.setScreen(screen);
+    }
+    
 }
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
index 38bd70a..29f4964 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
@@ -31,6 +31,7 @@ package com.jogamp.nativewindow;
 import com.jogamp.common.GlueGenVersion;
 import com.jogamp.common.util.JogampVersion;
 import com.jogamp.common.util.VersionUtil;
+
 import java.util.jar.Manifest;
 
 public class NativeWindowVersion extends JogampVersion {
@@ -45,9 +46,10 @@ public class NativeWindowVersion extends JogampVersion {
         if(null == jogampCommonVersionInfo) { // volatile: ok
             synchronized(NativeWindowVersion.class) {
                 if( null == jogampCommonVersionInfo ) {
-                    final String packageName = "javax.media.nativewindow";
-                    final Manifest mf = VersionUtil.getManifest(NativeWindowVersion.class.getClassLoader(), packageName);
-                    jogampCommonVersionInfo = new NativeWindowVersion(packageName, mf);
+                    final String packageName1 = "javax.media.nativewindow"; // atomic packaging - and identity
+                    final String packageName2 = "javax.media.opengl"; // all packaging
+                    final Manifest mf = VersionUtil.getManifest(NativeWindowVersion.class.getClassLoader(), new String[]{ packageName1, packageName2 } );
+                    jogampCommonVersionInfo = new NativeWindowVersion(packageName1, mf);
                 }
             }
         }
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
index 2a152ff..7e3d30a 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
@@ -74,8 +74,9 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple
   
   /**
    * @param capsChosen if null, <code>capsRequested</code> is copied and aligned 
-   *        with the graphics Capabilities of the AWT Component to produce the chosen Capabilities.
+   *        with the graphics {@link Capabilities} of the AWT Component to produce the chosen {@link Capabilities}.
    *        Otherwise the <code>capsChosen</code> is used.
+   * @param capsRequested if null, default {@link Capabilities} are used, otherwise the given values.
    */
   public static AWTGraphicsConfiguration create(Component awtComp, CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested) {
       final GraphicsConfiguration awtGfxConfig = awtComp.getGraphicsConfiguration();
@@ -91,6 +92,9 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple
       final AWTGraphicsDevice awtDevice = new AWTGraphicsDevice(awtGraphicsDevice, AbstractGraphicsDevice.DEFAULT_UNIT);
       final AWTGraphicsScreen awtScreen = new AWTGraphicsScreen(awtDevice);
 
+      if(null==capsRequested) {
+          capsRequested = new Capabilities();
+      }
       if(null==capsChosen) {
           GraphicsConfiguration gc = awtGraphicsDevice.getDefaultConfiguration();
           capsChosen = AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capsRequested, gc);
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java
index d78b4ac..e499ff7 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTWindowClosingProtocol.java
@@ -33,6 +33,7 @@ import java.awt.Window;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.awt.event.WindowListener;
+
 import javax.media.nativewindow.WindowClosingProtocol;
 
 import jogamp.nativewindow.awt.AWTMisc;
@@ -40,15 +41,22 @@ import jogamp.nativewindow.awt.AWTMisc;
 public class AWTWindowClosingProtocol implements WindowClosingProtocol {
 
   private Component comp;
-  private Runnable closingOperation;
-  private volatile boolean closingListenerSet = false;
+  private Runnable closingOperationClose;
+  private Runnable closingOperationNOP;
+  private boolean closingListenerSet = false;
   private Object closingListenerLock = new Object();
   private WindowClosingMode defaultCloseOperation = WindowClosingMode.DISPOSE_ON_CLOSE;
   private boolean defaultCloseOperationSetByUser = false;
 
-  public AWTWindowClosingProtocol(Component comp, Runnable closingOperation) {
+  /**
+   * @param comp mandatory AWT component which AWT Window is being queried by parent traversal
+   * @param closingOperationClose mandatory closing operation, triggered if windowClosing and {@link WindowClosingMode#DISPOSE_ON_CLOSE}
+   * @param closingOperationNOP optional closing operation, triggered if windowClosing and {@link WindowClosingMode#DO_NOTHING_ON_CLOSE}
+   */
+  public AWTWindowClosingProtocol(Component comp, Runnable closingOperationClose, Runnable closingOperationNOP) {
       this.comp = comp;
-      this.closingOperation = closingOperation;
+      this.closingOperationClose = closingOperationClose;
+      this.closingOperationNOP = closingOperationNOP;
   }
 
   class WindowClosingAdapter extends WindowAdapter {
@@ -59,54 +67,50 @@ public class AWTWindowClosingProtocol implements WindowClosingProtocol {
       if( WindowClosingMode.DISPOSE_ON_CLOSE == op ) {
           // we have to issue this call right away,
           // otherwise the window gets destroyed
-          closingOperation.run();
+          closingOperationClose.run();
+      } else if( null != closingOperationNOP ){
+          closingOperationNOP.run();
       }
     }
   }
   WindowListener windowClosingAdapter = new WindowClosingAdapter();
 
-  final boolean addClosingListenerImpl() {
-    Window w = AWTMisc.getWindow(comp);
-    if(null!=w) {
-        w.addWindowListener(windowClosingAdapter);
-        return true;
-    }
-    return false;
-  }
-
   /**
-   * Adds this closing listener to the components Window if exist and only one time.<br>
-   * Hence you may call this method every time to ensure it has been set,
-   * ie in case the Window parent is not available yet.
+   * Adds this closing listener to the components Window if exist and only one time.
+   * <p>
+   * If the closing listener is already added, and {@link IllegalStateException} is thrown. 
+   * </p>
    *
-   * @return
+   * @return true if added, otherwise false.
+   * @throws IllegalStateException
    */
-  public final boolean addClosingListenerOneShot() {
-    if(!closingListenerSet) { // volatile: ok
+  public final boolean addClosingListener() throws IllegalStateException {
       synchronized(closingListenerLock) {
-        if(!closingListenerSet) {
-            closingListenerSet=addClosingListenerImpl();
-            return closingListenerSet;
-        }
+          if(closingListenerSet) {
+              throw new IllegalStateException("WindowClosingListener already set");
+          }
+          final Window w = AWTMisc.getWindow(comp);
+          if(null!=w) {
+              w.addWindowListener(windowClosingAdapter);
+              closingListenerSet = true;
+              return true;
+          }
       }
-    }
-    return false;
+      return false;
   }
 
   public final boolean removeClosingListener() {
-    if(closingListenerSet) { // volatile: ok
       synchronized(closingListenerLock) {
-        if(closingListenerSet) {
-            Window w = AWTMisc.getWindow(comp);
-            if(null!=w) {
-                w.removeWindowListener(windowClosingAdapter);
-                closingListenerSet = false;
-                return true;
-            }
-        }
+          if(closingListenerSet) {
+              final Window w = AWTMisc.getWindow(comp);
+              if(null!=w) {
+                  w.removeWindowListener(windowClosingAdapter);
+                  closingListenerSet = false;
+                  return true;
+              }
+          }
       }
-    }
-    return false;
+      return false;
   }
 
   /**
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index a62d08c..a71356b 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -43,6 +43,8 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration;
 
 import java.awt.Component;
 import java.awt.Container;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
 import java.applet.Applet;
 import javax.media.nativewindow.AbstractGraphicsConfiguration;
 import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -83,7 +85,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
   protected long drawable;
   protected Rectangle bounds;
   protected Insets insets;
-  private long offscreenSurfaceLayer;
+  private volatile long offscreenSurfaceLayer;
 
   private long drawable_old;
 
@@ -110,9 +112,35 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
     this.component = windowObject;
     this.isApplet = false;
     this.offscreenSurfaceLayer = 0;
+    this.component.addComponentListener(new ComponentListener() {
+        @Override
+        public void componentResized(ComponentEvent e) {
+            layoutSurfaceLayerIfEnabled();
+        }
+
+        @Override
+        public void componentMoved(ComponentEvent e) {
+            layoutSurfaceLayerIfEnabled();
+        }
+
+        @Override
+        public void componentShown(ComponentEvent e) {
+            layoutSurfaceLayerIfEnabled();
+        }
+
+        @Override
+        public void componentHidden(ComponentEvent e) { }       
+    });
   }
 
   protected synchronized void invalidate() {
+    if(DEBUG) {
+        System.err.println("JAWTWindow.invalidate() - "+Thread.currentThread().getName());
+        if( isSurfaceLayerAttached() ) {
+            System.err.println("OffscreenSurfaceLayer still attached: 0x"+Long.toHexString(offscreenSurfaceLayer));        
+        }
+        // Thread.dumpStack();
+    }
     invalidateNative();
     jawt = null;
     isOffscreenLayerSurface = false;
@@ -130,7 +158,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
     if(changed) {
         if(DEBUG) {
             System.err.println("JAWTWindow.updateBounds: "+bounds+" -> "+jb);
-            Thread.dumpStack();
+            // Thread.dumpStack();
         }
         bounds.setX(jawtBounds.getX());
         bounds.setY(jawtBounds.getY());
@@ -199,47 +227,66 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
       if( !isOffscreenLayerSurfaceEnabled() ) {
           throw new NativeWindowException("Not an offscreen layer surface");
       }
-      int lockRes = lockSurface();
-      if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
-          throw new NativeWindowException("Could not lock (offscreen layer): "+this);
-      }
-      try {
-          if(DEBUG) {
-            System.err.println("JAWTWindow.attachSurfaceHandle(): 0x"+Long.toHexString(layerHandle) + ", bounds "+bounds);
-          }
-          attachSurfaceLayerImpl(layerHandle);
-          offscreenSurfaceLayer = layerHandle;
-      } finally {
-          unlockSurface();
+      if(DEBUG) {
+        System.err.println("JAWTWindow.attachSurfaceHandle: "+toHexString(layerHandle) + ", bounds "+bounds);
       }
+      attachSurfaceLayerImpl(layerHandle);
+      offscreenSurfaceLayer = layerHandle;
+      component.repaint();
+  }
+  protected void attachSurfaceLayerImpl(final long layerHandle) {
+      throw new UnsupportedOperationException("offscreen layer not supported");
   }
-  protected abstract void attachSurfaceLayerImpl(final long layerHandle);
 
+  /**
+   * Layout the offscreen layer according to the implementing class's constraints.
+   * <p>
+   * This method allows triggering a re-layout of the offscreen surface
+   * in case the implementation requires it.   
+   * </p>
+   * <p> 
+   * Call this method if any parent or ancestor's layout has been changed,
+   * which could affects the layout of this surface.
+   * </p>
+   * @see #isOffscreenLayerSurfaceEnabled()
+   * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
+   */
+  protected void layoutSurfaceLayerImpl(long layerHandle, int width, int height) {}
+  
+  private final void layoutSurfaceLayerIfEnabled() throws NativeWindowException {
+      if( isOffscreenLayerSurfaceEnabled() && 0 != offscreenSurfaceLayer ) {
+          layoutSurfaceLayerImpl(offscreenSurfaceLayer, getWidth(), getHeight());
+      }
+  }
+  
+  
   @Override
   public final void detachSurfaceLayer() throws NativeWindowException {
-      if( !isOffscreenLayerSurfaceEnabled() ) {
-          throw new java.lang.UnsupportedOperationException("Not an offscreen layer surface");
-      }
       if( 0 == offscreenSurfaceLayer) {
           throw new NativeWindowException("No offscreen layer attached: "+this);
       }
-      int lockRes = lockSurface();
-      if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
-          throw new NativeWindowException("Could not lock (offscreen layer): "+this);
-      }
-      try {
-          if(DEBUG) {
-            System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(offscreenSurfaceLayer));
-          }
-          detachSurfaceLayerImpl(offscreenSurfaceLayer);
-          offscreenSurfaceLayer = 0;
-      } finally {
-          unlockSurface();
+      if(DEBUG) {
+        System.err.println("JAWTWindow.detachSurfaceHandle(): osh "+toHexString(offscreenSurfaceLayer));
       }
+      detachSurfaceLayerImpl(offscreenSurfaceLayer, detachSurfaceLayerNotify);
+  }
+  private final Runnable detachSurfaceLayerNotify = new Runnable() {
+    @Override
+    public void run() {
+        offscreenSurfaceLayer = 0;
+    }
+  };
+
+  /** 
+   * @param detachNotify Runnable to be called before native detachment
+   */
+  protected void detachSurfaceLayerImpl(final long layerHandle, final Runnable detachNotify) {
+      throw new UnsupportedOperationException("offscreen layer not supported");
   }
-  protected abstract void detachSurfaceLayerImpl(final long layerHandle);
+  
 
-  protected final long getAttachedSurfaceLayer() {
+  @Override
+  public final long getAttachedSurfaceLayer() {
       return offscreenSurfaceLayer;
   }
   
@@ -254,6 +301,11 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
       getPrivateGraphicsConfiguration().setChosenCapabilities(caps);      
   }
   
+  @Override
+  public final RecursiveLock getLock() {
+      return surfaceLock;
+  }
+  
   //
   // SurfaceUpdateListener
   //
@@ -303,13 +355,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
   protected abstract int lockSurfaceImpl() throws NativeWindowException;
 
   protected void dumpJAWTInfo() {
-      if(null != jawt) {
-          System.err.println("JAWT version: 0x"+Integer.toHexString(jawt.getCachedVersion())+
-                             ", CA_LAYER: "+ JAWTUtil.isJAWTUsingOffscreenLayer(jawt)+
-                             ", isLayeredSurface "+isOffscreenLayerSurfaceEnabled()+", bounds "+bounds+", insets "+insets);
-      } else {
-          System.err.println("JAWT n/a, bounds "+bounds+", insets "+insets);
-      }
+      System.err.println(jawt2String(null).toString());
       // Thread.dumpStack();
   }
 
@@ -319,32 +365,41 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
     int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
 
     if ( LOCK_SURFACE_NOT_READY == res ) {
-        determineIfApplet();
-        try {
-            final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
-            adevice.lock();
+        if( !component.isDisplayable() ) {
+            // W/o native peer, we cannot utilize JAWT for locking.
+            surfaceLock.unlock();
+            if(DEBUG) {
+                System.err.println("JAWTWindow: Can't lock surface, component peer n/a. Component displayable "+component.isDisplayable()+", "+component);
+                Thread.dumpStack();
+            }
+        } else {
+            determineIfApplet();
             try {
-                if(null == jawt) { // no need to re-fetch for each frame
-                    jawt = fetchJAWTImpl();
-                    isOffscreenLayerSurface = JAWTUtil.isJAWTUsingOffscreenLayer(jawt);
-                }
-                res = lockSurfaceImpl();
-                if(LOCK_SUCCESS == res && drawable_old != drawable) {
-                    res = LOCK_SURFACE_CHANGED;
-                    if(DEBUG) {
-                        System.err.println("JAWTWindow: surface change 0x"+Long.toHexString(drawable_old)+" -> 0x"+Long.toHexString(drawable));
-                        // Thread.dumpStack();
+                final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
+                adevice.lock();
+                try {
+                    if(null == jawt) { // no need to re-fetch for each frame
+                        jawt = fetchJAWTImpl();
+                        isOffscreenLayerSurface = JAWTUtil.isJAWTUsingOffscreenLayer(jawt);
+                    }
+                    res = lockSurfaceImpl();
+                    if(LOCK_SUCCESS == res && drawable_old != drawable) {
+                        res = LOCK_SURFACE_CHANGED;
+                        if(DEBUG) {
+                            System.err.println("JAWTWindow: surface change "+toHexString(drawable_old)+" -> "+toHexString(drawable));
+                            // Thread.dumpStack();
+                        }
+                    }
+                } finally {
+                    if (LOCK_SURFACE_NOT_READY >= res) {
+                        adevice.unlock();
                     }
                 }
             } finally {
                 if (LOCK_SURFACE_NOT_READY >= res) {
-                    adevice.unlock();
+                    surfaceLock.unlock();
                 }
             }
-        } finally {
-            if (LOCK_SURFACE_NOT_READY >= res) {
-                surfaceLock.unlock();
-            }
         }
     }
     return res;
@@ -534,15 +589,32 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
       return component.hasFocus();
   }
 
+  protected StringBuilder jawt2String(StringBuilder sb) {
+      if( null == sb ) {
+          sb = new StringBuilder();
+      }
+      if(null != jawt) {
+          sb.append("JAWT version: 0x").append(Integer.toHexString(jawt.getCachedVersion())).
+          append(", CA_LAYER: ").append(JAWTUtil.isJAWTUsingOffscreenLayer(jawt)).
+          append(", isLayeredSurface ").append(isOffscreenLayerSurfaceEnabled()).append(", bounds ").append(bounds).append(", insets ").append(insets);
+      } else {
+          sb.append("JAWT n/a, bounds ").append(bounds).append(", insets ").append(insets);
+      }
+      return sb;
+  }
+  
   @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
 
-    sb.append("JAWT-Window["+
-                "windowHandle 0x"+Long.toHexString(getWindowHandle())+
-                ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+
-                ", bounds "+bounds+", insets "+insets+
-                ", shallUseOffscreenLayer "+shallUseOffscreenLayer+", isOffscreenLayerSurface "+isOffscreenLayerSurface);
+    sb.append("JAWT-Window[");
+    jawt2String(sb);
+    sb.append(  ", shallUseOffscreenLayer "+shallUseOffscreenLayer+", isOffscreenLayerSurface "+isOffscreenLayerSurface+
+                ", attachedSurfaceLayer "+toHexString(getAttachedSurfaceLayer())+
+                ", windowHandle "+toHexString(getWindowHandle())+
+                ", surfaceHandle "+toHexString(getSurfaceHandle())+
+                ", bounds "+bounds+", insets "+insets
+                );
     if(null!=component) {
       sb.append(", pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
                 ", visible "+component.isVisible());
@@ -556,4 +628,8 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
 
     return sb.toString();
   }
+  
+  protected final String toHexString(long l) {
+      return "0x"+Long.toHexString(l);
+  }
 }
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
index b824350..fb6d39b 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
@@ -38,7 +38,7 @@ import javax.media.nativewindow.*;
  */
 public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
     final long[] nativeDisplayID = new long[1];
-    final EGLDisplayLifecycleCallback eglLifecycleCallback;
+    /* final */ EGLDisplayLifecycleCallback eglLifecycleCallback;
 
     /**
      * Hack to allow inject a EGL termination call.
@@ -113,8 +113,22 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
     }
     
     @Override
-    public String toString() {
-        return "EGLGraphicsDevice[type EGL, connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", nativeDisplayID 0x"+Long.toHexString(nativeDisplayID[0])+", eglLifecycleCallback "+(null != eglLifecycleCallback)+"]";
+    public boolean isHandleOwner() {
+        return null != eglLifecycleCallback;
+    }    
+    @Override
+    public void clearHandleOwner() {
+        eglLifecycleCallback = null;
+    }
+    @Override
+    protected Object getHandleOwnership() {
+        return eglLifecycleCallback;
     }
+    @Override
+    protected Object setHandleOwnership(Object newOwnership) {
+        final EGLDisplayLifecycleCallback oldOwnership = eglLifecycleCallback; 
+        eglLifecycleCallback = (EGLDisplayLifecycleCallback) newOwnership;
+        return oldOwnership;
+    }    
 }
 
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
index 7be747f..5c4fd82 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
@@ -30,68 +30,116 @@ package com.jogamp.nativewindow.swt;
 import com.jogamp.common.os.Platform;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.widgets.Control;
 
 import javax.media.nativewindow.AbstractGraphicsScreen;
-import javax.media.nativewindow.DefaultGraphicsScreen;
 import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.nativewindow.VisualIDHolder;
 
 import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.common.util.VersionNumber;
 import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
 import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
 import com.jogamp.nativewindow.x11.X11GraphicsDevice;
-import com.jogamp.nativewindow.x11.X11GraphicsScreen;
 
 import jogamp.nativewindow.macosx.OSXUtil;
 import jogamp.nativewindow.x11.X11Lib;
 
 public class SWTAccessor {
-    static final Field swt_control_handle;
-    static final boolean swt_uses_long_handles;
+    private static final boolean DEBUG = true;
+    
+    private static final Field swt_control_handle;
+    private static final boolean swt_uses_long_handles;
+    
+    private static Object swt_osx_init = new Object(); 
+    private static Field swt_osx_control_view = null;
+    private static Field swt_osx_view_id = null;
+    
+    private static final String nwt;
+    private static final boolean isOSX;
+    private static final boolean isWindows;
+    private static final boolean isX11;
+    private static final boolean isX11GTK;
     
     // X11/GTK, Windows/GDI, ..
-    static final String str_handle = "handle";
+    private static final String str_handle = "handle";
     
     // OSX/Cocoa
-    static final String str_view = "view";  // OSX
-    static final String str_id = "id";    // OSX
+    private static final String str_osx_view = "view";  // OSX
+    private static final String str_osx_id = "id";    // OSX
     // static final String str_NSView = "org.eclipse.swt.internal.cocoa.NSView";
     
-    static final Method swt_control_internal_new_GC;
-    static final Method swt_control_internal_dispose_GC;
-    static final String str_internal_new_GC = "internal_new_GC";
-    static final String str_internal_dispose_GC = "internal_dispose_GC";
+    private static final Method swt_control_internal_new_GC;
+    private static final Method swt_control_internal_dispose_GC;
+    private static final String str_internal_new_GC = "internal_new_GC";
+    private static final String str_internal_dispose_GC = "internal_dispose_GC";
 
-    static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS";
-    static final Class<?> OS_gtk_class;
-    static final Method OS_gtk_widget_realize;
-    static final Method OS_gtk_widget_unrealize;
-    static final Method OS_GTK_WIDGET_WINDOW;
-    static final Method OS_gdk_x11_drawable_get_xdisplay;
-    static final Method OS_gdk_x11_drawable_get_xid;    
-    static final String str_gtk_widget_realize = "gtk_widget_realize";
-    static final String str_gtk_widget_unrealize = "gtk_widget_unrealize";
-    static final String str_GTK_WIDGET_WINDOW = "GTK_WIDGET_WINDOW";
-    static final String str_gdk_x11_drawable_get_xdisplay = "gdk_x11_drawable_get_xdisplay";
-    static final String str_gdk_x11_drawable_get_xid = "gdk_x11_drawable_get_xid";
+    private static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS";
+    public static final Class<?> OS_gtk_class;
+    private static final String str_OS_gtk_version = "GTK_VERSION";
+    public static final VersionNumber OS_gtk_version;
+    
+    private static final Method OS_gtk_widget_realize;
+    private static final Method OS_gtk_widget_unrealize; // optional (removed in SWT 4.3)
+    private static final Method OS_GTK_WIDGET_WINDOW;
+    private static final Method OS_gtk_widget_get_window;
+    private static final Method OS_gdk_x11_drawable_get_xdisplay;
+    private static final Method OS_gdk_x11_display_get_xdisplay;
+    private static final Method OS_gdk_window_get_display;    
+    private static final Method OS_gdk_x11_drawable_get_xid;  
+    private static final Method OS_gdk_x11_window_get_xid;
+    private static final Method OS_gdk_window_set_back_pixmap;
+    
+    private static final String str_gtk_widget_realize = "gtk_widget_realize";
+    private static final String str_gtk_widget_unrealize = "gtk_widget_unrealize";
+    private static final String str_GTK_WIDGET_WINDOW = "GTK_WIDGET_WINDOW";
+    private static final String str_gtk_widget_get_window = "gtk_widget_get_window";
+    private static final String str_gdk_x11_drawable_get_xdisplay = "gdk_x11_drawable_get_xdisplay";
+    private static final String str_gdk_x11_display_get_xdisplay = "gdk_x11_display_get_xdisplay";
+    private static final String str_gdk_window_get_display = "gdk_window_get_display";
+    private static final String str_gdk_x11_drawable_get_xid = "gdk_x11_drawable_get_xid";
+    private static final String str_gdk_x11_window_get_xid = "gdk_x11_window_get_xid";
+    private static final String str_gdk_window_set_back_pixmap = "gdk_window_set_back_pixmap";
+    
+    private static final VersionNumber GTK_VERSION_2_14_0 = new VersionNumber(2, 14, 0);
+    private static final VersionNumber GTK_VERSION_2_24_0 = new VersionNumber(2, 24, 0);
+    private static final VersionNumber GTK_VERSION_3_0_0  = new VersionNumber(3,  0, 0);
+    
+    private static VersionNumber GTK_VERSION(int version) {
+        // return (major << 16) + (minor << 8) + micro;
+        final int micro = ( version       ) & 0x0f;
+        final int minor = ( version >>  8 ) & 0x0f;
+        final int major = ( version >> 16 ) & 0x0f;
+        return new VersionNumber(major, minor, micro);
+    }
     
     static {
-        Field f = null;
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            public Object run() {
+                NativeWindowFactory.initSingleton(); // last resort ..
+                return null;
+            } } );
         
-        final String nwt = NativeWindowFactory.getNativeWindowType(false);
-
-        if(NativeWindowFactory.TYPE_MACOSX != nwt ) {
+        nwt = NativeWindowFactory.getNativeWindowType(false);
+        isOSX = NativeWindowFactory.TYPE_MACOSX == nwt;
+        isWindows = NativeWindowFactory.TYPE_WINDOWS == nwt;
+        isX11 = NativeWindowFactory.TYPE_X11 == nwt;
+        
+        Field f = null;        
+        if( !isOSX ) {
             try {
                 f = Control.class.getField(str_handle);
             } catch (Exception ex) {
                 throw new NativeWindowException(ex);
             }
-        }        
+        }
         swt_control_handle = f; // maybe null !
         
         boolean ulh;
@@ -123,39 +171,76 @@ public class SWTAccessor {
         }
         swt_control_internal_dispose_GC = m;
 
-        Class<?> c=null;                
-        Method m1=null, m2=null, m3=null, m4=null, m5=null;
-        Class<?> handleType = swt_uses_long_handles  ? long.class : int.class ;
-        if( NativeWindowFactory.TYPE_X11 == nwt ) {
+        Class<?> c=null;
+        VersionNumber _gtk_version = new VersionNumber(0, 0, 0);
+        Method m1=null, m2=null, m3=null, m4=null, m5=null, m6=null, m7=null, m8=null, m9=null, ma=null;
+        final Class<?> handleType = swt_uses_long_handles  ? long.class : int.class ;
+        if( isX11 ) {
+            // mandatory
             try {
                 c = ReflectionUtil.getClass(str_OS_gtk_class, false, SWTAccessor.class.getClassLoader());
+                Field field_OS_gtk_version = c.getField(str_OS_gtk_version);
+                _gtk_version = GTK_VERSION(field_OS_gtk_version.getInt(null));
                 m1 = c.getDeclaredMethod(str_gtk_widget_realize, handleType);        
-                m2 = c.getDeclaredMethod(str_gtk_widget_unrealize, handleType);
-                m3 = c.getDeclaredMethod(str_GTK_WIDGET_WINDOW, handleType);
-                m4 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xdisplay, handleType);
-                m5 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xid, handleType);
+                if (_gtk_version.compareTo(GTK_VERSION_2_14_0) >= 0) {
+                    m4 = c.getDeclaredMethod(str_gtk_widget_get_window, handleType);
+                } else {
+                    m3 = c.getDeclaredMethod(str_GTK_WIDGET_WINDOW, handleType);
+                }
+                if (_gtk_version.compareTo(GTK_VERSION_2_24_0) >= 0) {
+                    m6 = c.getDeclaredMethod(str_gdk_x11_display_get_xdisplay, handleType);
+                    m7 = c.getDeclaredMethod(str_gdk_window_get_display, handleType);                                
+                } else {
+                    m5 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xdisplay, handleType);                
+                }
+                if (_gtk_version.compareTo(GTK_VERSION_3_0_0) >= 0) {
+                    m9 = c.getDeclaredMethod(str_gdk_x11_window_get_xid, handleType);
+                } else {
+                    m8 = c.getDeclaredMethod(str_gdk_x11_drawable_get_xid, handleType);
+                }
+                ma = c.getDeclaredMethod(str_gdk_window_set_back_pixmap, handleType, handleType, boolean.class);
             } catch (Exception ex) { throw new NativeWindowException(ex); }
+            // optional 
+            try {
+                m2 = c.getDeclaredMethod(str_gtk_widget_unrealize, handleType);
+            } catch (Exception ex) { }
         }
         OS_gtk_class = c;
+        OS_gtk_version = _gtk_version;
         OS_gtk_widget_realize = m1;
         OS_gtk_widget_unrealize = m2;
         OS_GTK_WIDGET_WINDOW = m3;
-        OS_gdk_x11_drawable_get_xdisplay = m4;
-        OS_gdk_x11_drawable_get_xid = m5;
+        OS_gtk_widget_get_window = m4;
+        OS_gdk_x11_drawable_get_xdisplay = m5;
+        OS_gdk_x11_display_get_xdisplay = m6;
+        OS_gdk_window_get_display = m7;    
+        OS_gdk_x11_drawable_get_xid = m8;
+        OS_gdk_x11_window_get_xid = m9;
+        OS_gdk_window_set_back_pixmap = ma;
+        
+        isX11GTK = isX11 && null != OS_gtk_class;
+        
+        if(DEBUG) {
+            System.err.println("SWTAccessor.<init>: GTK Version: "+OS_gtk_version);
+        }
     }
-
-    static Object getIntOrLong(long arg) {
+        
+    private static Number getIntOrLong(long arg) {
         if(swt_uses_long_handles) {
             return new Long(arg);
         }
         return new Integer((int) arg);
     }
     
-    static void callStaticMethodL2V(Method m, long arg) {        
+    private static void callStaticMethodL2V(Method m, long arg) {        
         ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg) });
     }
     
-    static long callStaticMethodL2L(Method m, long arg) {
+    private static void callStaticMethodLLZ2V(Method m, long arg0, long arg1, boolean arg3) {        
+        ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg0), getIntOrLong(arg1), Boolean.valueOf(arg3) });
+    }
+    
+    private static long callStaticMethodL2L(Method m, long arg) {
         Object o = ReflectionUtil.callMethod(null, m, new Object[] { getIntOrLong(arg) });
         if(o instanceof Number) {
             return ((Number)o).longValue();
@@ -163,33 +248,114 @@ public class SWTAccessor {
             throw new InternalError("SWT method "+m.getName()+" didn't return int or long but "+o.getClass());
         }
     }
-        
+
+    //
+    // Public properties
+    //
+    
     public static boolean isUsingLongHandles() {
         return swt_uses_long_handles;
     }
 
-    public static long getHandle(Control swtControl) {
+    public static boolean useX11GTK() { return isX11GTK; }
+    public static VersionNumber GTK_VERSION() { return OS_gtk_version; }
+    
+    //
+    // Common GTK
+    //
+    
+    public static long gdk_widget_get_window(long handle) {
+        final long window;
+        if (OS_gtk_version.compareTo(GTK_VERSION_2_14_0) >= 0) {
+            window = callStaticMethodL2L(OS_gtk_widget_get_window, handle);
+        } else {
+            window = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle);
+        }
+        if(0 == window) {
+            throw new NativeWindowException("Null gtk-window-handle of SWT handle 0x"+Long.toHexString(handle));
+        }
+        return window;
+    }
+    
+    public static long gdk_window_get_xdisplay(long window) {
+        final long xdisplay;
+        if (OS_gtk_version.compareTo(GTK_VERSION_2_24_0) >= 0) {
+            final long display = callStaticMethodL2L(OS_gdk_window_get_display, window);
+            if(0 == display) {
+                throw new NativeWindowException("Null display-handle of gtk-window-handle 0x"+Long.toHexString(window));
+            }
+            xdisplay = callStaticMethodL2L(OS_gdk_x11_display_get_xdisplay, display);
+        } else {
+            xdisplay = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, window);
+        }
+        if(0 == xdisplay) {
+            throw new NativeWindowException("Null x11-display-handle of gtk-window-handle 0x"+Long.toHexString(window));
+        }
+        return xdisplay;
+    }
+    
+    public static long gdk_window_get_xwindow(long window) {
+        final long xWindow;
+        if (OS_gtk_version.compareTo(GTK_VERSION_3_0_0) >= 0) {
+            xWindow = callStaticMethodL2L(OS_gdk_x11_window_get_xid, window);
+        } else {
+            xWindow = callStaticMethodL2L(OS_gdk_x11_drawable_get_xid, window);
+        }
+        if(0 == xWindow) {
+            throw new NativeWindowException("Null x11-window-handle of gtk-window-handle 0x"+Long.toHexString(window));
+        }
+        return xWindow;
+    }
+    
+    public static void gdk_window_set_back_pixmap(long window, long pixmap, boolean parent_relative) {
+        callStaticMethodLLZ2V(OS_gdk_window_set_back_pixmap, window, pixmap, parent_relative);
+    }
+    
+    //
+    // Common any toolkit
+    //
+    
+    /**
+     * @param swtControl the SWT Control to retrieve the native widget-handle from
+     * @return the native widget-handle
+     * @throws NativeWindowException if the widget handle is null
+     */
+    public static long getHandle(Control swtControl) throws NativeWindowException {
         long h = 0;
-        if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) {
+        if( isOSX ) {
+            synchronized(swt_osx_init) {
+                try {
+                    if(null == swt_osx_view_id) {
+                        swt_osx_control_view = Control.class.getField(str_osx_view);
+                        Object view = swt_osx_control_view.get(swtControl);
+                        swt_osx_view_id = view.getClass().getField(str_osx_id);
+                        h = swt_osx_view_id.getLong(view);
+                    } else {
+                        h = swt_osx_view_id.getLong( swt_osx_control_view.get(swtControl) );
+                    }
+                } catch (Exception ex) {
+                    throw new NativeWindowException(ex);
+                }                    
+            }
+        } else {       
             try {
-                Field fView = Control.class.getField(str_view);
-                Object view = fView.get(swtControl);
-                Field fId = view.getClass().getField(str_id);
-                return fId.getLong(view);
+                h = swt_control_handle.getLong(swtControl);
             } catch (Exception ex) {
                 throw new NativeWindowException(ex);
-            }            
+            }
         }
-        
-        try {
-            h = swt_control_handle.getLong(swtControl);
-        } catch (Exception ex) {
-            throw new NativeWindowException(ex);
+        if(0 == h) {
+            throw new NativeWindowException("Null widget-handle of SWT "+swtControl.getClass().getName()+": "+swtControl.toString());
         }
         return h;
     }
 
-    public static void setRealized(final Control swtControl, final boolean realize) {
+    public static void setRealized(final Control swtControl, final boolean realize) 
+            throws NativeWindowException 
+    {
+        if(!realize && swtControl.isDisposed()) {
+            return;
+        }
         final long handle = getHandle(swtControl);
         
         if(null != OS_gtk_class) {
@@ -197,62 +363,69 @@ public class SWTAccessor {
                 public void run() {
                     if(realize) {
                         callStaticMethodL2V(OS_gtk_widget_realize, handle);
-                    } else {
+                    } else if(null != OS_gtk_widget_unrealize) {
                         callStaticMethodL2V(OS_gtk_widget_unrealize, handle);
                     }                    
                 }
             });
         }
     }
-    
-    public static AbstractGraphicsDevice getDevice(Control swtControl) {
-        long handle = getHandle(swtControl);
-        if( null != OS_gtk_class ) {
-            long widgedHandle = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle);
-            long displayHandle = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, widgedHandle);
-            return new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, false /* owner */);
+        
+    /**
+     * @param swtControl the SWT Control to retrieve the native device handle from
+     * @return the AbstractGraphicsDevice w/ the native device handle
+     * @throws NativeWindowException if the widget handle is null 
+     * @throws UnsupportedOperationException if the windowing system is not supported
+     */
+    public static AbstractGraphicsDevice getDevice(Control swtControl) throws NativeWindowException, UnsupportedOperationException {
+        final long handle = getHandle(swtControl);
+        if( isX11GTK ) {
+            final long xdisplay0 = gdk_window_get_xdisplay( gdk_widget_get_window( handle ) );
+            return new X11GraphicsDevice(xdisplay0, AbstractGraphicsDevice.DEFAULT_UNIT, false /* owner */);
         }
-        final String nwt = NativeWindowFactory.getNativeWindowType(false);
-        if( NativeWindowFactory.TYPE_WINDOWS == nwt ) {
+        if( isWindows ) {
             return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
         }
-        if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
+        if( isOSX ) {
             return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
         }
         throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
     }
+    
+    /**
+     * @param device
+     * @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen
+     * @return
+     */
     public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) {
-        if( null != OS_gtk_class ) {
-            return new X11GraphicsScreen((X11GraphicsDevice)device, screen);
-        }
-        final String nwt = NativeWindowFactory.getNativeWindowType(false);
-        if( NativeWindowFactory.TYPE_WINDOWS == nwt ||
-            NativeWindowFactory.TYPE_MACOSX == nwt ) {
-            return new DefaultGraphicsScreen(device, screen);
-        }
-        throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);        
+        return NativeWindowFactory.createScreen(device, screen);
     }
+    
     public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) {
-        if( null != OS_gtk_class ) {
+        if( isX11 ) {
             return X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle);
         }
-        final String nwt = NativeWindowFactory.getNativeWindowType(false);
-        if( NativeWindowFactory.TYPE_WINDOWS == nwt ||
-            NativeWindowFactory.TYPE_MACOSX == nwt ) {
+        if( isWindows || isOSX ) {
             return VisualIDHolder.VID_UNDEFINED;
         }
         throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);        
     }
     
-    public static long getWindowHandle(Control swtControl) {
-        long handle = getHandle(swtControl);        
-        if( null != OS_gtk_class ) {
-            long widgedHandle = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle);
-            return callStaticMethodL2L(OS_gdk_x11_drawable_get_xid, widgedHandle);
+    /**
+     * @param swtControl the SWT Control to retrieve the native window handle from
+     * @return the native window handle
+     * @throws NativeWindowException if the widget handle is null 
+     * @throws UnsupportedOperationException if the windowing system is not supported
+     */
+    public static long getWindowHandle(Control swtControl) throws NativeWindowException, UnsupportedOperationException {
+        final long handle = getHandle(swtControl);        
+        if(0 == handle) {
+            throw new NativeWindowException("Null SWT handle of SWT control "+swtControl);
         }
-        final String nwt = NativeWindowFactory.getNativeWindowType(false);
-        if( NativeWindowFactory.TYPE_WINDOWS == nwt ||
-            NativeWindowFactory.TYPE_MACOSX == nwt ) {
+        if( isX11GTK ) {
+            return gdk_window_get_xwindow( gdk_widget_get_window( handle ) );            
+        }
+        if( isWindows || isOSX ) {
             return handle;
         }
         throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
@@ -271,7 +444,7 @@ public class SWTAccessor {
             throw new InternalError("SWT internal_new_GC did not return int or long but "+o[0].getClass());
         }
     }
-
+    
     public static void disposeGC(final Control swtControl, final long gc, final GCData gcData) {
         invoke(true, new Runnable() {
             public void run() {
@@ -290,7 +463,7 @@ public class SWTAccessor {
     *   <li>Mac OSX
     *   <ul>
     *     <!--li>AWT EDT: In case AWT is available, the AWT EDT is the OSX UI main thread</li-->
-    *     <li><i>Main Thread</i>: Run on OSX UI main thread.</li>
+    *     <li><i>Main Thread</i>: Run on OSX UI main thread. 'wait' is implemented on Java site via lock/wait on {@link RunnableTask} to not freeze OSX main thread.</li>
     *   </ul></li>
     *   <li>Linux, Windows, ..
     *   <ul>
@@ -301,7 +474,7 @@ public class SWTAccessor {
     * @see Platform#getOSType()
     */
     public static void invoke(boolean wait, Runnable runnable) {
-        if( Platform.OS_TYPE == Platform.OSType.MACOS ) {
+        if( isOSX ) {
             // Use SWT main thread! Only reliable config w/ -XStartOnMainThread !?
             OSXUtil.RunOnMainThread(wait, runnable);
         } else {
@@ -309,4 +482,102 @@ public class SWTAccessor {
         }        
     }
     
+   /**
+    * Runs the specified action on the SWT UI thread.
+    * <p>
+    * If <code>display</code> is disposed or the current thread is the SWT UI thread
+    * {@link #invoke(boolean, Runnable)} is being used.
+    * @see #invoke(boolean, Runnable)
+    */
+    public static void invoke(org.eclipse.swt.widgets.Display display, boolean wait, Runnable runnable) {
+        if( display.isDisposed() || Thread.currentThread() == display.getThread() ) {
+            invoke(wait, runnable);
+        } else if( wait ) {            
+            display.syncExec(runnable);
+        } else {
+            display.asyncExec(runnable);
+        }
+    }
+    
+    //
+    // Specific X11 GTK ChildWindow - Using plain X11 native parenting (works well)
+    //
+    
+    public static long createCompatibleX11ChildWindow(AbstractGraphicsScreen screen, Control swtControl, int visualID, int width, int height) {
+        final long handle = getHandle(swtControl);
+        final long parentWindow = gdk_widget_get_window( handle );
+        gdk_window_set_back_pixmap (parentWindow, 0, false);
+        
+        final long x11ParentHandle = gdk_window_get_xwindow(parentWindow);
+        final long x11WindowHandle = X11Lib.CreateWindow(x11ParentHandle, screen.getDevice().getHandle(), screen.getIndex(), visualID, width, height, true, true);
+        
+        return x11WindowHandle;
+    }
+    
+    public static void resizeX11Window(AbstractGraphicsDevice device, Rectangle clientArea, long x11Window) {
+        X11Lib.SetWindowPosSize(device.getHandle(), x11Window, clientArea.x, clientArea.y, clientArea.width, clientArea.height);        
+    }
+    public static void destroyX11Window(AbstractGraphicsDevice device, long x11Window) {
+        X11Lib.DestroyWindow(device.getHandle(), x11Window);
+    }
+    
+    //
+    // Specific X11 SWT/GTK ChildWindow - Using SWT/GTK native parenting (buggy - sporadic resize flickering, sporadic drop of rendering)
+    //
+    // FIXME: Need to use reflection for 32bit access as well !
+    //
+    
+    // public static final int GDK_WA_TYPE_HINT = 1 << 9;
+    // public static final int GDK_WA_VISUAL = 1 << 6;
+    
+    public static long createCompatibleGDKChildWindow(Control swtControl, int visualID, int width, int height) {
+        return 0;
+        /**
+        final long handle = SWTAccessor.getHandle(swtControl);
+        final long parentWindow = gdk_widget_get_window( handle );
+        
+        final long screen = OS.gdk_screen_get_default ();
+        final long gdkvisual = OS.gdk_x11_screen_lookup_visual (screen, visualID);
+        
+        final GdkWindowAttr attrs = new GdkWindowAttr();
+        attrs.width = width > 0 ? width : 1;
+        attrs.height = height > 0 ? height : 1;        
+        attrs.event_mask = OS.GDK_KEY_PRESS_MASK | OS.GDK_KEY_RELEASE_MASK |
+                           OS.GDK_FOCUS_CHANGE_MASK | OS.GDK_POINTER_MOTION_MASK |
+                           OS.GDK_BUTTON_PRESS_MASK | OS.GDK_BUTTON_RELEASE_MASK |
+                           OS.GDK_ENTER_NOTIFY_MASK | OS.GDK_LEAVE_NOTIFY_MASK |
+                           OS.GDK_EXPOSURE_MASK | OS.GDK_VISIBILITY_NOTIFY_MASK |
+                           OS.GDK_POINTER_MOTION_HINT_MASK;
+        attrs.window_type = OS.GDK_WINDOW_CHILD;
+        attrs.visual = gdkvisual;
+        
+        final long childWindow = OS.gdk_window_new (parentWindow, attrs, OS.GDK_WA_VISUAL|GDK_WA_TYPE_HINT);
+        OS.gdk_window_set_user_data (childWindow, handle);
+        OS.gdk_window_set_back_pixmap (parentWindow, 0, false);
+        
+        OS.gdk_window_show (childWindow);
+        OS.gdk_flush();
+        return childWindow; */
+    }
+    
+    public static void showGDKWindow(long gdkWindow) {
+        /* OS.gdk_window_show (gdkWindow);
+        OS.gdk_flush(); */
+    }
+    public static void focusGDKWindow(long gdkWindow) {
+        /*
+        OS.gdk_window_show (gdkWindow);
+        OS.gdk_window_focus(gdkWindow, 0);
+        OS.gdk_flush(); */
+    }
+    public static void resizeGDKWindow(Rectangle clientArea, long gdkWindow) {
+        /**
+        OS.gdk_window_move (gdkWindow, clientArea.x, clientArea.y);
+        OS.gdk_window_resize (gdkWindow, clientArea.width, clientArea.height);
+        OS.gdk_flush(); */
+    }
+    
+    public static void destroyGDKWindow(long gdkWindow) {
+        // OS.gdk_window_destroy (gdkWindow);
+    }    
 }
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
index 0f28ca6..e630e01 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
@@ -45,7 +45,7 @@ import javax.media.nativewindow.ToolkitLock;
  */
 
 public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
-    final boolean handleOwner;
+    /* final */ boolean handleOwner;
     final boolean isXineramaEnabled;
 
     /** Constructs a new X11GraphicsDevice corresponding to the given connection and default
@@ -153,5 +153,23 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
         }
         return super.close();
     }
+    
+    @Override
+    public boolean isHandleOwner() {
+        return handleOwner;
+    }    
+    @Override
+    public void clearHandleOwner() {
+        handleOwner = false;
+    }
+    @Override
+    protected Object getHandleOwnership() {
+        return Boolean.valueOf(handleOwner);
+    }
+    @Override
+    protected Object setHandleOwnership(Object newOwnership) {
+        final Boolean oldOwnership = Boolean.valueOf(handleOwner); 
+        handleOwner = ((Boolean) newOwnership).booleanValue();
+        return oldOwnership;
+    }        
 }
-
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
index ebdaf2f..4e45113 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
@@ -42,8 +42,9 @@ package javax.media.nativewindow;
 
 /** A marker interface describing a graphics configuration, visual, or
     pixel format in a toolkit-independent manner. */
-
 public interface AbstractGraphicsConfiguration extends VisualIDHolder, Cloneable {
+    public Object clone();
+    
     /**
      * Return the screen this graphics configuration is valid for
      */
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
index 8ecd524..ed305d4 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
@@ -45,7 +45,6 @@ import jogamp.nativewindow.Debug;
 /** A interface describing a graphics device in a
     toolkit-independent manner.
  */
-
 public interface AbstractGraphicsDevice extends Cloneable {
     public static final boolean DEBUG = Debug.debug("GraphicsDevice");
     
@@ -58,6 +57,8 @@ public interface AbstractGraphicsDevice extends Cloneable {
     /** Default unit id for the 1st device: 0 */
     public static int DEFAULT_UNIT = 0;
 
+    public Object clone();
+    
     /**
      * Returns the type of the underlying subsystem, ie
      * NativeWindowFactory.TYPE_KD, NativeWindowFactory.TYPE_X11, ..
@@ -88,10 +89,16 @@ public interface AbstractGraphicsDevice extends Cloneable {
     public int getUnitID();
 
     /**
-     * Returns a unique ID String of this device using {@link #getType() type},
-     * {@link #getConnection() connection} and {@link #getUnitID() unitID}.<br>
-     * The unique ID does not reflect the instance of the device, hence the handle is not included.<br>
+     * Returns a unique ID object of this device using {@link #getType() type},
+     * {@link #getConnection() connection} and {@link #getUnitID() unitID} as it's key components.
+     * <p>
+     * The unique ID does not reflect the instance of the device, hence the handle is not included.
      * The unique ID may be used as a key for semantic device mapping.
+     * </p>
+     * <p>
+     * The returned string object reference is unique using {@link String#intern()}  
+     * and hence can be used as a key itself.
+     * </p>
      */
     public String getUniqueID();
 
@@ -143,10 +150,17 @@ public interface AbstractGraphicsDevice extends Cloneable {
      * <p>
      * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice} 
      * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice} 
-     * issue the native close operation or skip it depending on the handles's ownership.
+     * issue the native close operation or skip it depending on the {@link #isHandleOwner() handles's ownership}.
      * </p> 
      *
      * @return true if the handle was not <code>null</code> and closing was successful, otherwise false.
      */
     public boolean close();
+    
+    /**
+     * @return <code>true</code> if instance owns the handle to issue {@link #close()}, otherwise <code>false</code>.
+     */
+    public boolean isHandleOwner();
+    
+    public void clearHandleOwner();
 }
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
index eb2cc91..acb9807 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
@@ -44,6 +44,8 @@ package javax.media.nativewindow;
  */
 
 public interface AbstractGraphicsScreen extends Cloneable {
+    public Object clone();
+    
     /**
      * Return the device this graphics configuration is valid for
      */
diff --git a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java
index 5795e8c..8e83eda 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java
@@ -157,11 +157,9 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
     }
     final CapabilitiesImmutable caps = (CapabilitiesImmutable) o; */
         
-    final int a = ( alphaBits > 0 ) ? alphaBits : 1;
-    final int rgba = redBits * greenBits * blueBits * a;
-
-    final int xa = ( caps.getAlphaBits() ) > 0 ? caps.getAlphaBits() : 1;
-    final int xrgba = caps.getRedBits() * caps.getGreenBits() * caps.getBlueBits() * xa;
+    final int rgba = redBits * greenBits * blueBits * ( alphaBits + 1 );
+    
+    final int xrgba = caps.getRedBits() * caps.getGreenBits() * caps.getBlueBits() * ( caps.getAlphaBits() + 1 );
 
     if(rgba > xrgba) {
         return 1;
@@ -390,18 +388,23 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable {
     return sink;
   }
   
+  /** Element separator */
+  protected static final String ESEP = "/";
+  /** Component separator */
+  protected static final String CSEP = ", ";
+  
   protected StringBuilder toString(StringBuilder sink, boolean withOnOffScreen) {  
     if(null == sink) {
         sink = new StringBuilder();
     }
-    sink.append("rgba 0x").append(toHexString(redBits)).append("/").append(toHexString(greenBits)).append("/").append(toHexString(blueBits)).append("/").append(toHexString(alphaBits));
+    sink.append("rgba ").append(redBits).append(ESEP).append(greenBits).append(ESEP).append(blueBits).append(ESEP).append(alphaBits);
     if(backgroundOpaque) {
         sink.append(", opaque");
     } else {
-        sink.append(", trans-rgba 0x").append(toHexString(transparentValueRed)).append("/").append(toHexString(transparentValueGreen)).append("/").append(toHexString(transparentValueBlue)).append("/").append(toHexString(transparentValueAlpha));
+        sink.append(", trans-rgba 0x").append(toHexString(transparentValueRed)).append(ESEP).append(toHexString(transparentValueGreen)).append(ESEP).append(toHexString(transparentValueBlue)).append(ESEP).append(toHexString(transparentValueAlpha));
     }
     if(withOnOffScreen) {
-        sink.append(", ");
+        sink.append(CSEP);
         onoffScreenToString(sink);
     }
     return sink;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
index a33c379..6b23172 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
@@ -93,25 +93,26 @@ public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphics
     /**
      * Set the capabilities to a new value.
      *
+     * <p>
      * The use case for setting the Capabilities at a later time is
-     * a change of the graphics device in a multi-screen environment.<br>
-     *
+     * a change or re-validation of capabilities.
+     * </p>
      * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
      */
     protected void setChosenCapabilities(CapabilitiesImmutable capsChosen) {
-        capabilitiesChosen = capsChosen;
+        this.capabilitiesChosen = capsChosen;
     }
 
     /**
      * Set a new screen.
      *
+     * <p>
      * the use case for setting a new screen at a later time is
-     * a change of the graphics device in a multi-screen environment.<br>
-     *
-     * A copy of the passed object is being used.
+     * a change of the graphics device in a multi-screen environment.
+     * </p>
      */
-    final protected void setScreen(DefaultGraphicsScreen screen) {
-        this.screen = (AbstractGraphicsScreen) screen.clone();
+    protected void setScreen(AbstractGraphicsScreen screen) {
+        this.screen = screen;
     }
 
     @Override
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 9288652..0bf5c29 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -37,10 +37,10 @@ import jogamp.nativewindow.NativeWindowFactoryImpl;
 
 public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice {
     private static final String separator = "_";
-    private String type;
-    protected String connection;
-    protected int unitID;
-    protected String uniqueID;
+    private final String type;
+    protected final String connection;
+    protected final int unitID;
+    protected final String uniqueID;
     protected long handle;
     protected ToolkitLock toolkitLock;
 
@@ -171,11 +171,56 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
     }
 
     @Override
+    public boolean isHandleOwner() {
+        return false;
+    }
+    
+    @Override
+    public void clearHandleOwner() {        
+    }
+    
+    @Override
     public String toString() {
-        return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", "+toolkitLock+"]";
+        return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", owner "+isHandleOwner()+", "+toolkitLock+"]";
     }
 
     /**
+     * Set the native handle of the underlying native device
+     * and return the previous one.
+     */
+    protected final long setHandle(long newHandle) {
+        final long oldHandle = handle;
+        handle = newHandle;
+        return oldHandle;
+    }
+    
+    protected Object getHandleOwnership() {
+        return null;
+    }
+    protected Object setHandleOwnership(Object newOwnership) {
+        return null;
+    }
+    
+    public static final void swapDeviceHandleAndOwnership(final DefaultGraphicsDevice aDevice1, final DefaultGraphicsDevice aDevice2) {
+        aDevice1.lock();
+        try {
+            aDevice2.lock();
+            try {
+                final long aDevice1Handle = aDevice1.getHandle();
+                final long aDevice2Handle = aDevice2.setHandle(aDevice1Handle);
+                aDevice1.setHandle(aDevice2Handle);
+                final Object aOwnership1 = aDevice1.getHandleOwnership();
+                final Object aOwnership2 = aDevice2.setHandleOwnership(aOwnership1);
+                aDevice1.setHandleOwnership(aOwnership2);
+            } finally {
+                aDevice2.unlock();
+            }
+        } finally {
+            aDevice1.unlock();
+        }
+    }
+        
+    /**
      * Set the internal ToolkitLock, which is used within the
      * {@link #lock()} and {@link #unlock()} implementation.
      *
@@ -185,8 +230,9 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
      * </p>
      * 
      * @param locker the ToolkitLock, if null, {@link jogamp.nativewindow.NullToolkitLock} is being used
+     * @return the previous ToolkitLock instance
      */
-    protected void setToolkitLock(ToolkitLock locker) {
+    protected ToolkitLock setToolkitLock(ToolkitLock locker) {
         final ToolkitLock _toolkitLock = toolkitLock;
         _toolkitLock.lock();
         try {
@@ -194,6 +240,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
         } finally {
             _toolkitLock.unlock();
         }
+        return _toolkitLock;
     }
 
     /**
@@ -206,7 +253,12 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
          return toolkitLock;
     }
 
+   /** 
+    * Returns a unique String object using {@link String#intern()} for the given arguments, 
+    * which object reference itself can be used as a key.
+    */
     protected static String getUniqueID(String type, String connection, int unitID) {
-      return (type + separator + connection + separator + unitID).intern();
+      final String r = (type + separator + connection + separator + unitID).intern();
+      return r.intern();
     }
 }
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
index f50bd0e..9fa58c7 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
@@ -33,8 +33,8 @@
 package javax.media.nativewindow;
 
 public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen {
-    AbstractGraphicsDevice device;
-    private int idx;
+    private final AbstractGraphicsDevice device;
+    private final int idx;
 
     public DefaultGraphicsScreen(AbstractGraphicsDevice device, int idx) {
         this.device = device;
@@ -57,7 +57,7 @@ public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen
     public AbstractGraphicsDevice getDevice() {
         return device;
     }
-
+    
     public int getIndex() {
       return idx;
     }
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java
index 27462ae..a89caec 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java
@@ -56,7 +56,7 @@ public interface NativeSurface extends SurfaceUpdatedListener {
    * ie return a value other than {@link #LOCK_SURFACE_UNLOCKED} and {@link #LOCK_SURFACE_NOT_READY},
    * which is 
    * <pre> 
-   *    boolean ok = lockSurface() > LOCK_SURFACE_NOT_READY; 
+   *    boolean ok = LOCK_SURFACE_NOT_READY < lockSurface(); 
    * </pre> 
    * </p>
    * <p>
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java
index 12e2029..a740ebb 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java
@@ -54,8 +54,7 @@ import javax.media.nativewindow.util.Point;
 public interface NativeWindow extends NativeSurface {
 
   /**
-   * destroys the window and releases
-   * windowing related resources.
+   * Destroys this window incl. releasing all related resources.
    */
   public void destroy();
 
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index 179610b..bf37b8d 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -37,8 +37,10 @@ import java.io.File;
 import java.lang.reflect.Method;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import jogamp.nativewindow.Debug;
@@ -48,6 +50,10 @@ import jogamp.nativewindow.ResourceToolkitLock;
 
 import com.jogamp.common.os.Platform;
 import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
+import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
 
 /** Provides a pluggable mechanism for arbitrary window toolkits to
     adapt their components to the {@link NativeWindow} interface,
@@ -104,7 +110,9 @@ public abstract class NativeWindowFactory {
     private static boolean requiresToolkitLock;
     private static boolean desktopHasThreadingIssues;
 
+    // Shutdown hook mechanism for the factory
     private static volatile boolean isJVMShuttingDown = false;
+    private static final List<Runnable> customShutdownHooks = new ArrayList<Runnable>();
     
     /** Creates a new NativeWindowFactory instance. End users do not
         need to call this method. */
@@ -148,8 +156,23 @@ public abstract class NativeWindowFactory {
     }
 
     static {
-        Platform.initSingleton();
-        DEBUG = Debug.debug("NativeWindow");
+        final boolean[] _DEBUG = new boolean[] { false };
+        final String[] _tmp = new String[] { null };
+        
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            public Object run() {
+                Platform.initSingleton(); // last resort ..
+                _DEBUG[0] = Debug.debug("NativeWindow");
+                _tmp[0] = Debug.getProperty("nativewindow.ws.name", true);
+                Runtime.getRuntime().addShutdownHook(
+                    new Thread(new Runnable() {
+                                public void run() {
+                                    NativeWindowFactory.shutdown(true);
+                                } }, "NativeWindowFactory_ShutdownHook" ) ) ;                        
+                return null;
+            } } ) ;
+        
+        DEBUG = _DEBUG[0];
         if(DEBUG) {
             System.err.println(Thread.currentThread().getName()+" - Info: NativeWindowFactory.<init>");
             // Thread.dumpStack();
@@ -157,11 +180,10 @@ public abstract class NativeWindowFactory {
         
         // Gather the windowing TK first
         nativeWindowingTypePure = _getNativeWindowingType();
-        final String tmp = Debug.getProperty("nativewindow.ws.name", true);
-        if(null==tmp || tmp.length()==0) {
+        if(null==_tmp[0] || _tmp[0].length()==0) {
             nativeWindowingTypeCustom = nativeWindowingTypePure;
         } else {
-            nativeWindowingTypeCustom = tmp.intern(); // canonical representation
+            nativeWindowingTypeCustom = _tmp[0].intern(); // canonical representation
         }
     }
 
@@ -191,6 +213,72 @@ public abstract class NativeWindowFactory {
         }
     }
 
+    /** Returns true if the JVM is shutting down, otherwise false. */ 
+    public static final boolean isJVMShuttingDown() { return isJVMShuttingDown; }
+    
+    /** 
+     * Add a custom shutdown hook to be performed at JVM shutdown before shutting down NativeWindowFactory instance.
+     *  
+     * @param head if true add runnable at the start, otherwise at the end
+     * @param runnable runnable to be added.
+     */
+    public static void addCustomShutdownHook(boolean head, Runnable runnable) {
+        synchronized( customShutdownHooks ) {
+            if( !customShutdownHooks.contains( runnable ) ) {
+                if( head ) {
+                    customShutdownHooks.add(0, runnable);
+                } else {
+                    customShutdownHooks.add( runnable );
+                }
+            }
+        }
+    }
+
+    /** 
+     * Cleanup resources at JVM shutdown
+     */
+    public static synchronized void shutdown(boolean _isJVMShuttingDown) {
+        isJVMShuttingDown = _isJVMShuttingDown;
+        if(DEBUG) {
+            System.err.println("NativeWindowFactory.shutdown() START: JVM Shutdown "+isJVMShuttingDown+", on thread "+Thread.currentThread().getName());
+        }
+        synchronized(customShutdownHooks) {
+            final int cshCount = customShutdownHooks.size();
+            for(int i=0; i < cshCount; i++) {
+                try {
+                    if( DEBUG ) { 
+                        System.err.println("NativeWindowFactory.shutdown - customShutdownHook #"+(i+1)+"/"+cshCount);
+                    }
+                    customShutdownHooks.get(i).run();
+                } catch(Throwable t) {
+                    System.err.println("NativeWindowFactory.shutdown: Catched "+t.getClass().getName()+" during customShutdownHook #"+(i+1)+"/"+cshCount);
+                    if( DEBUG ) { 
+                        t.printStackTrace(); 
+                    }
+                }
+            }
+            customShutdownHooks.clear();
+        }
+        if(DEBUG) {
+            System.err.println("NativeWindowFactory.shutdown(): Post customShutdownHook");
+        }
+        
+        if(initialized) {
+            initialized = false;
+            if(null != registeredFactories) {
+                registeredFactories.clear();
+                registeredFactories = null;
+            }
+            GraphicsConfigurationFactory.shutdown();
+        }
+        
+        shutdownNativeImpl(NativeWindowFactory.class.getClassLoader()); // always re-shutdown
+        // SharedResourceToolkitLock.shutdown(DEBUG); // not used yet
+        if(DEBUG) {
+            System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END JVM Shutdown "+isJVMShuttingDown);
+        }
+    }
+    
     private static void shutdownNativeImpl(final ClassLoader cl) {
         final String clazzName;
         if( TYPE_X11 == nativeWindowingTypePure ) {
@@ -297,29 +385,6 @@ public abstract class NativeWindowFactory {
         }
     }
 
-    public static synchronized void shutdown(boolean _isJVMShuttingDown) {
-        isJVMShuttingDown = _isJVMShuttingDown;
-        if(DEBUG) {
-            System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() START: JVM Shutdown "+isJVMShuttingDown);                
-        }
-        if(initialized) {
-            initialized = false;
-            if(null != registeredFactories) {
-                registeredFactories.clear();
-                registeredFactories = null;
-            }
-            GraphicsConfigurationFactory.shutdown();
-        }
-        shutdownNativeImpl(NativeWindowFactory.class.getClassLoader()); // always re-shutdown
-        // SharedResourceToolkitLock.shutdown(DEBUG); // not used yet
-        if(DEBUG) {
-            System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END JVM Shutdown "+isJVMShuttingDown);
-        }
-    }
-    
-    /** Returns true if the JVM is shutting down, otherwise false. */ 
-    public static final boolean isJVMShuttingDown() { return isJVMShuttingDown; }
-    
     /** @return true if the underlying toolkit requires locking, otherwise false. */
     public static boolean requiresToolkitLock() {
         return requiresToolkitLock;
@@ -419,6 +484,30 @@ public abstract class NativeWindowFactory {
         return NativeWindowFactoryImpl.getNullToolkitLock();
     }
     
+    /**
+     * @param device
+     * @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen
+     * @return newly created AbstractGraphicsScreen matching device's native type
+     */
+    public static AbstractGraphicsScreen createScreen(AbstractGraphicsDevice device, int screen) {
+        final String type = device.getType();
+        if( TYPE_X11 == type ) {
+            final X11GraphicsDevice x11Device = (X11GraphicsDevice)device;
+            if(0 > screen) {
+                screen = x11Device.getDefaultScreen();
+            }
+            return new X11GraphicsScreen(x11Device, screen);
+        }
+        if(0 > screen) {
+            screen = 0; // FIXME: Needs native API utilization
+        }
+        if( TYPE_AWT == type ) {
+            final AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) device;
+            return new AWTGraphicsScreen(awtDevice);
+        }
+        return new DefaultGraphicsScreen(device, screen);
+    }
+    
     /** Returns the appropriate NativeWindowFactory to handle window
         objects of the given type. The windowClass might be {@link
         NativeWindow NativeWindow}, in which case the client has
diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
index f980010..1826008 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
@@ -27,12 +27,18 @@
  */
 package javax.media.nativewindow;
 
+import com.jogamp.common.util.locks.RecursiveLock;
+
 /**
  * Interface specifying the offscreen layer surface protocol.
  */
 public interface OffscreenLayerSurface {
   /** 
    * Attach the offscreen layer to this offscreen layer surface.
+   * <p>
+   * Implementation may realize all required resources at this point.
+   * </p>
+   * 
    * @see #isOffscreenLayerSurfaceEnabled()
    * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
    */
@@ -47,10 +53,16 @@ public interface OffscreenLayerSurface {
    */
   public void detachSurfaceLayer() throws NativeWindowException;
   
+  /** Returns the attached surface layer or null if none is attached. */
+  public long getAttachedSurfaceLayer();
+  
   /** Returns true if a surface layer is attached, otherwise false. */
   public boolean isSurfaceLayerAttached();
   
   /** Sets the capabilities of this instance, allowing upstream API's to refine it, i.e. OpenGL related settings. */
   public void setChosenCapabilities(CapabilitiesImmutable caps);
   
+  /** Returns the recursive lock object of this surface, which synchronizes multithreaded access. */ 
+  public RecursiveLock getLock();
+  
 }
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
index 395fdc8..15a8738 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
@@ -44,6 +44,7 @@ public interface ProxySurface extends MutableSurface {
     /** 
      * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's surface handle
      * @see #addUpstreamOptionBits(int)
+     * @see #clearUpstreamOptionBits(int)
      * @see #getUpstreamOptionBits()
      */ 
     public static final int OPT_PROXY_OWNS_UPSTREAM_SURFACE = 1 << 6;
@@ -51,6 +52,7 @@ public interface ProxySurface extends MutableSurface {
     /** 
      * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's {@link AbstractGraphicsDevice}.
      * @see #addUpstreamOptionBits(int)
+     * @see #clearUpstreamOptionBits(int)
      * @see #getUpstreamOptionBits()
      */ 
     public static final int OPT_PROXY_OWNS_UPSTREAM_DEVICE = 1 << 7;
@@ -58,6 +60,7 @@ public interface ProxySurface extends MutableSurface {
     /** 
      * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete.
      * @see #addUpstreamOptionBits(int)
+     * @see #clearUpstreamOptionBits(int)
      * @see #getUpstreamOptionBits()
      */ 
     public static final int OPT_UPSTREAM_WINDOW_INVISIBLE = 1 << 8;
@@ -65,7 +68,20 @@ public interface ProxySurface extends MutableSurface {
     /** Allow redefining the AbstractGraphicsConfiguration */
     public void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg);    
 
-    /** Returns the set {@link UpstreamSurfaceHook}, or null if not set. */
+    /**
+     * Return the upstream {@link NativeSurface} if used, otherwise <code>null</code>.
+     * <p> 
+     * An upstream {@link NativeSurface} may backup this {@link ProxySurface} instance's representation,
+     * e.g. via a {@link #setUpstreamSurfaceHook(UpstreamSurfaceHook) set} {@link UpstreamSurfaceHook}.
+     * </p>
+     * <p>
+     * One example is the JOGL EGLWrappedSurface, which might be backed up by a
+     * native platform NativeSurface (X11, WGL, CGL, ..).
+     * </p>
+     */
+    public NativeSurface getUpstreamSurface();
+    
+    /** Returns the {@link UpstreamSurfaceHook} if {@link #setUpstreamSurfaceHook(UpstreamSurfaceHook) set}, otherwise <code>null</code>. */
     public UpstreamSurfaceHook getUpstreamSurfaceHook();
     
     /**
diff --git a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
index 884c916..02f68f4 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java
@@ -37,6 +37,10 @@ package javax.media.nativewindow;
  * this protocol default behavior {@link WindowClosingMode#DISPOSE_ON_CLOSE DISPOSE_ON_CLOSE} shall be used.</p>
  */
 public interface WindowClosingProtocol {
+    
+    /**
+     * Window closing mode if triggered by toolkit close operation.
+     */
     public enum WindowClosingMode {
         /**
          * Do nothing on native window close operation.<br>
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java b/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java
index 0a5a945..4fae98f 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java
@@ -57,7 +57,9 @@ public class Dimension implements Cloneable, DimensionImmutable {
         }
     }
 
+    @Override
     public int getWidth() { return width; }
+    @Override
     public int getHeight() { return height; }
 
     public void setWidth(int width) {
@@ -77,10 +79,12 @@ public class Dimension implements Cloneable, DimensionImmutable {
         return this;
     }
 
+    @Override
     public String toString() {
         return new String(width+" x "+height);
     }
 
+    @Override
     public boolean equals(Object obj) {
         if(this == obj)  { return true; }
         if (obj instanceof Dimension) {
@@ -91,6 +95,7 @@ public class Dimension implements Cloneable, DimensionImmutable {
         return false;
     }
 
+    @Override
     public int hashCode() {
         // 31 * x == (x << 5) - x
         int hash = 31 + width;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java b/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java
index 199ec27..f22668f 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java
@@ -57,11 +57,17 @@ public class Insets implements Cloneable, InsetsImmutable {
         }
     }
 
+    @Override
     public final int getLeftWidth() { return l; }
+    @Override
     public final int getRightWidth() { return r; }
+    @Override
     public final int getTotalWidth() { return l + r; }
+    @Override
     public final int getTopHeight() { return t; }
+    @Override
     public final int getBottomHeight() { return b; }
+    @Override
     public final int getTotalHeight() { return t + b; }
 
     public void setLeftWidth(int left) { l = left; }
@@ -69,6 +75,7 @@ public class Insets implements Cloneable, InsetsImmutable {
     public void setTopHeight(int top) { t = top; }
     public void setBottomHeight(int bottom) { b = bottom; }
     
+    @Override
     public boolean equals(Object obj) {
         if(this == obj)  { return true; }
         if (obj instanceof Insets) {
@@ -79,6 +86,7 @@ public class Insets implements Cloneable, InsetsImmutable {
         return false;
     }
 
+    @Override
     public int hashCode() {
         int sum1 = l + b;
         int sum2 = t + r;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Point.java b/src/nativewindow/classes/javax/media/nativewindow/util/Point.java
index c53b169..8e6caf7 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/Point.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/Point.java
@@ -54,6 +54,7 @@ public class Point implements Cloneable, PointImmutable {
         }
     }
 
+    @Override
     public boolean equals(Object obj) {
         if(this == obj)  { return true; }
         if (obj instanceof Point) {
@@ -63,14 +64,17 @@ public class Point implements Cloneable, PointImmutable {
         return false;
     }
 
+    @Override
     public final int getX() {
         return x;
     }
 
+    @Override
     public final int getY() {
         return y;
     }
 
+    @Override
     public int hashCode() {
         // 31 * x == (x << 5) - x
         int hash = 31 + x;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java b/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java
index 8d6bfe4..8e6fc8e 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java
@@ -28,6 +28,8 @@
  
 package javax.media.nativewindow.util;
 
+import java.util.List;
+
 public class Rectangle implements Cloneable, RectangleImmutable {
     int x;
     int y;
@@ -57,15 +59,90 @@ public class Rectangle implements Cloneable, RectangleImmutable {
         }
     }
 
+    @Override
     public final int getX() { return x; }
+    @Override
     public final int getY() { return y; }
+    @Override
     public final int getWidth() { return width; }
+    @Override
     public final int getHeight() { return height; }
-    public void setX(int x) { this.x = x; }
-    public void setY(int y) { this.y = y; }
-    public void setWidth(int width) { this.width = width; }
-    public void setHeight(int height) { this.height = height; }
+    
+    public final void setX(int x) { this.x = x; }
+    public final void setY(int y) { this.y = y; }
+    public final void setWidth(int width) { this.width = width; }
+    public final void setHeight(int height) { this.height = height; }
 
+    @Override
+    public final RectangleImmutable union(final RectangleImmutable r) {
+        return union(r.getX(), r.getY(), r.getX() + r.getWidth(), r.getY() + r.getHeight());
+    }
+    @Override
+    public final RectangleImmutable union(final int rx1, final int ry1, final int rx2, final int ry2) {
+        final int x1 = Math.min(x, rx1);
+        final int y1 = Math.min(y, ry1);
+        final int x2 = Math.max(x + width, rx2);
+        final int y2 = Math.max(y + height, ry2);
+        return new Rectangle(x1, y1, x2 - x1, y2 - y1);                
+    }
+    /**
+     * Calculates the union of the given rectangles, stores it in this instance and returns this instance.
+     * @param rectangles given list of rectangles
+     * @return this instance holding the union of given rectangles.
+     */
+    public final Rectangle union(final List<RectangleImmutable> rectangles) {
+        int x1=Integer.MAX_VALUE, y1=Integer.MAX_VALUE;
+        int x2=Integer.MIN_VALUE, y2=Integer.MIN_VALUE;
+        for(int i=rectangles.size()-1; i>=0; i--) {
+            final RectangleImmutable vp = rectangles.get(i);
+            x1 = Math.min(x1, vp.getX());
+            x2 = Math.max(x2, vp.getX() + vp.getWidth());
+            y1 = Math.min(y1, vp.getY());
+            y2 = Math.max(y2, vp.getY() + vp.getHeight());
+        }
+        setX(x1);
+        setY(y1);
+        setWidth(x2 - x1);
+        setHeight(y2 - y1);
+        return this;
+    }
+        
+    @Override
+    public final RectangleImmutable intersection(RectangleImmutable r) {
+        return intersection(r.getX(), r.getY(), r.getX() + r.getWidth(), r.getY() + r.getHeight());
+    }
+    @Override
+    public final RectangleImmutable intersection(final int rx1, final int ry1, final int rx2, final int ry2) {
+        final int x1 = Math.max(x, rx1);
+        final int y1 = Math.max(y, ry1);
+        final int x2 = Math.min(x + width, rx2);
+        final int y2 = Math.min(y + height, ry2);
+        final int ix, iy, iwidth, iheight;
+        if( x2 < x1 ) {
+            ix = 0;
+            iwidth = 0;
+        } else {
+            ix = x1;
+            iwidth = x2 - x1;
+        }
+        if( y2 < y1 ) {
+            iy = 0;
+            iheight = 0;
+        } else {
+            iy = y1;
+            iheight = y2 - y1;
+        }
+        return new Rectangle (ix, iy, iwidth, iheight);
+    }
+    @Override
+    public final float coverage(RectangleImmutable r) {
+        final RectangleImmutable isect = intersection(r);
+        final float sqI = (float) ( isect.getWidth()*isect.getHeight() );
+        final float sqT = (float) ( width*height );
+        return sqI / sqT;
+    }
+    
+    @Override
     public boolean equals(Object obj) {
         if(this == obj)  { return true; }
         if (obj instanceof Rectangle) {
@@ -76,6 +153,7 @@ public class Rectangle implements Cloneable, RectangleImmutable {
         return false;
     }
 
+    @Override
     public int hashCode() {
         int sum1 = x + height;
         int sum2 = width + y;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java
index d3b43c8..7531989 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java
@@ -41,6 +41,26 @@ public interface RectangleImmutable extends WriteCloneable {
 
     int getY();
 
+    /** Returns the union of this rectangle and the given rectangle. */
+    RectangleImmutable union(final RectangleImmutable r);
+    /** Returns the union of this rectangleand the given coordinates. */
+    RectangleImmutable union(final int rx1, final int ry1, final int rx2, final int ry2);
+    /** Returns the intersection of this rectangleand the given rectangle. */
+    RectangleImmutable intersection(RectangleImmutable r);
+    /** Returns the intersection of this rectangleand the given coordinates. */
+    RectangleImmutable intersection(final int rx1, final int ry1, final int rx2, final int ry2);
+    /** 
+     * Returns the coverage of given rectangle w/ this this one, i.e. between <code>0.0</code> and <code>1.0</code>.
+     * <p>
+     * Coverage is computed by:
+     * <pre>
+     *    isect = this.intersection(r);
+     *    coverage = area( isect ) / area( this ) ;
+     * </pre>
+     * </p> 
+     */
+    float coverage(RectangleImmutable r);
+    
     /**
      * Checks whether two rect objects are equal. Two instances
      * of <code>Rectangle</code> are equal if the four integer values
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java b/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java
index 8f21bc4..d7e451a 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java
@@ -36,8 +36,8 @@ package javax.media.nativewindow.util;
  * </ul>
  */
 public class SurfaceSize {
-    DimensionImmutable resolution;
-    int bitsPerPixel;
+    final DimensionImmutable resolution;
+    final int bitsPerPixel;
 
     public SurfaceSize(DimensionImmutable resolution, int bitsPerPixel) {
         if(null==resolution || bitsPerPixel<=0) {
diff --git a/src/nativewindow/classes/jogamp/nativewindow/Debug.java b/src/nativewindow/classes/jogamp/nativewindow/Debug.java
index e07fd1b..95547c9 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/Debug.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/Debug.java
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * 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
@@ -39,6 +40,9 @@
 
 package jogamp.nativewindow;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
 import com.jogamp.common.util.PropertyAccess;
 
 /** Helper routines for logging and debugging. */
@@ -49,7 +53,11 @@ public class Debug extends PropertyAccess {
   private static final boolean debugAll;
   
   static {
-    PropertyAccess.addTrustedPrefix("nativewindow.", Debug.class);
+    AccessController.doPrivileged(new PrivilegedAction<Object>() {
+        public Object run() {
+            PropertyAccess.addTrustedPrefix("nativewindow.");
+            return null;
+    } } );
 
     verbose = isPropertyDefined("nativewindow.verbose", true);
     debugAll = isPropertyDefined("nativewindow.debug", true);
@@ -61,18 +69,6 @@ public class Debug extends PropertyAccess {
     }
   }
 
-  public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) {
-    return PropertyAccess.isPropertyDefined(property, jnlpAlias, null);
-  }
-    
-  public static String getProperty(final String property, final boolean jnlpAlias) {
-    return PropertyAccess.getProperty(property, jnlpAlias, null);
-  }
-    
-  public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) {
-      return PropertyAccess.getBooleanProperty(property, jnlpAlias, null);
-  }
-    
   public static boolean verbose() {
     return verbose;
   }
diff --git a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
index 63f56cb..56e3427 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
@@ -42,7 +42,6 @@ import com.jogamp.common.util.locks.RecursiveLock;
 
 public abstract class ProxySurfaceImpl implements ProxySurface {    
     private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
-    protected long displayHandle; // convenient ref of config.screen.device.handle
     private AbstractGraphicsConfiguration config; // control access due to delegation
     private UpstreamSurfaceHook upstream;
     private long surfaceHandle_old;
@@ -65,7 +64,6 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
             throw new IllegalArgumentException("null UpstreamSurfaceHook");
         }
         this.config = cfg;
-        this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
         this.upstream = upstream;
         this.surfaceHandle_old = 0;
         this.implBitfield = 0;
@@ -76,9 +74,12 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
     }
 
     @Override
-    public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; }
+    public NativeSurface getUpstreamSurface() { return null; }
     
     @Override
+    public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; }
+            
+    @Override
     public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook) {
         if(null == hook) {
             throw new IllegalArgumentException("null UpstreamSurfaceHook");
@@ -96,7 +97,6 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
         if(upstreamSurfaceHookLifecycleEnabled) {
             upstream.create(this);
         }
-        this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
         this.surfaceHandle_old = 0;
     }
 
@@ -111,7 +111,6 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
             }
             invalidateImpl();
         }
-        this.displayHandle = 0;
         this.surfaceHandle_old = 0;
     }
     
@@ -123,11 +122,6 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
         throw new InternalError("UpstreamSurfaceHook given, but required method not implemented.");        
     }
     
-    @Override
-    public final long getDisplayHandle() {
-        return displayHandle;
-    }
-
     protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() {
         return config;
     }
@@ -138,6 +132,11 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
     }
 
     @Override
+    public final long getDisplayHandle() {
+        return config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+    }
+
+    @Override
     public final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) {
         config = cfg;
     }
@@ -305,12 +304,15 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
         if(null == sink) {
             sink = new StringBuilder();
         }
-        sink.append(getUpstreamSurfaceHook()).
-        append(", displayHandle 0x" + Long.toHexString(getDisplayHandle())).
-        append(", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle())).
-        append(", size " + getWidth() + "x" + getHeight()).append(", ");
+        sink.append("displayHandle 0x" + Long.toHexString(getDisplayHandle())).
+        append("\n, surfaceHandle 0x" + Long.toHexString(getSurfaceHandle())).
+        append("\n, size " + getWidth() + "x" + getHeight()).append("\n, ");
         getUpstreamOptionBits(sink);
-        sink.append(", surfaceLock "+surfaceLock);
+        sink.append("\n, "+config).
+        append("\n, surfaceLock "+surfaceLock+"\n, ").
+        append(getUpstreamSurfaceHook()).
+        append("\n, upstreamSurface "+(null != getUpstreamSurface()));
+        // append("\n, upstreamSurface "+getUpstreamSurface());
         return sink;
     }
     
diff --git a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
index d77cd75..66be82a 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
@@ -27,6 +27,7 @@
  */
 package jogamp.nativewindow.awt;
 
+import java.awt.FocusTraversalPolicy;
 import java.awt.Window;
 import java.awt.Component;
 import java.awt.Container;
@@ -69,6 +70,33 @@ public class AWTMisc {
     }
 
     /**
+     * Traverse to the next forward or backward component using the
+     * container's FocusTraversalPolicy.
+     * 
+     * @param comp the assumed current focuse component 
+     * @param forward if true, returns the next focus component, otherwise the previous one.
+     * @return
+     */
+    public static Component getNextFocus(Component comp, boolean forward) {
+        Container focusContainer = comp.getFocusCycleRootAncestor();
+        while ( focusContainer != null && 
+                ( !focusContainer.isShowing() || !focusContainer.isFocusable() || !focusContainer.isEnabled() ) )
+        {
+            comp = focusContainer;
+            focusContainer = comp.getFocusCycleRootAncestor();
+        }
+        Component next = null;
+        if (focusContainer != null) {
+            final FocusTraversalPolicy policy = focusContainer.getFocusTraversalPolicy();
+            next = forward ? policy.getComponentAfter(focusContainer, comp) : policy.getComponentBefore(focusContainer, comp);
+            if (next == null) {
+                next = policy.getDefaultComponent(focusContainer);
+            }
+        }
+        return next;
+    }
+    
+    /**
      * Issue this when your non AWT toolkit gains focus to clear AWT menu path
      */
     public static void clearAWTMenus() {
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
index 349da8e..1f5d337 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
@@ -55,6 +55,8 @@ import jogamp.nativewindow.Debug;
 
 import com.jogamp.common.os.Platform;
 import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
 
 public class JAWTUtil {
   public static final boolean DEBUG = Debug.debug("JAWT");
@@ -80,9 +82,7 @@ public class JAWTUtil {
   private static final Method  sunToolkitAWTUnlockMethod;
   private static final boolean hasSunToolkitAWTLock;
   
-  private static volatile Thread exclusiveOwnerThread;
-  private static int lockCounter;
-
+  private static final RecursiveLock jawtLock;
   private static final ToolkitLock jawtToolkitLock;
 
   private static class PrivilegedDataBlob1 {
@@ -232,26 +232,28 @@ public class JAWTUtil {
     }
     hasSunToolkitAWTLock = _hasSunToolkitAWTLock;
     // hasSunToolkitAWTLock = false;
-    exclusiveOwnerThread = null;
-    lockCounter = 0;
+    jawtLock = LockFactory.createRecursiveLock();
 
-    jawtToolkitLock = new ToolkitLock() {
+    jawtToolkitLock = new ToolkitLock() {          
           public final void lock() {
               JAWTUtil.lockToolkit();
-              if(TRACE_LOCK) { System.err.println("JAWTToolkitLock.lock()"); }
           }    
           public final void unlock() {
-              if(TRACE_LOCK) { System.err.println("JAWTToolkitLock.unlock()"); }
               JAWTUtil.unlockToolkit();
           }
           @Override
           public final void validateLocked() throws RuntimeException {
               JAWTUtil.validateLocked();
           }
+          @Override
           public final void dispose() {
               // nop
-          }          
-      };  
+          }
+          @Override
+          public String toString() {
+              return "JAWTToolkitLock[obj 0x"+Integer.toHexString(hashCode())+", isOwner "+jawtLock.isOwner(Thread.currentThread())+", "+jawtLock+"]";
+          }
+      };
 
     // trigger native AWT toolkit / properties initialization
     Map<?,?> desktophints = null;
@@ -318,80 +320,65 @@ public class JAWTUtil {
   }
 
   /**
-   * Locks the AWT's global ReentrantLock.<br>
-   *
+   * Locks the AWT's global ReentrantLock.
+   * <p>
    * JAWT's native Lock() function calls SunToolkit.awtLock(),
-   * which just uses AWT's global ReentrantLock.<br>
+   * which just uses AWT's global ReentrantLock.
+   * </p>
+   * <p>
+   * AWT locking is wrapped through a recursive lock object. 
+   * </p>
    */
-  private static final void awtLock() {
-    if(hasSunToolkitAWTLock) {
-        try {
-            sunToolkitAWTLockMethod.invoke(null, (Object[])null);
-        } catch (Exception e) {
-          throw new NativeWindowException("SunToolkit.awtLock failed", e);
+  public static void lockToolkit() throws NativeWindowException {
+    jawtLock.lock();
+    if( 1 == jawtLock.getHoldCount() ) {
+        if(!headlessMode && !isJava2DQueueFlusherThread()) {
+            if(hasSunToolkitAWTLock) {
+                try {
+                    sunToolkitAWTLockMethod.invoke(null, (Object[])null);
+                } catch (Exception e) {
+                  throw new NativeWindowException("SunToolkit.awtLock failed", e);
+                }
+            } else {
+                jawtLockObject.Lock();
+            }
         }
-    } else {
-        jawtLockObject.Lock();
     }
-    if(0 == lockCounter) {
-        exclusiveOwnerThread = Thread.currentThread();
-    }
-    lockCounter++;
+    if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.lock(): "+jawtLock); }
   }
 
   /**
-   * Unlocks the AWT's global ReentrantLock.<br>
-   *
+   * Unlocks the AWT's global ReentrantLock.
+   * <p>
    * JAWT's native Unlock() function calls SunToolkit.awtUnlock(),
-   * which just uses AWT's global ReentrantLock.<br>
+   * which just uses AWT's global ReentrantLock.
+   * </p>
+   * <p>
+   * AWT unlocking is wrapped through a recursive lock object. 
+   * </p>
    */
-  private static final void awtUnlock() {
-    awtValidateLocked();
-    lockCounter--;
-    if(0 == lockCounter) {
-        exclusiveOwnerThread = null;
-    }
-    if(hasSunToolkitAWTLock) {
-        try {
-            sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
-        } catch (Exception e) {
-          throw new NativeWindowException("SunToolkit.awtUnlock failed", e);
-        }
-    } else {
-        jawtLockObject.Unlock();
-    }
-  }
-
-  private static final void awtValidateLocked() throws RuntimeException {
-    final Thread ct = Thread.currentThread();
-    if( ct != exclusiveOwnerThread ) {
-        if ( null == exclusiveOwnerThread ) {
-            throw new RuntimeException(ct.getName()+": JAWT-ToolkitLock not locked");
-        }
-        throw new RuntimeException(ct.getName()+": Not JAWT-ToolkitLock owner. Owner is "+exclusiveOwnerThread.getName());
-    }
-  }
-  
-  public static void lockToolkit() throws NativeWindowException {
-    if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.lock()"); }
-    if(!headlessMode && !isJava2DQueueFlusherThread()) {
-        awtLock();
-    }
-  }
-
   public static void unlockToolkit() {
-    if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.unlock()"); }
-    if(!headlessMode && !isJava2DQueueFlusherThread()) {
-        awtUnlock();
+    jawtLock.validateLocked();    
+    if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.unlock(): "+jawtLock); }
+    if( 1 == jawtLock.getHoldCount() ) {
+        if(!headlessMode && !isJava2DQueueFlusherThread()) {
+            if(hasSunToolkitAWTLock) {
+                try {
+                    sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
+                } catch (Exception e) {
+                  throw new NativeWindowException("SunToolkit.awtUnlock failed", e);
+                }
+            } else {
+                jawtLockObject.Unlock();
+            }
+        }
     }
+    jawtLock.unlock();
   }
   
   public static final void validateLocked() throws RuntimeException {
-    if(!headlessMode && !isJava2DQueueFlusherThread()) {
-        awtValidateLocked();
-    }
-  }
-  
+    jawtLock.validateLocked();
+  }  
 
   public static ToolkitLock getJAWTToolkitLock() {
     return jawtToolkitLock;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
index 5fd2422..080504a 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
@@ -69,29 +69,63 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
     }
   }
 
+  @Override
   protected void invalidateNative() {
-      offscreenSurfaceHandle=0;
-      offscreenSurfaceHandleSet=false;
-      if(isOffscreenLayerSurfaceEnabled()) {
-          if(0 != rootSurfaceLayerHandle) {
-              OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
-              rootSurfaceLayerHandle = 0;
-          }
+      if(DEBUG) {
+          System.err.println("MacOSXJAWTWindow.invalidateNative(): osh-enabled "+isOffscreenLayerSurfaceEnabled()+
+                             ", osd-set "+offscreenSurfaceDrawableSet+
+                             ", osd "+toHexString(offscreenSurfaceDrawable)+
+                             ", osl "+toHexString(getAttachedSurfaceLayer())+
+                             ", rsl "+toHexString(rootSurfaceLayer)+
+                             ", wh "+toHexString(windowHandle)+" - "+Thread.currentThread().getName());
+      }
+      offscreenSurfaceDrawable=0;
+      offscreenSurfaceDrawableSet=false;
+      if( isOffscreenLayerSurfaceEnabled() ) {
           if(0 != windowHandle) {
               OSXUtil.DestroyNSWindow(windowHandle);
           }
+          OSXUtil.RunOnMainThread(false, new Runnable() {
+              public void run() {
+                  if( 0 != rootSurfaceLayer ) {
+                      if( 0 != jawtSurfaceLayersHandle) {
+                          UnsetJAWTRootSurfaceLayer0(jawtSurfaceLayersHandle, rootSurfaceLayer);
+                      }
+                      OSXUtil.DestroyCALayer(rootSurfaceLayer);
+                      rootSurfaceLayer = 0;
+                  }
+                  jawtSurfaceLayersHandle = 0;
+              }
+          });
       }
       windowHandle=0;
   }
-
+  
+  @Override
   protected void attachSurfaceLayerImpl(final long layerHandle) {
-      OSXUtil.AddCASublayer(rootSurfaceLayerHandle, layerHandle);
+      OSXUtil.RunOnMainThread(false, new Runnable() {
+          public void run() {      
+              OSXUtil.AddCASublayer(rootSurfaceLayer, layerHandle, getWidth(), getHeight());
+          } } );
+  }
+  
+  @Override
+  protected void layoutSurfaceLayerImpl(long layerHandle, int width, int height) {
+      if(DEBUG) {
+        System.err.println("JAWTWindow.layoutSurfaceLayerImpl: "+toHexString(layerHandle) + ", "+width+"x"+height+"; "+this);
+      }
+      OSXUtil.FixCALayerLayout(rootSurfaceLayer, layerHandle, width, height);
   }
   
-  protected void detachSurfaceLayerImpl(final long layerHandle) {
-      OSXUtil.RemoveCASublayer(rootSurfaceLayerHandle, layerHandle);
+  @Override
+  protected void detachSurfaceLayerImpl(final long layerHandle, final Runnable detachNotify) {
+      OSXUtil.RunOnMainThread(false, new Runnable() {
+          public void run() {
+              detachNotify.run();
+              OSXUtil.RemoveCASublayer(rootSurfaceLayer, layerHandle);
+          } } );
   }
-    
+  
   @Override
   public final long getWindowHandle() {
     return windowHandle;
@@ -99,7 +133,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
   
   @Override
   public final long getSurfaceHandle() {
-    return offscreenSurfaceHandleSet ? offscreenSurfaceHandle : drawable /* super.getSurfaceHandle() */ ;
+    return offscreenSurfaceDrawableSet ? offscreenSurfaceDrawable : drawable /* super.getSurfaceHandle() */ ;
   }
   
   public void setSurfaceHandle(long surfaceHandle) {
@@ -107,25 +141,24 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
           throw new java.lang.UnsupportedOperationException("Not using CALAYER");
       }
       if(DEBUG) {
-        System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
+        System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): "+toHexString(surfaceHandle));
       }
-      this.offscreenSurfaceHandle = surfaceHandle;
-      this.offscreenSurfaceHandleSet = true;
+      this.offscreenSurfaceDrawable = surfaceHandle;
+      this.offscreenSurfaceDrawableSet = true;
   }
 
   protected JAWT fetchJAWTImpl() throws NativeWindowException {
        // use offscreen if supported and [ applet or requested ]
       return JAWTUtil.getJAWT(getShallUseOffscreenLayer() || isApplet());
   }
+  
   protected int lockSurfaceImpl() throws NativeWindowException {
     int ret = NativeWindow.LOCK_SURFACE_NOT_READY;
-    if(null == ds) {
-        ds = getJAWT().GetDrawingSurface(component);
-        if (ds == null) {
-          // Widget not yet realized
-          unlockSurfaceImpl();
-          return NativeWindow.LOCK_SURFACE_NOT_READY;
-        }
+    ds = getJAWT().GetDrawingSurface(component);
+    if (ds == null) {
+      // Widget not yet realized
+      unlockSurfaceImpl();
+      return NativeWindow.LOCK_SURFACE_NOT_READY;
     }
     int res = ds.Lock();
     dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ;
@@ -141,21 +174,19 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
     if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
       ret = NativeWindow.LOCK_SURFACE_CHANGED;
     }
-    if(null == dsi) {
-        if (firstLock) {
-          AccessController.doPrivileged(new PrivilegedAction<Object>() {
-              public Object run() {
-                dsi = ds.GetDrawingSurfaceInfo();
-                return null;
-              }
-            });
-        } else {
-          dsi = ds.GetDrawingSurfaceInfo();
-        }
-        if (dsi == null) {
-          unlockSurfaceImpl();
-          return NativeWindow.LOCK_SURFACE_NOT_READY;
-        }
+    if (firstLock) {
+      AccessController.doPrivileged(new PrivilegedAction<Object>() {
+          public Object run() {
+            dsi = ds.GetDrawingSurfaceInfo();
+            return null;
+          }
+        });
+    } else {
+      dsi = ds.GetDrawingSurfaceInfo();
+    }
+    if (dsi == null) {
+      unlockSurfaceImpl();
+      return NativeWindow.LOCK_SURFACE_NOT_READY;
     }
     updateBounds(dsi.getBounds());
     if (DEBUG && firstLock ) {
@@ -193,31 +224,43 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
             } else {
                 drawable = OSXUtil.GetNSView(windowHandle);
                 if(0 == drawable) {
-                  errMsg = "Null NSView of NSWindow 0x"+Long.toHexString(windowHandle);
+                  errMsg = "Null NSView of NSWindow "+toHexString(windowHandle);
                 }
             }
             if(null == errMsg) {
-                // fix caps reflecting offscreen! (no GL available here ..)
-                Capabilities caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable();
+                // Fix caps reflecting offscreen! (no GL available here ..)
+                final Capabilities caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable();
                 caps.setOnscreen(false);
                 setChosenCapabilities(caps);
             }
         }
         if(null == errMsg) {
-            if(0 == rootSurfaceLayerHandle) {        
-                rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
-                if(0 == rootSurfaceLayerHandle) {
-                  errMsg = "Could not create root CALayer";                
-                } else if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) {
-                  errMsg = "Could not set JAWT rootSurfaceLayerHandle 0x"+Long.toHexString(rootSurfaceLayerHandle);
-                }
-            }
+            jawtSurfaceLayersHandle = GetJAWTSurfaceLayersHandle0(dsi.getBuffer());
+            OSXUtil.RunOnMainThread(false, new Runnable() {
+                public void run() {
+                    String errMsg = null;
+                    if(0 == rootSurfaceLayer && 0 != jawtSurfaceLayersHandle) {        
+                        rootSurfaceLayer = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
+                        if(0 == rootSurfaceLayer) {
+                          errMsg = "Could not create root CALayer";                
+                        } else {
+                            try {
+                                SetJAWTRootSurfaceLayer0(jawtSurfaceLayersHandle, rootSurfaceLayer);
+                            } catch(Exception e) {
+                                errMsg = "Could not set JAWT rootSurfaceLayerHandle "+toHexString(rootSurfaceLayer)+", cause: "+e.getMessage();
+                            }
+                        }
+                        if(null != errMsg) {
+                            if(0 != rootSurfaceLayer) {
+                              OSXUtil.DestroyCALayer(rootSurfaceLayer);
+                              rootSurfaceLayer = 0;
+                            }
+                            throw new NativeWindowException(errMsg+": "+MacOSXJAWTWindow.this);
+                        }
+                    }
+                } } );
         }
         if(null != errMsg) {
-            if(0 != rootSurfaceLayerHandle) {
-              OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
-              rootSurfaceLayerHandle = 0;
-            }
             if(0 != windowHandle) {
               OSXUtil.DestroyNSWindow(windowHandle);
               windowHandle = 0;
@@ -269,22 +312,33 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
       return getLocationOnScreenNonBlocking(storage, component);     
   }  
   protected Point getLocationOnScreenNativeImpl(final int x0, final int y0) { return null; }
-
-  private static native boolean SetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
-  // private static native boolean UnsetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
+  
+  
+  private static native long GetJAWTSurfaceLayersHandle0(Buffer jawtDrawingSurfaceInfoBuffer);
+  
+  /** 
+   * Set the given root CALayer in the JAWT surface
+   */  
+  private static native void SetJAWTRootSurfaceLayer0(long jawtSurfaceLayersHandle, long caLayer);
+  
+  /** 
+   * Unset the given root CALayer in the JAWT surface, passing the NIO DrawingSurfaceInfo buffer
+   */  
+  private static native void UnsetJAWTRootSurfaceLayer0(long jawtSurfaceLayersHandle, long caLayer);
   
   // Variables for lockSurface/unlockSurface
   private JAWT_DrawingSurface ds;
   private boolean dsLocked;
   private JAWT_DrawingSurfaceInfo dsi;
+  private long jawtSurfaceLayersHandle;
   
   private JAWT_MacOSXDrawingSurfaceInfo macosxdsi;
   
-  private long rootSurfaceLayerHandle = 0; // attached to the JAWT_SurfaceLayer
+  private volatile long rootSurfaceLayer = 0; // attached to the JAWT_SurfaceLayer
   
   private long windowHandle = 0;
-  private long offscreenSurfaceHandle = 0;
-  private boolean offscreenSurfaceHandleSet = false;
+  private long offscreenSurfaceDrawable = 0;
+  private boolean offscreenSurfaceDrawableSet = false;
    
   // Workaround for instance of 4796548
   private boolean firstLock = true;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
index 5d1d437..905a313 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
@@ -64,13 +64,6 @@ public class WindowsJAWTWindow extends JAWTWindow {
     windowHandle = 0;
   }
 
-  protected void attachSurfaceLayerImpl(final long layerHandle) {
-      throw new UnsupportedOperationException("offscreen layer not supported");
-  }
-  protected void detachSurfaceLayerImpl(final long layerHandle) {
-      throw new UnsupportedOperationException("offscreen layer not supported");
-  }
-  
   protected JAWT fetchJAWTImpl() throws NativeWindowException {
       return JAWTUtil.getJAWT(false); // no offscreen
   }
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
index 4678092..2e5dc7f 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
@@ -59,13 +59,6 @@ public class X11JAWTWindow extends JAWTWindow {
 
   protected void invalidateNative() { }
 
-  protected void attachSurfaceLayerImpl(final long layerHandle) {
-      throw new UnsupportedOperationException("offscreen layer not supported");
-  }
-  protected void detachSurfaceLayerImpl(final long layerHandle) {
-      throw new UnsupportedOperationException("offscreen layer not supported");
-  }
-  
   protected JAWT fetchJAWTImpl() throws NativeWindowException {
       return JAWTUtil.getJAWT(false); // no offscreen
   }
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index a195f13..1a90c09 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -32,6 +32,10 @@ import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.nativewindow.util.Insets;
 import javax.media.nativewindow.util.Point;
 
+import com.jogamp.common.util.Function;
+import com.jogamp.common.util.FunctionTask;
+import com.jogamp.common.util.RunnableTask;
+
 import jogamp.nativewindow.Debug;
 import jogamp.nativewindow.NWJNILibLoader;
 import jogamp.nativewindow.ToolkitProperties;
@@ -79,11 +83,11 @@ public class OSXUtil implements ToolkitProperties {
     public static final boolean hasThreadingIssues() { return false; }
     
     public static boolean isNSView(long object) {
-        return isNSView0(object);
+        return 0 != object ? isNSView0(object) : false;
     }
     
     public static boolean isNSWindow(long object) {
-        return isNSWindow0(object);
+        return 0 != object ? isNSWindow0(object) : false;
     }
     
     /**
@@ -132,33 +136,182 @@ public class OSXUtil implements ToolkitProperties {
       return GetNSWindow0(nsView);
     }
     
-    public static long CreateCALayer(int x, int y, int width, int height) {
-        return CreateCALayer0(x, y, width, height);
+    /** 
+     * Create a CALayer suitable to act as a root CALayer.
+     * @see #DestroyCALayer(long)
+     * @see #AddCASublayer(long, long) 
+     */
+    public static long CreateCALayer(final int x, final int y, final int width, final int height) {
+      final long l = CreateCALayer0(x, y, width, height);
+      if(DEBUG) {
+          System.err.println("OSXUtil.CreateCALayer: 0x"+Long.toHexString(l)+" - "+Thread.currentThread().getName());
+      }
+      return l;
     }
-    public static void AddCASublayer(long rootCALayer, long subCALayer) {
+    
+    /** 
+     * Attach a sub CALayer to the root CALayer
+     * <p>
+     * Method will trigger a <code>display</code>
+     * call to the CALayer hierarchy to enforce resource creation if required, e.g. an NSOpenGLContext.
+     * </p>
+     * <p>
+     * Hence it is important that related resources are not locked <i>if</i>
+     * they will be used for creation.  
+     * </p>
+     * @see #CreateCALayer(int, int, int, int)
+     * @see #RemoveCASublayer(long, long, boolean)
+     */
+    public static void AddCASublayer(final long rootCALayer, final long subCALayer, final int width, final int height) {
         if(0==rootCALayer || 0==subCALayer) {
             throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
         }
-        AddCASublayer0(rootCALayer, subCALayer);
+        if(DEBUG) {
+            System.err.println("OSXUtil.AttachCALayer: 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
+        }
+        AddCASublayer0(rootCALayer, subCALayer, width, height);
+    }
+    
+    /** 
+     * Fix root and sub CALayer position to 0/0 and size
+     * <p>
+     * If the sub CALayer implements the Objective-C NativeWindow protocol NWDedicatedSize (e.g. JOGL's MyNSOpenGLLayer),
+     * the dedicated size is passed to the layer, which propagates it appropriately. 
+     * </p>
+     * <p>
+     * On OSX/Java7 our root CALayer's frame position and size gets corrupted by its NSView,
+     * hence we have created the NWDedicatedSize protocol.
+     * </p>
+     * 
+     * @param rootCALayer the root surface layer, maybe null.
+     * @param subCALayer the client surface layer, maybe null.
+     * @param width the expected width
+     * @param height the expected height
+     */
+    public static void FixCALayerLayout(final long rootCALayer, final long subCALayer, final int width, final int height) {
+        if( 0==rootCALayer && 0==subCALayer ) {
+            return;
+        }
+        FixCALayerLayout0(rootCALayer, subCALayer, width, height);
     }
-    public static void RemoveCASublayer(long rootCALayer, long subCALayer) {
+    
+    /** 
+     * Detach a sub CALayer from the root CALayer.
+     */
+    public static void RemoveCASublayer(final long rootCALayer, final long subCALayer) {
         if(0==rootCALayer || 0==subCALayer) {
             throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
         }
+        if(DEBUG) {
+            System.err.println("OSXUtil.DetachCALayer: 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
+        }
         RemoveCASublayer0(rootCALayer, subCALayer);
     }
-    public static void DestroyCALayer(long caLayer) {
+    
+    /** 
+     * Destroy a CALayer.
+     * @see #CreateCALayer(int, int, int, int)
+     */    
+    public static void DestroyCALayer(final long caLayer) {
         if(0==caLayer) {
             throw new IllegalArgumentException("caLayer 0x"+Long.toHexString(caLayer));
         }
-        DestroyCALayer0(caLayer);    
+        if(DEBUG) {
+            System.err.println("OSXUtil.DestroyCALayer: 0x"+Long.toHexString(caLayer)+" - "+Thread.currentThread().getName());
+        }
+        DestroyCALayer0(caLayer);
     }
     
+    /**
+     * Run on OSX UI main thread.
+     * <p> 
+     * 'waitUntilDone' is implemented on Java site via lock/wait on {@link RunnableTask} to not freeze OSX main thread.
+     * </p>
+     * 
+     * @param waitUntilDone
+     * @param runnable
+     */
     public static void RunOnMainThread(boolean waitUntilDone, Runnable runnable) {
-        if(IsMainThread0()) {
+        if( IsMainThread0() ) {
             runnable.run(); // don't leave the JVM
         } else {
-            RunOnMainThread0(waitUntilDone, runnable);
+            // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
+            // otherwise we may freeze the OSX main thread.            
+            Throwable throwable = null;
+            final Object sync = new Object();
+            final RunnableTask rt = new RunnableTask( runnable, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err ); 
+            synchronized(sync) {
+                RunOnMainThread0(rt);
+                if( waitUntilDone ) {
+                    try {
+                        sync.wait();
+                    } catch (InterruptedException ie) {
+                        throwable = ie;
+                    }
+                    if(null==throwable) {
+                        throwable = rt.getThrowable();
+                    }
+                    if(null!=throwable) {
+                        throw new RuntimeException(throwable);
+                    }
+                }
+            }
+        }
+    }
+    
+    /**
+     * Run later on current OSX thread.
+     * 
+     * @param runnable
+     * @param delay delay to run the runnable in milliseconds
+     */
+    public static void RunLater(Runnable runnable, int delay) {
+        RunLater0(new RunnableTask( runnable, null, true, System.err ), delay);
+    }
+    
+    private static Runnable _nop = new Runnable() { public void run() {}; };
+    
+    /** Issues a {@link #RunOnMainThread(boolean, Runnable)} w/ an <i>NOP</i> runnable, while waiting until done. */ 
+    public static void WaitUntilFinish() {
+        RunOnMainThread(true, _nop);
+    }
+    
+    /**
+     * Run on OSX UI main thread.
+     * <p> 
+     * 'waitUntilDone' is implemented on Java site via lock/wait on {@link FunctionTask} to not freeze OSX main thread.
+     * </p>
+     * 
+     * @param waitUntilDone
+     * @param func
+     */
+    public static <R,A> R RunOnMainThread(boolean waitUntilDone, Function<R,A> func, A... args) {
+        if( IsMainThread0() ) {
+            return func.eval(args); // don't leave the JVM
+        } else {
+            // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
+            // otherwise we may freeze the OSX main thread.            
+            Throwable throwable = null;
+            final Object sync = new Object();
+            final FunctionTask<R,A> rt = new FunctionTask<R,A>( func, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err ); 
+            synchronized(sync) {
+                rt.setArgs(args);
+                RunOnMainThread0(rt);
+                if( waitUntilDone ) {
+                    try {
+                        sync.wait();
+                    } catch (InterruptedException ie) {
+                        throwable = ie;
+                    }
+                    if(null==throwable) {
+                        throwable = rt.getThrowable();
+                    }
+                    if(null!=throwable) {
+                        throw new RuntimeException(throwable);
+                    }
+                }
+            }
+            return rt.getResult();
         }
     }
     
@@ -202,10 +355,12 @@ public class OSXUtil implements ToolkitProperties {
     private static native long GetNSView0(long nsWindow);
     private static native long GetNSWindow0(long nsView);
     private static native long CreateCALayer0(int x, int y, int width, int height);
-    private static native void AddCASublayer0(long rootCALayer, long subCALayer);
+    private static native void AddCASublayer0(long rootCALayer, long subCALayer, int width, int height);
+    private static native void FixCALayerLayout0(long rootCALayer, long subCALayer, int width, int height);
     private static native void RemoveCASublayer0(long rootCALayer, long subCALayer);
     private static native void DestroyCALayer0(long caLayer);
-    private static native void RunOnMainThread0(boolean waitUntilDone, Runnable runnable);
+    private static native void RunOnMainThread0(Runnable runnable);
+    private static native void RunLater0(Runnable runnable, int delay);
     private static native boolean IsMainThread0();
     private static native int GetScreenRefreshRate0(int scrn_idx);
 }
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
index 2f4e183..00741a3 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
@@ -34,7 +34,6 @@ import javax.media.nativewindow.NativeWindowFactory;
 import jogamp.nativewindow.NWJNILibLoader;
 import jogamp.nativewindow.Debug;
 import jogamp.nativewindow.ToolkitProperties;
-import jogamp.nativewindow.x11.X11Util;
 
 public class GDIUtil implements ToolkitProperties {
     private static final boolean DEBUG = Debug.debug("GDIUtil");
@@ -49,7 +48,7 @@ public class GDIUtil implements ToolkitProperties {
      */
     public static synchronized void initSingleton() {
         if(!isInit) {
-            synchronized(X11Util.class) {
+            synchronized(GDIUtil.class) {
                 if(!isInit) {
                     if(DEBUG) {
                         System.out.println("GDI.initSingleton()");
@@ -92,7 +91,7 @@ public class GDIUtil implements ToolkitProperties {
     public static long CreateDummyWindow(int x, int y, int width, int height) {
         synchronized(dummyWindowSync) {
             dummyWindowClass = dummyWindowClassFactory.getSharedClass();
-            return CreateDummyWindow0(dummyWindowClass.getHandle(), dummyWindowClass.getName(), dummyWindowClass.getName(), x, y, width, height);
+            return CreateDummyWindow0(dummyWindowClass.getHInstance(), dummyWindowClass.getName(), dummyWindowClass.getName(), x, y, width, height);
         }
     }
   
@@ -112,12 +111,22 @@ public class GDIUtil implements ToolkitProperties {
         return (Point) GetRelativeLocation0(src_win, dest_win, src_x, src_y);
     }
     
+    public static boolean IsUndecorated(long win) {
+        return IsUndecorated0(win);
+    }
+    
+    public static boolean IsChild(long win) {
+        return IsChild0(win);
+    }
+    
     public static native boolean CreateWindowClass(long hInstance, String clazzName, long wndProc);
     public static native boolean DestroyWindowClass(long hInstance, String className);
     
     private static native boolean initIDs0();
     private static native long getDummyWndProc0();  
     private static native Object GetRelativeLocation0(long src_win, long dest_win, int src_x, int src_y);
+    private static native boolean IsChild0(long win);
+    private static native boolean IsUndecorated0(long win);
   
     static native long CreateDummyWindow0(long hInstance, String className, String windowName, int x, int y, int width, int height);  
 }
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
index afb3daf..949f5d0 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
@@ -37,7 +37,10 @@ public class RegisteredClass {
         className = name;
     }
 
-    public final long getHandle() { return hInstance; }
+    /** Application handle, same as {@link RegisteredClassFactory#getHInstance()}. */
+    public final long getHInstance() { return hInstance; }
+    
+    /** Unique Window Class Name */
     public final String getName() { return className; }
 
     @Override
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java
index 00bedfc..0280b0d 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java
@@ -33,8 +33,17 @@ import java.util.ArrayList;
 import javax.media.nativewindow.NativeWindowException;
 
 public class RegisteredClassFactory {
-    static final boolean DEBUG = Debug.debug("RegisteredClass");
-    private static ArrayList<RegisteredClassFactory> registeredFactories = new ArrayList<RegisteredClassFactory>();    
+    private static final boolean DEBUG = Debug.debug("RegisteredClass");
+    private static final ArrayList<RegisteredClassFactory> registeredFactories;    
+    private static final long hInstance;
+    
+    static {
+        hInstance = GDI.GetApplicationHandle();
+        if( 0 == hInstance ) {
+            throw new NativeWindowException("Error: Null ModuleHandle for Application");
+        }
+        registeredFactories = new ArrayList<RegisteredClassFactory>();
+    }
     
     private String classBaseName;
     private long wndProc;
@@ -43,7 +52,7 @@ public class RegisteredClassFactory {
     private int classIter = 0;
     private int sharedRefCount = 0;
     private final Object sync = new Object();
-
+    
     /**
      * Release the {@link RegisteredClass} of all {@link RegisteredClassFactory}. 
      */
@@ -53,7 +62,7 @@ public class RegisteredClassFactory {
                 final RegisteredClassFactory rcf = registeredFactories.get(j);
                 synchronized(rcf.sync) {
                     if(null != rcf.sharedClass) {
-                        GDIUtil.DestroyWindowClass(rcf.sharedClass.getHandle(), rcf.sharedClass.getName());
+                        GDIUtil.DestroyWindowClass(rcf.sharedClass.getHInstance(), rcf.sharedClass.getName());
                         rcf.sharedClass = null;
                         rcf.sharedRefCount = 0;
                         rcf.classIter = 0;                 
@@ -65,6 +74,9 @@ public class RegisteredClassFactory {
             }
         }
     }
+    
+    /** Application handle. */
+    public static long getHInstance() { return hInstance; }
 
     public RegisteredClassFactory(String classBaseName, long wndProc) {
         this.classBaseName = classBaseName;
@@ -80,10 +92,6 @@ public class RegisteredClassFactory {
               if( null != sharedClass ) {
                   throw new InternalError("Error ("+sharedRefCount+"): SharedClass not null: "+sharedClass);
               }
-              long hInstance = GDI.GetApplicationHandle();
-              if( 0 == hInstance ) {
-                  throw new NativeWindowException("Error: Null ModuleHandle for Application");
-              }
               String clazzName = null;
               boolean registered = false;
               final int classIterMark = classIter - 1; 
@@ -121,7 +129,7 @@ public class RegisteredClassFactory {
               throw new InternalError("Error ("+sharedRefCount+"): SharedClass is null");
           }
           if( 0 == sharedRefCount ) {
-              GDIUtil.DestroyWindowClass(sharedClass.getHandle(), sharedClass.getName());
+              GDIUtil.DestroyWindowClass(sharedClass.getHInstance(), sharedClass.getName());
               if(DEBUG) {
                   System.err.println("RegisteredClassFactory releaseSharedClass ("+sharedRefCount+") released: "+sharedClass);
               }
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
index 67a33e5..8278620 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
@@ -37,7 +37,7 @@ public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize
                 s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
             }
             if( 0 == s.getSurfaceHandle() ) {
-                final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64);
+                final long windowHandle = X11Lib.CreateWindow(0, device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64, false, false);
                 if(0 == windowHandle) {
                     throw new NativeWindowException("Creating dummy window failed w/ "+cfg);
                 }
@@ -59,7 +59,7 @@ public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize
             }
             device.lock();
             try {
-                X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle());            
+                X11Lib.DestroyWindow(device.getHandle(), s.getSurfaceHandle());            
                 s.setSurfaceHandle(0);
                 s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
             } finally {
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index c771cd6..bbc58b7 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -46,6 +46,7 @@ import jogamp.nativewindow.NWJNILibLoader;
 import jogamp.nativewindow.ToolkitProperties;
 
 import com.jogamp.common.util.LongObjectHashMap;
+import com.jogamp.common.util.PropertyAccess;
 import com.jogamp.nativewindow.x11.X11GraphicsDevice;
 
 /**
@@ -82,6 +83,9 @@ public class X11Util implements ToolkitProperties {
      * </p>
      */
     public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true);
+    
+    /** See {@link #ATI_HAS_XCLOSEDISPLAY_BUG}. */
+    public static final boolean HAS_XCLOSEDISPLAY_BUG = Debug.isPropertyDefined("nativewindow.debug.X11Util.HAS_XCLOSEDISPLAY_BUG", true);
 
     /**
      * See Bug 623 - https://jogamp.org/bugzilla/show_bug.cgi?id=623
@@ -94,10 +98,10 @@ public class X11Util implements ToolkitProperties {
     private static final boolean TRACE_DISPLAY_LIFECYCLE = Debug.isPropertyDefined("nativewindow.debug.X11Util.TraceDisplayLifecycle", true);
     private static String nullDisplayName = null;
     private static volatile boolean isInit = false;
-    private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues
+    private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues, or GLRendererQuirks.DontCloseX11Display
     private static boolean hasThreadingIssues = false; // ATI/AMD X11 driver issues
 
-    private static Object setX11ErrorHandlerLock = new Object();
+    private static final Object setX11ErrorHandlerLock = new Object();
     private static final String X11_EXTENSION_ATIFGLRXDRI     = "ATIFGLRXDRI";
     private static final String X11_EXTENSION_ATIFGLEXTENSION = "ATIFGLEXTENSION";
     
@@ -120,7 +124,7 @@ public class X11Util implements ToolkitProperties {
                     final boolean isInitOK = initialize0( XERROR_STACKDUMP );
         
                     final boolean hasX11_EXTENSION_ATIFGLRXDRI, hasX11_EXTENSION_ATIFGLEXTENSION;
-                    final long dpy = X11Lib.XOpenDisplay(null);
+                    final long dpy = X11Lib.XOpenDisplay(PropertyAccess.getProperty("nativewindow.x11.display.default", true));
                     if(0 != dpy) {
                         if(XSYNC_ENABLED) {
                             X11Lib.XSynchronize(dpy, true);
@@ -137,8 +141,11 @@ public class X11Util implements ToolkitProperties {
                         hasX11_EXTENSION_ATIFGLRXDRI = false;
                         hasX11_EXTENSION_ATIFGLEXTENSION = false;
                     }
-                    hasThreadingIssues = ATI_HAS_MULTITHREADING_BUG && ( hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION );
-                    markAllDisplaysUnclosable = ATI_HAS_XCLOSEDISPLAY_BUG && ( hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION );
+                    final boolean isATIFGLRX = hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION ;
+                    hasThreadingIssues = ATI_HAS_MULTITHREADING_BUG && isATIFGLRX;
+                    if ( !markAllDisplaysUnclosable ) {
+                        markAllDisplaysUnclosable = ( ATI_HAS_XCLOSEDISPLAY_BUG && isATIFGLRX ) || HAS_XCLOSEDISPLAY_BUG;
+                    }
                     
                     if(DEBUG) {
                         System.err.println("X11Util.initSingleton(): OK "+isInitOK+"]"+
@@ -178,7 +185,10 @@ public class X11Util implements ToolkitProperties {
             synchronized(X11Util.class) {
                 if(isInit) {                    
                     final boolean isJVMShuttingDown = NativeWindowFactory.isJVMShuttingDown() ;
-                    if(DEBUG || openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0) {
+                    if( DEBUG ||
+                        ( ( openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0 ) &&
+                          ( reusableDisplayList.size() != pendingDisplayList.size() || !markAllDisplaysUnclosable )
+                        ) ) {
                         System.err.println("X11Util.Display: Shutdown (JVM shutdown: "+isJVMShuttingDown+
                                            ", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+
                                            ", reusable (open, marked uncloseable): "+reusableDisplayList.size()+
@@ -197,12 +207,12 @@ public class X11Util implements ToolkitProperties {
                         }
                     }
             
-                    synchronized(globalLock) {
-                        // Only at JVM shutdown time, since AWT impl. seems to 
-                        // dislike closing of X11 Display's (w/ ATI driver). 
-                        if( isJVMShuttingDown ) {
-                            isInit = false;                            
-                            closePendingDisplayConnections();    
+                    // Only at JVM shutdown time, since AWT impl. seems to 
+                    // dislike closing of X11 Display's (w/ ATI driver). 
+                    if( isJVMShuttingDown ) {
+                        synchronized(globalLock) {
+                            isInit = false;
+                            closePendingDisplayConnections();
                             openDisplayList.clear();
                             reusableDisplayList.clear();
                             pendingDisplayList.clear();
@@ -241,7 +251,22 @@ public class X11Util implements ToolkitProperties {
     public static String getNullDisplayName() {
         return nullDisplayName;
     }
-    
+
+    public static void markAllDisplaysUnclosable() {
+        synchronized(globalLock) {
+            markAllDisplaysUnclosable = true;
+            for(int i=0; i<openDisplayList.size(); i++) {
+                openDisplayList.get(i).setUncloseable(true);
+            }
+            for(int i=0; i<reusableDisplayList.size(); i++) {
+                reusableDisplayList.get(i).setUncloseable(true);
+            }
+            for(int i=0; i<pendingDisplayList.size(); i++) {
+                pendingDisplayList.get(i).setUncloseable(true);
+            }
+        }
+    }
+
     public static boolean getMarkAllDisplaysUnclosable() {
         return markAllDisplaysUnclosable;
     }
@@ -326,7 +351,9 @@ public class X11Util implements ToolkitProperties {
                     XCloseDisplay(ndpy.getHandle());
                     num++;
                 }
-                System.err.println("X11Util.closePendingDisplayConnections(): Closed "+num+" pending display connections");
+                if(DEBUG) {
+                    System.err.println("X11Util.closePendingDisplayConnections(): Closed "+num+" pending display connections");
+                }
             }
         }
         return num;
@@ -446,10 +473,8 @@ public class X11Util implements ToolkitProperties {
     }
 
     public static void closeDisplay(long handle) {
-        NamedDisplay namedDpy;
-
         synchronized(globalLock) {
-            namedDpy = (NamedDisplay) openDisplayMap.remove(handle);
+            final NamedDisplay namedDpy = (NamedDisplay) openDisplayMap.remove(handle);
             if(null==namedDpy) {
                 X11Util.dumpPendingDisplayConnections();
                 throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped. Thread "+Thread.currentThread().getName());
@@ -461,8 +486,12 @@ public class X11Util implements ToolkitProperties {
     
             namedDpy.removeRef();
             if(!openDisplayList.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); }
-            
-            if(!namedDpy.isUncloseable()) {
+
+            if( markAllDisplaysUnclosable ) {
+                 // if set-mark 'slipped' this one .. just to be safe!
+                namedDpy.setUncloseable(true);
+            }
+            if( !namedDpy.isUncloseable() ) {
                 XCloseDisplay(namedDpy.getHandle());
                 pendingDisplayList.remove(namedDpy);
             } else {
@@ -470,7 +499,7 @@ public class X11Util implements ToolkitProperties {
                 X11Lib.XSync(namedDpy.getHandle(), true); // flush output buffer and discard all events                
                 reusableDisplayList.add(namedDpy);
             }
-            
+
             if(DEBUG) {
                 System.err.println("X11Util.Display: Closed (real: "+(!namedDpy.isUncloseable())+") "+namedDpy+". Thread "+Thread.currentThread().getName());
             }    
diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c
index d2fdd5d..e909c04 100644
--- a/src/nativewindow/native/NativewindowCommon.c
+++ b/src/nativewindow/native/NativewindowCommon.c
@@ -74,7 +74,7 @@ jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
     return strChars;
 }
 
-JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached) {
+JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) {
     JNIEnv* curEnv = NULL;
     JNIEnv* newEnv = NULL;
     int envRes;
@@ -83,7 +83,12 @@ JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int *
     envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
     if( JNI_EDETACHED == envRes ) {
         // detached thread - attach to JVM
-        if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) {
+        if( asDaemon ) {
+            envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL);
+        } else {
+            envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL);
+        }
+        if( JNI_OK != envRes ) {
             fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
             return NULL;
         }
diff --git a/src/nativewindow/native/NativewindowCommon.h b/src/nativewindow/native/NativewindowCommon.h
index 73b890c..a2975f3 100644
--- a/src/nativewindow/native/NativewindowCommon.h
+++ b/src/nativewindow/native/NativewindowCommon.h
@@ -13,6 +13,6 @@ jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
 void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...);
 void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
 
-JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached);
+JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached);
 
 #endif
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java b/src/nativewindow/native/macosx/NativeWindowProtocols.h
similarity index 82%
copy from src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
copy to src/nativewindow/native/macosx/NativeWindowProtocols.h
index 93c8409..b91a50d 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
+++ b/src/nativewindow/native/macosx/NativeWindowProtocols.h
@@ -1,6 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -27,15 +26,9 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.newt.event;
+#import <Foundation/NSGeometry.h>
 
-public abstract class KeyAdapter implements KeyListener
-{
- public void keyPressed(KeyEvent e) {
- }
- public void keyReleased(KeyEvent e) {
- }
- public void keyTyped(KeyEvent e)  {
- }
-}
+ at protocol NWDedicatedSize
+- (void)setDedicatedSize:(CGSize)size;
+ at end
 
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index 1cf41fc..688ef79 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -32,13 +32,14 @@
 #include <stdarg.h>
 #include <unistd.h>
 #include <AppKit/AppKit.h>
+#import <QuartzCore/QuartzCore.h>
+#import "NativeWindowProtocols.h"
 
 #include "NativewindowCommon.h"
 #include "jogamp_nativewindow_macosx_OSXUtil.h"
 #include "jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow.h"
 
 #include <jawt_md.h>
-#import <JavaNativeFoundation.h>
 
 // #define VERBOSE 1
 //
@@ -49,6 +50,16 @@
     #define DBG_PRINT(...)
 #endif
 
+// #define VERBOSE2 1
+//
+#ifdef VERBOSE2
+    #define DBG_PRINT2(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#else
+    #define DBG_PRINT2(...)
+#endif
+
+// #define DBG_LIFECYCLE 1
+
 static const char * const ClazzNameRunnable = "java/lang/Runnable";
 static jmethodID runnableRunID = NULL;
 
@@ -116,13 +127,17 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
 JNIEXPORT jboolean JNICALL 
 Java_jogamp_nativewindow_macosx_OSXUtil_isNSView0(JNIEnv *env, jclass _unused, jlong object) {
     NSObject *nsObj = (NSObject*) (intptr_t) object;
-    return [nsObj isMemberOfClass:[NSView class]];
+    jboolean u = [nsObj isKindOfClass:[NSView class]];
+    DBG_PRINT( "isNSView(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+    return u;
 }
 
 JNIEXPORT jboolean JNICALL 
 Java_jogamp_nativewindow_macosx_OSXUtil_isNSWindow0(JNIEnv *env, jclass _unused, jlong object) {
     NSObject *nsObj = (NSObject*) (intptr_t) object;
-    return [nsObj isMemberOfClass:[NSWindow class]];
+    jboolean u = [nsObj isKindOfClass:[NSWindow class]];
+    DBG_PRINT( "isNSWindow(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+    return u;
 }
 
 /*
@@ -313,6 +328,70 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSWindow0
     return res;
 }
 
+/**
+ * Track lifecycle via DBG_PRINT messages, if VERBOSE is enabled!
+ */
+ at interface MyCALayer: CALayer
+{
+}
+- (id)init;
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+- (void)dealloc;
+#endif
+- (id<CAAction>)actionForKey:(NSString *)key ;
+
+ at end
+
+ at implementation MyCALayer
+
+- (id)init
+{
+    DBG_PRINT("MyCALayer::init.0\n");
+    MyCALayer * o = [super init];
+    DBG_PRINT("MyCALayer::init.X: new %p\n", o);
+    return o;
+}
+
+#ifdef DBG_LIFECYCLE
+
+- (id)retain
+{
+    DBG_PRINT("MyCALayer::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+    // NSLog(@"MyCALayer::retain: %@",[NSThread callStackSymbols]);
+    id o = [super retain];
+    DBG_PRINT("MyCALayer::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+    return o;
+}
+
+- (oneway void)release
+{
+    DBG_PRINT("MyCALayer::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+    // NSLog(@"MyCALayer::release: %@",[NSThread callStackSymbols]);
+    [super release];
+    // DBG_PRINT("MyCALayer::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+- (void)dealloc
+{
+    DBG_PRINT("MyCALayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
+    // NSLog(@"MyCALayer::dealloc: %@",[NSThread callStackSymbols]);
+    [super dealloc];
+    // DBG_PRINT("MyCALayer.dealloc.X: %p\n", self);
+}
+
+#endif
+
+- (id<CAAction>)actionForKey:(NSString *)key 
+{
+    DBG_PRINT("MyCALayer::actionForKey.0 %p key %s -> NIL\n", self, [key UTF8String]);
+    return nil;
+    // return [super actionForKey: key];
+}
+
+ at end
+
 /*
  * Class:     Java_jogamp_nativewindow_macosx_OSXUtil
  * Method:    CreateCALayer0
@@ -323,8 +402,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
-    CALayer* layer = [[CALayer alloc] init];
-    DBG_PRINT("CALayer::CreateCALayer.0: %p %d/%d %dx%d (refcnt %d)\n", layer, (int)x, (int)y, (int)width, (int)height, (int)[layer retainCount]);
+    MyCALayer* layer = [[MyCALayer alloc] init];
+    DBG_PRINT("CALayer::CreateCALayer.0: root %p %d/%d %dx%d (refcnt %d)\n", layer, (int)x, (int)y, (int)width, (int)height, (int)[layer retainCount]);
     // avoid zero size
     if(0 == width) { width = 32; }
     if(0 == height) { height = 32; }
@@ -339,59 +418,124 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
     // no animations for add/remove/swap sublayers etc 
     // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
     [layer removeAllAnimations];
+    // [layer addAnimation:nil forKey:kCATransition];
     [layer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
     [layer setNeedsDisplayOnBoundsChange: YES];
-    DBG_PRINT("CALayer::CreateCALayer.1: %p %lf/%lf %lfx%lf\n", layer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height);
-    DBG_PRINT("CALayer::CreateCALayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
-
+    DBG_PRINT("CALayer::CreateCALayer.1: root %p %lf/%lf %lfx%lf\n", layer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height);
     [pool release];
+    DBG_PRINT("CALayer::CreateCALayer.X: root %p (refcnt %d)\n", layer, (int)[layer retainCount]);
 
     return (jlong) ((intptr_t) layer);
 }
 
+static void FixCALayerLayout0(MyCALayer* rootLayer, CALayer* subLayer, jint width, jint height) {
+    if( NULL != rootLayer ) {
+        CGRect lRect = [rootLayer frame];
+        if(lRect.origin.x!=0 || lRect.origin.y!=0 || lRect.size.width!=width || lRect.size.height!=height) {
+            DBG_PRINT("CALayer::FixCALayerLayout0.0: Root %p frame %lf/%lf %lfx%lf -> 0/0 %dx%d\n",
+                rootLayer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)width, (int)height);
+            lRect.origin.x = 0;
+            lRect.origin.y = 0;
+            lRect.size.width = width;
+            lRect.size.height = height;
+            [rootLayer setFrame: lRect];
+        }
+    }
+    if( NULL != subLayer ) {
+        CGRect lRect = [subLayer frame];
+        if(lRect.origin.x!=0 || lRect.origin.y!=0 || lRect.size.width!=width || lRect.size.height!=height) {
+            DBG_PRINT("CALayer::FixCALayerLayout0.0: SubL %p frame %lf/%lf %lfx%lf -> 0/0 %dx%d\n",
+                subLayer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)width, (int)height);
+            lRect.origin.x = 0;
+            lRect.origin.y = 0;
+            lRect.size.width = width;
+            lRect.size.height = height;
+            if( [subLayer conformsToProtocol:@protocol(NWDedicatedSize)] ) {
+                CALayer <NWDedicatedSize> * subLayerDS = (CALayer <NWDedicatedSize> *) subLayer;
+                [subLayerDS setDedicatedSize: lRect.size];
+            } else {
+                [subLayer setFrame: lRect];
+            }
+        } 
+    }
+}
+
 /*
  * Class:     Java_jogamp_nativewindow_macosx_OSXUtil
  * Method:    AddCASublayer0
- * Signature: (JJ)V
+ * Signature: (JJII)V
  */
 JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0
-  (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer)
+  (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer, jint width, jint height)
 {
-    JNF_COCOA_ENTER(env);
-    CALayer* rootLayer = (CALayer*) ((intptr_t) rootCALayer);
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    MyCALayer* rootLayer = (MyCALayer*) ((intptr_t) rootCALayer);
     CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
 
+    [CATransaction begin];
+    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+    [rootLayer retain]; // Pairs w/ RemoveCASublayer
+    [subLayer retain]; // Pairs w/ RemoveCASublayer
+
     CGRect lRectRoot = [rootLayer frame];
-    DBG_PRINT("CALayer::AddCASublayer0.0: Origin %p frame0: %lf/%lf %lfx%lf\n", 
+    DBG_PRINT("CALayer::AddCASublayer0.0: Origin %p frame0: %lf/%lf %lfx%lf\n",
         rootLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height);
     if(lRectRoot.origin.x!=0 || lRectRoot.origin.y!=0) {
         lRectRoot.origin.x = 0;
         lRectRoot.origin.y = 0;
-        [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
-            [rootLayer setFrame: lRectRoot];
-        }];
+        [rootLayer setFrame: lRectRoot];
         DBG_PRINT("CALayer::AddCASublayer0.1: Origin %p frame*: %lf/%lf %lfx%lf\n", 
             rootLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height);
     }
-    DBG_PRINT("CALayer::AddCASublayer0.2: %p . %p %lf/%lf %lfx%lf (refcnt %d)\n", 
-        rootLayer, subLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height, (int)[subLayer retainCount]);
-
-    [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
-        // simple 1:1 layout !
-        [subLayer setFrame:lRectRoot];
-        [rootLayer addSublayer:subLayer];
-
-        // no animations for add/remove/swap sublayers etc 
-        // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
-        [rootLayer removeAllAnimations];
-        [rootLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
-        [rootLayer setNeedsDisplayOnBoundsChange: YES];
-        [subLayer removeAllAnimations];
-        [subLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
-        [subLayer setNeedsDisplayOnBoundsChange: YES];
-    }];
-    DBG_PRINT("CALayer::AddCASublayer0.X: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]);
-    JNF_COCOA_EXIT(env);
+    DBG_PRINT("CALayer::AddCASublayer0.2: root %p (refcnt %d) .sub %p %lf/%lf %lfx%lf (refcnt %d)\n", 
+        rootLayer, (int)[rootLayer retainCount],
+        subLayer, lRectRoot.origin.x, lRectRoot.origin.y, lRectRoot.size.width, lRectRoot.size.height, (int)[subLayer retainCount]);
+
+    // simple 1:1 layout !
+    [subLayer setFrame:lRectRoot];
+    [rootLayer addSublayer:subLayer];
+
+    // no animations for add/remove/swap sublayers etc 
+    // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
+    [rootLayer removeAllAnimations];
+    // [rootLayer addAnimation:nil forKey:kCATransition]; // JAU
+    [rootLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+    [rootLayer setNeedsDisplayOnBoundsChange: YES];
+    [subLayer removeAllAnimations];
+    // [subLayer addAnimation:nil forKey:kCATransition]; // JAU
+    [subLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+    [subLayer setNeedsDisplayOnBoundsChange: YES];
+
+    FixCALayerLayout0(rootLayer, subLayer, width, height);
+
+    [CATransaction commit];
+
+    [pool release];
+    DBG_PRINT("CALayer::AddCASublayer0.X: root %p (refcnt %d) .sub %p (refcnt %d)\n", 
+        rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount]);
+}
+
+/*
+ * Class:     Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method:    FixCALayerLayout0
+ * Signature: (JJII)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_FixCALayerLayout0
+  (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer, jint width, jint height)
+{
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    MyCALayer* rootLayer = (MyCALayer*) ((intptr_t) rootCALayer);
+    CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
+
+    [CATransaction begin];
+    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+    FixCALayerLayout0(rootLayer, subLayer, width, height);
+
+    [CATransaction commit];
+
+    [pool release];
 }
 
 /*
@@ -402,18 +546,27 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0
 JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RemoveCASublayer0
   (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer)
 {
-    JNF_COCOA_ENTER(env);
-    CALayer* rootLayer = (CALayer*) ((intptr_t) rootCALayer);
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    MyCALayer* rootLayer = (MyCALayer*) ((intptr_t) rootCALayer);
     CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
 
     (void)rootLayer; // no warnings
 
-    DBG_PRINT("CALayer::RemoveCASublayer0.0: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]);
-    [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
-        [subLayer removeFromSuperlayer];
-    }];
-    DBG_PRINT("CALayer::RemoveCASublayer0.X: %p . %p\n", rootLayer, subLayer);
-    JNF_COCOA_EXIT(env);
+    DBG_PRINT("CALayer::RemoveCASublayer0.0: root %p (refcnt %d) .sub %p (refcnt %d)\n", 
+        rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount]);
+
+    [CATransaction begin];
+    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+    [subLayer removeFromSuperlayer];
+    [subLayer release]; // Pairs w/ AddCASublayer
+    [rootLayer release]; // Pairs w/ AddCASublayer
+
+    [CATransaction commit];
+
+    [pool release];
+    DBG_PRINT("CALayer::RemoveCASublayer0.X: root %p (refcnt %d) .sub %p (refcnt %d)\n", 
+        rootLayer, (int)[rootLayer retainCount], subLayer, (int)[subLayer retainCount]);
 }
 
 /*
@@ -424,73 +577,90 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RemoveCASublayer0
 JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyCALayer0
   (JNIEnv *env, jclass unused, jlong caLayer)
 {
-    JNF_COCOA_ENTER(env);
-    CALayer* layer = (CALayer*) ((intptr_t) caLayer);
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    MyCALayer* layer = (MyCALayer*) ((intptr_t) caLayer);
+
+    [CATransaction begin];
+    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
 
-    DBG_PRINT("CALayer::DestroyCALayer0.0: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
-    [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
-        [layer release]; // performs release!
-    }];
-    DBG_PRINT("CALayer::DestroyCALayer0.X: %p\n", layer);
-    JNF_COCOA_EXIT(env);
+    DBG_PRINT("CALayer::DestroyCALayer0.0: root %p (refcnt %d)\n", layer, (int)[layer retainCount]);
+    [layer release]; // Trigger release and dealloc of root CALayer, it's child etc ..
+
+    [CATransaction commit];
+
+    [pool release];
+    DBG_PRINT("CALayer::DestroyCALayer0.X: root %p\n", layer);
 }
 
 /*
  * Class:     Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
- * Method:    SetJAWTRootSurfaceLayer0
- * Signature: (JJ)Z
+ * Method:    GetJAWTSurfaceLayersHandle0
+ * Signature: (J)J
  */
-JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0
-  (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_GetJAWTSurfaceLayersHandle0
+  (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer)
 {
-    JNF_COCOA_ENTER(env);
     JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
     if (NULL == dsi) {
         NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
-        return JNI_FALSE;
+        return 0;
     }
-    CALayer* layer = (CALayer*) (intptr_t) caLayer;
-    [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
-        id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
-        DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: %p -> %p (refcnt %d)\n", surfaceLayers.layer, layer, (int)[layer retainCount]);
-        surfaceLayers.layer = layer; // already incr. retain count
-        DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
-    }];
-    JNF_COCOA_EXIT(env);
-    return JNI_TRUE;
+    id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
+    return (jlong) ((intptr_t) surfaceLayers);
+}
+
+/*
+ * Class:     Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
+ * Method:    SetJAWTRootSurfaceLayer0
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0
+  (JNIEnv *env, jclass unused, jlong jawtSurfaceLayersHandle, jlong caLayer)
+{
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+    [CATransaction begin];
+    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+    id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)(intptr_t)jawtSurfaceLayersHandle;
+    MyCALayer* layer = (MyCALayer*) (intptr_t) caLayer;
+    DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: pre %p -> root %p (refcnt %d)\n", [surfaceLayers layer], layer, (int)[layer retainCount]);
+    [surfaceLayers setLayer: [layer retain]]; // Pairs w/ Unset
+
+    [CATransaction commit];
+
+    [pool release];
+    DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.X: root %p (refcnt %d)\n", layer, (int)[layer retainCount]);
 }
 
 /*
  * Class:     Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
  * Method:    UnsetJAWTRootSurfaceLayer0
- * Signature: (JJ)Z
-JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0
-  (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0
+  (JNIEnv *env, jclass unused, jlong jawtSurfaceLayersHandle, jlong caLayer)
 {
-    JNF_COCOA_ENTER(env);
-    JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
-    if (NULL == dsi) {
-        NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
-        return JNI_FALSE;
-    }
-    CALayer* layer = (CALayer*) (intptr_t) caLayer;
-    {
-        id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
-        if(layer != surfaceLayers.layer) {
-            NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer);
-            return JNI_FALSE;
-        }
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+    [CATransaction begin];
+    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+    id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)(intptr_t)jawtSurfaceLayersHandle;
+    MyCALayer* layer = (MyCALayer*) (intptr_t) caLayer;
+    if(layer != [surfaceLayers layer]) {
+        NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer);
+        return;
     }
-    // [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
-        id <JAWT_SurfaceLayers> surfaceLayers = (id <JAWT_SurfaceLayers>)dsi->platformInfo;
-        DBG_PRINT("CALayer::detachJAWTSurfaceLayer: (%p) %p -> NULL\n", layer, surfaceLayers.layer);
-        surfaceLayers.layer = NULL;
-        [layer release];
-    // }];
-    JNF_COCOA_EXIT(env);
-    return JNI_TRUE;
+    DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.0: root %p (refcnt %d) -> nil\n", layer, (int)[layer retainCount]);
+    [layer release]; // Pairs w/ Set
+    [surfaceLayers setLayer: NULL];
+
+    [CATransaction commit];
+
+    [pool release];
+    DBG_PRINT("CALayer::UnsetJAWTRootSurfaceLayer.X: root %p (refcnt %d) -> nil\n", layer, (int)[layer retainCount]);
 }
- */
 
 @interface MainRunnable : NSObject
 
@@ -503,6 +673,13 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
 - (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers;
 - (void) jRun;
 
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+- (void)dealloc;
+#endif
+
+
 @end
 
 @implementation MainRunnable
@@ -518,33 +695,59 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
 - (void) jRun
 {
     int shallBeDetached = 0;
-    JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+    JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached);
+    DBG_PRINT2("MainRunnable.1 env: %d\n", (int)(NULL!=env));
     if(NULL!=env) {
+        DBG_PRINT2("MainRunnable.1.0\n");
         (*env)->CallVoidMethod(env, runnableObj, runnableRunID);
+        DBG_PRINT2("MainRunnable.1.1\n");
+        (*env)->DeleteGlobalRef(env, runnableObj);
 
         if (shallBeDetached) {
-            (*jvmHandle)->DetachCurrentThread(jvmHandle);
+            DBG_PRINT2("MainRunnable.1.3\n");
+            // Keep attached on main thread !
+            // (*jvmHandle)->DetachCurrentThread(jvmHandle);
         }
     }
+    DBG_PRINT2("MainRunnable.X\n");
 }
 
- at end
+#ifdef DBG_LIFECYCLE
 
+- (id)retain
+{
+    DBG_PRINT2("MainRunnable::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+    id o = [super retain];
+    DBG_PRINT2("MainRunnable::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+    return o;
+}
 
-/*
- * Class:     Java_jogamp_nativewindow_macosx_OSXUtil
- * Method:    RunOnMainThread0
- * Signature: (ZLjava/lang/Runnable;)V
- */
-JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0
-  (JNIEnv *env, jclass unused, jboolean jwait, jobject runnable)
+- (oneway void)release
 {
-    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    DBG_PRINT2("MainRunnable::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+    [super release];
+    // DBG_PRINT2("MainRunnable::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+- (void)dealloc
+{
+    DBG_PRINT2("MainRunnable::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
+    [super dealloc];
+    // DBG_PRINT2("MainRunnable.dealloc.X: %p\n", self);
+}
+
+#endif
+
+ at end
+
+static void RunOnThread (JNIEnv *env, jobject runnable, BOOL onMain, jint delayInMS)
+{
+    DBG_PRINT2( "RunOnThread0: isMainThread %d, NSApp %d, NSApp-isRunning %d, onMain %d, delay %dms\n", 
+        (int)([NSThread isMainThread]), (int)(NULL!=NSApp), (int)([NSApp isRunning]), (int)onMain, (int)delayInMS);
 
-    if ( NO == [NSThread isMainThread] ) {
-        jobject runnableGlob = (*env)->NewGlobalRef(env, runnable);
+    if ( !onMain || NO == [NSThread isMainThread] ) {
+        jobject runnableObj = (*env)->NewGlobalRef(env, runnable);
 
-        BOOL wait = (JNI_TRUE == jwait) ? YES : NO;
         JavaVM *jvmHandle = NULL;
         int jvmVersion = 0;
 
@@ -554,21 +757,56 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0
             jvmVersion = (*env)->GetVersion(env);
         }
 
-        MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableGlob jvmHandle: jvmHandle jvmVersion: jvmVersion];
-        [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:wait];
+        DBG_PRINT2( "RunOnThread.1.0\n");
+        MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj jvmHandle: jvmHandle jvmVersion: jvmVersion];
+
+        if( onMain ) {
+            [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO];
+        } else {
+            NSTimeInterval delay = (double)delayInMS/1000.0;
+            [mr performSelector:@selector(jRun) withObject:nil afterDelay:delay];
+        }
+        DBG_PRINT2( "RunOnThread.1.1\n");
+
         [mr release];
+        DBG_PRINT2( "RunOnThread.1.2\n");
 
-        (*env)->DeleteGlobalRef(env, runnableGlob);
     } else {
+        DBG_PRINT2( "RunOnThread.2\n");
         (*env)->CallVoidMethod(env, runnable, runnableRunID);
     }
+    DBG_PRINT2( "RunOnThread.X\n");
+}
 
+/*
+ * Class:     Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method:    RunOnMainThread0
+ * Signature: (ZLjava/lang/Runnable;)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0
+  (JNIEnv *env, jclass unused, jobject runnable)
+{
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    RunOnThread (env, runnable, YES, 0);
     [pool release];
 }
 
 /*
  * Class:     Java_jogamp_nativewindow_macosx_OSXUtil
- * Method:    RunOnMainThread0
+ * Method:    RunLater0
+ * Signature: (ZLjava/lang/Runnable;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunLater0
+  (JNIEnv *env, jclass unused, jobject runnable, jint delay)
+{
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    RunOnThread (env, runnable, NO, delay);
+    [pool release];
+}
+
+/*
+ * Class:     Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method:    IsMainThread0
  * Signature: (V)V
  */
 JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_IsMainThread0
@@ -614,13 +852,12 @@ JNIEXPORT jint JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenRefreshR
   (JNIEnv *env, jclass unused, jint scrn_idx)
 {
     int res = 0;
-    JNF_COCOA_ENTER(env);
-    // NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
     NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
     DBG_PRINT("GetScreenRefreshRate.0: screen %p\n", (void *)screen);
     if(NULL != screen) {
         CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
-        DBG_PRINT("GetScreenRefreshRate.1: display %p\n", (void *)display);
+        DBG_PRINT("GetScreenRefreshRate.1: display %p\n", (void *)(intptr_t)display);
         if(0 != display) {
             CFDictionaryRef mode = CGDisplayCurrentMode(display);
             DBG_PRINT("GetScreenRefreshRate.2: mode %p\n", (void *)mode);
@@ -633,9 +870,8 @@ JNIEXPORT jint JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenRefreshR
     if(0 == res) {
         res = 60; // default .. (experienced on OSX 10.6.8)
     }
-    DBG_PRINT(stderr, "GetScreenRefreshRate.X: %d\n", res);
-    // [pool release];
-    JNF_COCOA_EXIT(env);
+    DBG_PRINT("GetScreenRefreshRate.X: %d\n", (int)res);
+    [pool release];
     return res;
 }
 
diff --git a/src/nativewindow/native/win32/DeviceDriverQuery.txt b/src/nativewindow/native/win32/DeviceDriverQuery.txt
new file mode 100644
index 0000000..7401ed8
--- /dev/null
+++ b/src/nativewindow/native/win32/DeviceDriverQuery.txt
@@ -0,0 +1,41 @@
+    
+    // INCOMPLETE !
+    // 
+    // See Bug 706 and Bug 520
+    //   https://jogamp.org/bugzilla/show_bug.cgi?id=520
+    //   https://jogamp.org/bugzilla/show_bug.cgi?id=706
+    //
+    // Device Driver SDK
+    //   http://msdn.microsoft.com/en-us/library/ff553567.aspx#ddk_setupdi_device_information_functions_dg
+    {
+        /**
+            System-Defined Device Setup Classes Available to Vendors (GUID)
+
+            Display Adapters
+                    Class = Display
+                    ClassGuid = {4d36e968-e325-11ce-bfc1-08002be10318}
+            This class includes video adapters. Drivers for this class include display drivers and video miniport drivers.
+
+            /opt-windows/mingw/include/devguid.h GUID_DEVCLASS_DISPLAY
+            GUID_DEVCLASS_DISPLAY
+            HDEVINFO SetupDiGetClassDevs(
+              _In_opt_  const GUID *ClassGuid,
+              _In_opt_  PCTSTR Enumerator,
+              _In_opt_  HWND hwndParent,
+              _In_      DWORD Flags
+              );
+
+        */
+        const GUID devClassDisplay = GUID_DEVCLASS_DISPLAY;
+        // http://msdn.microsoft.com/en-us/library/ff551069.aspx
+        HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_DISPLAY, NULL /* bus */, NULL /* windows */, DIGCF_PRESENT | DIGCF_PROFILE  /* flags */); 
+        DWORD MemberIndex = 0;
+        SP_DEVINFO_DATA DeviceInfoData;
+        DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+        while( TRUE == SetupDiEnumDeviceInfo(DeviceInfoSet, MemberIndex, &DeviceInfoData) ) {
+            SetupDiGetSelectedDevice();
+            MemberIndex++;
+        }
+        SetupDiDestroyDeviceInfoList(hDevInfo);
+    }
+
diff --git a/src/nativewindow/native/win32/GDImisc.c b/src/nativewindow/native/win32/GDImisc.c
index 3ab7f98..23be473 100644
--- a/src/nativewindow/native/win32/GDImisc.c
+++ b/src/nativewindow/native/win32/GDImisc.c
@@ -224,3 +224,29 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_windows_GDIUtil_GetRelativeLo
     return (*env)->NewObject(env, pointClz, pointCstr, (jint)dest.x, (jint)dest.y);
 }
 
+/*
+ * Class:     jogamp_nativewindow_windows_GDIUtil
+ * Method:    IsChild0
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_IsChild0
+  (JNIEnv *env, jclass unused, jlong jwin)
+{
+    HWND hwnd = (HWND) (intptr_t) jwin;
+    LONG style = GetWindowLong(hwnd, GWL_STYLE);
+    BOOL bIsChild = 0 != (style & WS_CHILD) ;
+    return bIsChild ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class:     jogamp_nativewindow_windows_GDIUtil
+ * Method:    IsUndecorated0
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_IsUndecorated0
+  (JNIEnv *env, jclass unused, jlong jwin)
+{
+    HWND hwnd = (HWND) (intptr_t) jwin;
+    LONG style = GetWindowLong(hwnd, GWL_STYLE);
+    BOOL bIsUndecorated = 0 != (style & (WS_CHILD|WS_POPUP)) ;
+    return bIsUndecorated ? JNI_TRUE : JNI_FALSE;
+}
+
diff --git a/src/nativewindow/native/win32/WindowsDWM.h b/src/nativewindow/native/win32/WindowsDWM.h
index 36f82fc..6e5160f 100644
--- a/src/nativewindow/native/win32/WindowsDWM.h
+++ b/src/nativewindow/native/win32/WindowsDWM.h
@@ -4,6 +4,8 @@
     #include <windows.h> 
 
     #define DWM_BB_ENABLE                 0x00000001  // fEnable has been specified  
+    #define DWM_BB_BLURREGION             0x00000002
+    #define DWM_BB_TRANSITIONONMAXIMIZED  0x00000004
     #define DWM_EC_DISABLECOMPOSITION     0
     #define DWM_EC_ENABLECOMPOSITION      1
       
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 129baac..31620d7 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -31,6 +31,8 @@
 #include "jogamp_nativewindow_x11_X11Lib.h"
 #include "jogamp_nativewindow_x11_X11Util.h"
 
+#include <X11/Xatom.h>
+
 // #define VERBOSE_ON 1
 
 #ifdef VERBOSE_ON
@@ -85,6 +87,8 @@ Bool XF86VidModeSetGammaRamp(
 #define RTLD_DEFAULT NULL
 #endif
 
+#define X11_MOUSE_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask)
+
 static const char * const ClazzNameBuffers = "com/jogamp/common/nio/Buffers";
 static const char * const ClazzNameBuffersStaticCstrName = "copyByteBuffer";
 static const char * const ClazzNameBuffersStaticCstrSignature = "(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;";
@@ -170,13 +174,13 @@ static void setupJVMVars(JNIEnv * env) {
 }
 
 static XErrorHandler origErrorHandler = NULL ;
-static int errorHandlerQuiet = 0 ;
+static int errorHandlerQuiet = 1 ;
 static int errorHandlerDebug = 0 ;
 static int errorHandlerThrowException = 0;
 
 static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
 {
-    if(!errorHandlerQuiet) {
+    if( !errorHandlerQuiet || errorHandlerDebug ) {
         const char * errnoStr = strerror(errno);
         char errCodeStr[80];
         char reqCodeStr[80];
@@ -193,7 +197,7 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
         fflush(stderr);
 
         if( NULL != jvmHandle && ( errorHandlerDebug || errorHandlerThrowException ) ) {
-            jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+            jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached);
             if(NULL == jniEnv) {
                 fprintf(stderr, "Nativewindow X11 Error: null JNIEnv");
                 fflush(stderr);
@@ -220,12 +224,16 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
     return 0;
 }
 
-void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync) {
+static void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int force, int onoff, int quiet, int sync) {
     errorHandlerQuiet = quiet;
     if(onoff) {
-        if(NULL==origErrorHandler) {
+        if(force || NULL==origErrorHandler) {
+            XErrorHandler prevErrorHandler;
             setupJVMVars(env);
-            origErrorHandler = XSetErrorHandler(x11ErrorHandler);
+            prevErrorHandler = XSetErrorHandler(x11ErrorHandler);
+            if(x11ErrorHandler != prevErrorHandler) { // if forced don't overwrite w/ orig w/ our handler
+                origErrorHandler = prevErrorHandler;
+            }
             if(sync && NULL!=dpy) {
                 XSync(dpy, False);
             }
@@ -254,7 +262,7 @@ static int x11IOErrorHandler(Display *dpy)
     fflush(stderr);
 
     if( NULL != jvmHandle ) {
-        jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+        jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached);
         if (NULL != jniEnv) {
             NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr);
             if (shallBeDetached) {
@@ -292,7 +300,7 @@ Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboo
 
         _initClazzAccess(env);
         x11IOErrorHandlerEnable(1, env);
-        NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 0, 0 /* no dpy, no sync */);
+        NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 1, debug ? 0 : 1, 0 /* no dpy, force, no sync */);
         _initialized=1;
         if(JNI_TRUE == debug) {
             fprintf(stderr, "Info: NativeWindow native init passed\n");
@@ -303,13 +311,13 @@ Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboo
 
 JNIEXPORT void JNICALL 
 Java_jogamp_nativewindow_x11_X11Util_shutdown0(JNIEnv *env, jclass _unused) {
-    NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0 /* no dpy, no sync */);
+    NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, errorHandlerQuiet, 0 /* no dpy, no sync */);
     x11IOErrorHandlerEnable(0, env);
 }
 
 JNIEXPORT void JNICALL 
 Java_jogamp_nativewindow_x11_X11Util_setX11ErrorHandler0(JNIEnv *env, jclass _unused, jboolean onoff, jboolean quiet) {
-    NativewindowCommon_x11ErrorHandlerEnable(env, NULL, onoff ? 1 : 0, quiet ? 1 : 0, 0 /* no dpy, no sync */);
+    NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, onoff ? 1 : 0, quiet ? 1 : 0, 0 /* no dpy, force, no sync */);
 }
 
 /*   Java->C glue code:
@@ -334,9 +342,9 @@ Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Lja
   if (arg3 != NULL) {
     _ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset);
   }
-  NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 1, 0, 0);
+  NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 1, errorHandlerQuiet, 0);
   _res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
-  // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, 0);
+  // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, errorHandlerQuiet, 0);
   count = _ptr3[0];
   if (arg3 != NULL) {
     (*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
@@ -363,7 +371,7 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
         return;
     }
 
-    NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 1);
+    NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 1);
     memset(&xwa, 0, sizeof(XWindowAttributes));
     XGetWindowAttributes(dpy, w, &xwa);
     if(NULL != xwa.visual) {
@@ -371,7 +379,7 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
     } else {
         r = 0;
     }
-    // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+    // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
 
     return r;
 }
@@ -383,9 +391,9 @@ Java_jogamp_nativewindow_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused,
     if(0==display) {
         NativewindowCommon_FatalError(env, "invalid display connection..");
     }
-  NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 1, 0, 0);
+  NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 1, errorHandlerQuiet, 0);
   r = (jint) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) );
-  // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, 0);
+  // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, errorHandlerQuiet, 0);
   return r;
 }
 
@@ -426,23 +434,68 @@ Java_jogamp_nativewindow_x11_X11Lib_XCloseDisplay__J(JNIEnv *env, jclass _unused
   if(0==display) {
       NativewindowCommon_FatalError(env, "invalid display connection..");
   }
-  NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 0, 0);
+  NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 1, errorHandlerQuiet, 0);
   _res = XCloseDisplay((Display *) (intptr_t) display);
-  // NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0);
+  // NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, errorHandlerQuiet, 0);
   return _res;
 }
 
+static void NativewindowX11_setNormalWindowEWMH (Display *dpy, Window w) {
+    Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False );
+    Atom types[1]={0};
+    types[0] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False );
+    XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, 1);
+    XSync(dpy, False);
+}
+
+#define DECOR_USE_MWM 1     // works for known WMs
+// #define DECOR_USE_EWMH 1 // haven't seen this to work (NORMAL->POPUP, never gets undecorated)
+
+/* see <http://tonyobryan.com/index.php?article=9> */
+#define MWM_HINTS_DECORATIONS   (1L << 1)
+#define PROP_MWM_HINTS_ELEMENTS 5
+
+static void NativewindowX11_setDecorations (Display *dpy, Window w, Bool decorated) {
+
+#ifdef DECOR_USE_MWM
+    unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status
+    Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False );
+#endif
+
+#ifdef DECOR_USE_EWMH
+    Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False );
+    Atom types[3]={0};
+    int ntypes=0;
+    if(True==decorated) {
+        types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False );
+    } else {
+        types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", False );
+    }
+#endif
+
+#ifdef DECOR_USE_MWM
+    XChangeProperty( dpy, w, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS);
+#endif
+
+#ifdef DECOR_USE_EWMH
+    XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
+#endif
+
+    XSync(dpy, False);
+}
+
 /*
  * Class:     jogamp_nativewindow_x11_X11Lib
- * Method:    CreateDummyWindow
- * Signature: (JIIII)J
+ * Method:    CreateWindow
+ * Signature: (JJIIIIZZ)J
  */
-JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
-  (JNIEnv *env, jclass unused, jlong display, jint screen_index, jint visualID, jint width, jint height)
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateWindow
+  (JNIEnv *env, jclass unused, jlong parent, jlong display, jint screen_index, jint visualID, jint width, jint height, jboolean input, jboolean visible)
 {
     Display * dpy  = (Display *)(intptr_t)display;
     int       scrn_idx = (int)screen_index;
-    Window  windowParent = 0;
+    Window root = RootWindow(dpy, scrn_idx);
+    Window  windowParent = (Window) parent;
     Window  window = 0;
 
     XVisualInfo visualTemplate;
@@ -466,9 +519,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
         return 0;
     }
 
-    NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+    NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
 
     scrn = ScreenOfDisplay(dpy, scrn_idx);
+    if(0==windowParent) {
+        windowParent = root;
+    }
 
     // try given VisualID on screen
     memset(&visualTemplate, 0, sizeof(XVisualInfo));
@@ -486,7 +542,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
 
     if (visual==NULL)
     { 
-        // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+        // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
         NativewindowCommon_throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!");
         return 0;
     } 
@@ -496,9 +552,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
         pVisualQuery=NULL;
     }
 
-    if(0==windowParent) {
-        windowParent = XRootWindowOfScreen(scrn);
-    }
 
     attrMask  = ( CWBackingStore | CWBackingPlanes | CWBackingPixel | CWBackPixmap | 
                   CWBorderPixel | CWColormap | CWOverrideRedirect ) ;
@@ -510,15 +563,22 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
     xswa.backing_store=NotUseful; /* NotUseful, WhenMapped, Always */
     xswa.backing_planes=0;        /* planes to be preserved if possible */
     xswa.backing_pixel=0;         /* value to use in restoring planes */
+    if( input ) {
+        xswa.event_mask  = X11_MOUSE_EVENT_MASK;
+        xswa.event_mask |= KeyPressMask | KeyReleaseMask ;
+    }
+    if( visible ) {
+        xswa.event_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask ;
+    }
 
     xswa.colormap = XCreateColormap(dpy,
-                                    XRootWindow(dpy, scrn_idx),
+                                    windowParent,
                                     visual,
                                     AllocNone);
 
     window = XCreateWindow(dpy,
                            windowParent,
-                           0, 0,
+                           0, 0, // only a hint, WM most likely will override
                            width, height,
                            0, // border width
                            depth,
@@ -526,11 +586,27 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
                            visual,
                            attrMask,
                            &xswa);
+    if(0==window) {
+        NativewindowCommon_throwNewRuntimeException(env, "could not create Window, bail out!");
+        return 0;
+    }
+
+    NativewindowX11_setNormalWindowEWMH(dpy, window);
+    NativewindowX11_setDecorations(dpy, window, False);
+
+    if( visible ) {
+        XEvent event;
+
+        XMapWindow(dpy, window);
+    }
+
     XSync(dpy, False);
 
-    XSelectInput(dpy, window, 0); // no events
+    if( !input ) {
+        XSelectInput(dpy, window, 0); // no events
+    }
 
-    // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+    // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
 
     DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", window, dpy);
 
@@ -540,25 +616,57 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
 
 /*
  * Class:     jogamp_nativewindow_x11_X11Lib
- * Method:    DestroyDummyWindow
+ * Method:    DestroyWindow
  * Signature: (JJ)V
  */
-JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyDummyWindow
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyWindow
   (JNIEnv *env, jclass unused, jlong display, jlong window)
 {
     Display * dpy = (Display *)(intptr_t)display;
     Window      w = (Window) window;
+    XWindowAttributes xwa;
 
     if(NULL==dpy) {
         NativewindowCommon_throwNewRuntimeException(env, "invalid display connection..");
         return;
     }
 
-    NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+    NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
+    XSync(dpy, False);
+    memset(&xwa, 0, sizeof(XWindowAttributes));
+    XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction
+    XSelectInput(dpy, w, 0);
     XUnmapWindow(dpy, w);
     XSync(dpy, False);
     XDestroyWindow(dpy, w);
-    // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+    if( None != xwa.colormap ) {
+        XFreeColormap(dpy, xwa.colormap);
+    }
+    // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
+}
+
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_SetWindowPosSize
+  (JNIEnv *env, jclass unused, jlong display, jlong window, jint x, jint y, jint width, jint height) {
+    Display * dpy = (Display *)(intptr_t)display;
+    Window      w = (Window) window;
+    XWindowChanges xwc;
+    int flags = 0;
+    
+    memset(&xwc, 0, sizeof(XWindowChanges));
+
+    if(0<=x && 0<=y) {
+        flags |= CWX | CWY;
+        xwc.x=x;
+        xwc.y=y;
+    }
+
+    if(0<width && 0<height) {
+        flags |= CWWidth | CWHeight;
+        xwc.width=width;
+        xwc.height=height;
+    }
+    XConfigureWindow(dpy, w, flags, &xwc);
+    XSync(dpy, False);
 }
 
 /*
@@ -582,11 +690,11 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_x11_X11Lib_GetRelativeLocatio
     if( 0 == jdest_win ) { dest_win = root; }
     if( 0 == jsrc_win ) { src_win = root; }
 
-    NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 1, 0, 0);
+    NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
 
     res = XTranslateCoordinates(dpy, src_win, dest_win, src_x, src_y, &dest_x, &dest_y, &child);
 
-    // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0);
+    // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 0);
 
     DBG_PRINT( "X11: GetRelativeLocation0: %p %d/%d -> %p %d/%d - ok: %d\n",
         (void*)src_win, src_x, src_y, (void*)dest_win, dest_x, dest_y, (int)res);
diff --git a/src/nativewindow/native/x11/Xmisc.h b/src/nativewindow/native/x11/Xmisc.h
index a44da95..91f2ac5 100644
--- a/src/nativewindow/native/x11/Xmisc.h
+++ b/src/nativewindow/native/x11/Xmisc.h
@@ -39,6 +39,4 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 
-void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy, int onoff, int quiet, int sync);
-
 #endif /* Xmisc_h */
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index e97dec8..d6ddd96 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -158,19 +158,15 @@ public abstract class Display {
      * </p>
      * <p>
      * If a previous one exists and it differs from the new one, 
-     * it's being stopped, wait-until-idle and reset to allow restart.
+     * it's being stopped, wait-until-idle and reset to allow a restart at a later time.
      * </p>
      * <p>
      * If <code>newEDTUtil</code> is not null and equals the previous one,
-     * <code>null</code> is returned and no change is being made.
+     * no change is being made.
      * </p>
      * <p>
-     * Note that <code>newEDTUtil</code> will not be started if not done so already,
-     * to do so you may issue {@link EDTUtil#invoke(boolean, Runnable) invoke} 
-     * on the new EDTUtil:
-     * <pre>
-     *          newEDTUtil.invoke(true, new Runnable() { public void run() { } } );
-     * </pre>
+     * Note that <code>newEDTUtil</code> will be started by this method,
+     * if it is not running yet.
      * </p>
      */
     public abstract EDTUtil setEDTUtil(EDTUtil newEDTUtil);
@@ -182,7 +178,7 @@ public abstract class Display {
     public abstract void dispatchMessages();
     
     // Global Displays
-    protected static ArrayList<Display> displayList = new ArrayList<Display>();
+    protected static final ArrayList<Display> displayList = new ArrayList<Display>();
     protected static int displaysActive = 0;
 
     public static void dumpDisplayList(String prefix) {
diff --git a/src/newt/classes/com/jogamp/newt/MonitorDevice.java b/src/newt/classes/com/jogamp/newt/MonitorDevice.java
new file mode 100644
index 0000000..4b0a760
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/MonitorDevice.java
@@ -0,0 +1,235 @@
+/**
+ * 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.newt;
+
+import java.util.List;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import com.jogamp.common.util.ArrayHashSet;
+
+/** 
+ * Visual output device, i.e. a CRT, LED ..consisting of it's components:<br>
+ * <ui>
+ *   <li>Immutable
+ *   <ul>
+ *     <li>nativeId</li>
+ *     <li>{@link DimensionImmutable} size in [mm]</li>
+ *     <li>{@link MonitorMode} original mode</li>
+ *     <li><code>List<MonitorMode></code> supportedModes</li>
+ *   </ul></li>
+ *   <li>Mutable
+ *   <ul>
+ *     <li>{@link MonitorMode} current mode</li>
+ *     <li>{@link RectangleImmutable} viewport (rotated)</li>
+ *   </ul></li>
+ * </ul>
+ */
+public abstract class MonitorDevice {
+    protected final Screen screen; // backref
+    protected final int nativeId; // unique monitor device ID 
+    protected final DimensionImmutable sizeMM; // in [mm]
+    protected final MonitorMode originalMode;
+    protected final ArrayHashSet<MonitorMode> supportedModes; // FIXME: May need to support mutable mode, i.e. adding modes on the fly!
+    protected MonitorMode currentMode;
+    protected boolean modeChanged;
+    protected Rectangle viewport;
+
+    protected MonitorDevice(Screen screen, int nativeId, DimensionImmutable sizeMM, Rectangle viewport, MonitorMode currentMode, ArrayHashSet<MonitorMode> supportedModes) {
+        this.screen = screen;
+        this.nativeId = nativeId;
+        this.sizeMM = sizeMM;
+        this.originalMode = currentMode;
+        this.supportedModes = supportedModes;
+        this.currentMode = currentMode;
+        this.viewport = viewport;
+        this.modeChanged = false;
+    }
+    
+    /** Returns the {@link Screen} owning this monitor. */
+    public final Screen getScreen() {
+        return screen;
+    }
+    
+    /**
+     * Tests equality of two <code>MonitorDevice</code> objects 
+     * by evaluating equality of it's components:<br>
+     * <ul>
+     *  <li><code>nativeID</code></li>
+     * </ul>
+     * <br>
+     */
+    public final boolean equals(Object obj) {
+        if (this == obj) { return true; }
+        if (obj instanceof MonitorDevice) {
+            MonitorDevice md = (MonitorDevice)obj;
+            return md.nativeId == nativeId;
+        }
+        return false;
+    }
+
+    /**
+     * Returns a combined hash code of it's elements:<br>
+     * <ul>
+     *  <li><code>nativeID</code></li>
+     * </ul>
+     */
+    public final int hashCode() {
+        return nativeId;
+    }
+    
+    /** @return the immutable unique native Id of this monitor device. */
+    public final int getId() { return nativeId; }
+    
+    /**
+     * @return the immutable monitor size in millimeters.
+     */
+    public final DimensionImmutable getSizeMM() {
+        return sizeMM;
+    }
+
+    /**
+     * Returns the immutable original {@link com.jogamp.newt.MonitorMode}, as used at NEWT initialization.
+     * <p>
+     * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+     * </p>
+     */
+    public final MonitorMode getOriginalMode() {
+        return originalMode;
+    }
+
+    /**
+     * Returns a list of immutable {@link MonitorMode}s supported by this monitor.
+     * <p>
+     * Use w/ care, it's not a copy!
+     * </p>
+     */
+    public final List<MonitorMode> getSupportedModes() {
+        return supportedModes.getData();
+    }
+
+    /** Returns the {@link RectangleImmutable rectangular} portion of the rotated virtual {@link Screen} size represented by this monitor. */  
+    public final RectangleImmutable getViewport() {
+        return viewport;
+    }
+    
+    /** Returns <code>true</code> if given coordinates are contained by this {@link #getViewport() viewport}, otherwise <code>false</code>. */
+    public final boolean contains(int x, int y) {
+        return x >= viewport.getX() &&
+               x <  viewport.getX() + viewport.getWidth() &&
+               y >= viewport.getY() &&
+               y <  viewport.getY() + viewport.getHeight() ;
+    }
+    
+    /** 
+     * Returns the coverage of given rectangle w/ this this {@link #getViewport() viewport}, i.e. between <code>0.0</code> and <code>1.0</code>.
+     * <p>
+     * Coverage is computed by:
+     * <pre>
+     *    isect = viewport.intersection(r);
+     *    coverage = area( isect ) / area( viewport ) ;
+     * </pre>
+     * </p> 
+     */
+    public final float coverage(RectangleImmutable r) {
+        return viewport.coverage(r);
+    }
+    
+    /**
+     * Returns the union of the given monitor's {@link #getViewport() viewport}.
+     * @param result storage for result, will be returned
+     * @param monitors given list of monitors
+     * @return viewport representing the union of given monitor's viewport.
+     */
+    public static Rectangle unionOfViewports(final Rectangle result, final List<MonitorDevice> monitors) {
+        int x1=Integer.MAX_VALUE, y1=Integer.MAX_VALUE;
+        int x2=Integer.MIN_VALUE, y2=Integer.MIN_VALUE;
+        for(int i=monitors.size()-1; i>=0; i--) {
+            final RectangleImmutable vp = monitors.get(i).getViewport();
+            x1 = Math.min(x1, vp.getX());
+            x2 = Math.max(x2, vp.getX() + vp.getWidth());
+            y1 = Math.min(y1, vp.getY());
+            y2 = Math.max(y2, vp.getY() + vp.getHeight());
+        }
+        result.setX(x1);
+        result.setY(y1);
+        result.setWidth(x2 - x1);
+        result.setHeight(y2 - y1);
+        return result;
+    }
+    
+    public final boolean isOriginalMode() {
+        return currentMode.hashCode() == originalMode.hashCode();
+    }
+    
+    /**
+     * Returns <code>true</true> if the {@link MonitorMode}
+     * has been changed programmatic via this API <i>only</i>, otherwise <code>false</code>. 
+     * <p>
+     * Note: We cannot guarantee that we won't interfere w/ another running
+     * application's screen mode change or vice versa.
+     * </p>
+     */
+    public final boolean isModeChangedByUs() {
+        return modeChanged && !isOriginalMode();
+    }
+    
+    /**
+     * Returns the cached current {@link MonitorMode} w/o native query.
+     * <p>
+     * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+     * </p>
+     */
+    public final MonitorMode getCurrentMode() {
+        return currentMode;
+    }
+    
+    /**
+     * Returns the current {@link MonitorMode} resulting from a native query.
+     * <p>
+     * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+     * </p>
+     */
+    public abstract MonitorMode queryCurrentMode();
+
+    /**
+     * Set the current {@link com.jogamp.newt.MonitorMode}.
+     * @param mode to be made current, must be element of the list {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+     * @return true if successful, otherwise false
+     */
+    public abstract boolean setCurrentMode(MonitorMode mode);
+
+    public String toString() {
+        return "Monitor[Id "+Display.toHexString(nativeId)+", "+sizeMM+" mm, viewport "+viewport+ ", orig "+originalMode+", curr "+currentMode+
+               ", modeChanged "+modeChanged+", modeCount "+supportedModes.size()+"]";
+    }
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/MonitorMode.java b/src/newt/classes/com/jogamp/newt/MonitorMode.java
new file mode 100644
index 0000000..914aa88
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/MonitorMode.java
@@ -0,0 +1,355 @@
+/**
+ * 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.newt;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.nativewindow.util.SurfaceSize;
+
+import com.jogamp.newt.util.MonitorModeUtil;
+
+
+/** 
+ * Immutable MonitorMode Class, consisting of it's read only components:<br>
+ * <ul>
+ *  <li>nativeId</li>
+ *  <li>{@link SizeAndRRate}, consist out of non rotated {@link #getSurfaceSize() surface size}, {@link #getRefreshRate() refresh rate} and {@link #getFlags() flags}.</li>
+ *  <li><code>rotation</code>, measured counter clockwise (CCW)</li>
+ * </ul>
+ *
+ * <i>Aquire and filter MonitorMode</i><br>
+ * <ul>
+ *  <li>{@link MonitorDevice} Selection:
+ *  <ul>
+ *    <li>A List of all {@link MonitorDevice}s is accessible via {@link Screen#getMonitorDevices()}.</li>
+ *    <li>The main monitor used by a windows is accessible via {@link Window#getMainMonitor()}.</li>
+ *    <li>The main monitor covering an arbitrary rectnagle is accessible via {@link Screen#getMainMonitor(RectangleImmutable)}.</li>
+ *  </ul></li>
+ *  <li>The current MonitorMode can be obtained via {@link MonitorDevice#getCurrentMode()}.</li>
+ *  <li>The original MonitorMode can be obtained via {@link MonitorDevice#getOriginalMode()}.</li>
+ *  <li>{@link MonitorMode} Filtering:
+ *  <ul>
+ *    <li>A {@link MonitorDevice}'s MonitorModes is accessible via {@link MonitorDevice#getSupportedModes()}.</li>
+ *    <li>You may utilize {@link MonitorModeUtil} to filter and select a desired MonitorMode.</li>
+ *  </ul></li>
+ * </ul>
+ * <br>
+ *
+ * <i>Changing MonitorMode</i><br>
+ * <ul>
+ *  <li> Use {@link MonitorDevice#setCurrentMode(MonitorMode)}
+ *       to change the current MonitorMode for all {@link Screen}s referenced via the {@link Screen#getFQName() full qualified name (FQN)}.</li>
+ *  <li> The {@link MonitorDevice#getOriginalMode() original mode} is restored when
+ *  <ul>
+ *    <li>the last FQN referenced Screen closes.</li>
+ *    <li>the JVM shuts down.</li>
+ *  </ul></li>
+ * </ul>
+ * <br>
+ * Example for changing the MonitorMode:
+ * <pre>
+        // Pick the monitor:
+        // Either the one used by a window ..
+        MonitorDevice monitor = window.getMainMonitor();
+        
+        // Or arbitrary from the list ..
+        List<MonitorDevice> allMonitor = getMonitorDevices();
+        MonitorDevice monitor = allMonitor.get(0);
+
+        // Current and original modes ..
+        MonitorMode mmCurrent = monitor.queryCurrentMode();
+        MonitorMode mmOrig = monitor.getOriginalMode();
+        
+        // Target resolution
+        Dimension res = new Dimension(800, 600);
+
+        // Target refresh rate shall be similar to current one ..
+        float freq = mmCurrent.getRefreshRate();
+
+        // Target rotation shall be similar to current one
+        int rot = mmCurrent.getRotation();
+
+        // Filter criterias sequential out of all available MonitorMode of the chosen MonitorDevice
+        List<MonitorMode> monitorModes = monitor.getSupportedModes();
+        monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+        monitorModes = MonitorModeUtil.filterByRotation(monitorModes, rot);
+        monitorModes = MonitorModeUtil.filterByResolution(monitorModes, res);
+        monitorModes = MonitorModeUtil.filterByRate(monitorModes, freq);        
+        monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+
+        // pick 1st one and set to current ..
+        MonitorMode mm = monitorModes.get(0);
+        monitor.setCurrentMode(mm);
+ * </pre>
+ */
+public class MonitorMode {
+    /** 
+     * Immutable <i>surfaceSize and refreshRate</i> Class, consisting of it's read only components:<br>
+     * <ul>
+     *  <li>nativeId</li>
+     *  <li>{@link SurfaceSize} surface memory size</li>
+     *  <li><code>refresh rate</code></li>
+     * </ul>
+     */
+    public static class SizeAndRRate {
+        /** Non rotated surface size */
+        public final SurfaceSize surfaceSize;
+        /** Vertical refresh rate */
+        public final float refreshRate;
+        /** Mode bitfield flags, i.e. {@link #FLAG_DOUBLESCAN}, {@link #FLAG_INTERLACE}, .. */
+        public final int flags;
+        public final int hashCode;
+    
+        public SizeAndRRate(SurfaceSize surfaceSize, float refreshRate, int flags) {
+            if(null==surfaceSize) {
+                throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")");
+            }
+            this.surfaceSize=surfaceSize;
+            this.refreshRate=refreshRate;
+            this.flags = flags;
+            this.hashCode = getHashCode();
+        }
+    
+        private final static String STR_INTERLACE = "Interlace";
+        private final static String STR_DOUBLESCAN = "DoubleScan";
+        private final static String STR_SEP = ", ";
+        
+        public static final StringBuffer flags2String(int flags) {
+            final StringBuffer sb = new StringBuffer();
+            boolean sp = false;
+            if( 0 != ( flags & FLAG_INTERLACE ) ) {
+                sb.append(STR_INTERLACE);
+                sp = true;
+            }
+            if( 0 != ( flags & FLAG_DOUBLESCAN ) ) {
+                if( sp ) {
+                    sb.append(STR_SEP);
+                }
+                sb.append(STR_DOUBLESCAN);
+                sp = true;
+            }
+            return sb;
+        }
+        public final String toString() {
+            return new String(surfaceSize+" @ "+refreshRate+" Hz, flags ["+flags2String(flags).toString()+"]");
+        }
+    
+        /**
+         * Tests equality of two {@link SizeAndRRate} objects 
+         * by evaluating equality of it's components:<br/>
+         * <ul>
+         *  <li><code>surfaceSize</code></li>
+         *  <li><code>refreshRate</code></li>
+         *  <li><code>flags</code></li>
+         * </ul>
+         */
+        public final boolean equals(Object obj) {
+            if (this == obj) { return true; }
+            if (obj instanceof SizeAndRRate) {
+                final SizeAndRRate p = (SizeAndRRate)obj;
+                return surfaceSize.equals(p.surfaceSize) &&
+                       refreshRate == p.refreshRate &&
+                       flags == p.flags ;
+            }
+            return false;
+        }
+    
+        /**
+         * Returns a combined hash code of it's elements:<br/>
+         * <ul>
+         *  <li><code>surfaceSize</code></li>
+         *  <li><code>refreshRate</code></li>
+         *  <li><code>flags</code></li>
+         * </ul>
+         */
+        public final int hashCode() {
+            return hashCode;
+        }        
+        private final int getHashCode() {
+            // 31 * x == (x << 5) - x
+            int hash = 31 + surfaceSize.hashCode();
+            hash = ((hash << 5) - hash) + (int)(refreshRate*100.0f);
+            hash = ((hash << 5) - hash) + flags;
+            return hash;
+        }        
+    }
+    
+    /** zero rotation, compared to normal settings */
+    public static final int ROTATE_0   = 0;
+
+    /**  90 degrees CCW rotation */
+    public static final int ROTATE_90  = 90;
+
+    /** 180 degrees CCW rotation */
+    public static final int ROTATE_180 = 180;
+
+    /** 270 degrees CCW rotation */
+    public static final int ROTATE_270 = 270;
+    
+    /** Frame is split into two fields. See {@link #getFlags()}. */
+    public static final int FLAG_INTERLACE = 1 << 0;
+    
+    /** Lines are doubled. See {@link #getFlags()}. */
+    public static final int FLAG_DOUBLESCAN = 1 << 1;
+
+    /** The immutable native Id of this instance, which may not be unique. */
+    private final int nativeId;    
+    private final SizeAndRRate sizeAndRRate;
+    private final int rotation;
+    private final int hashCode;
+
+    public static boolean isRotationValid(int rotation) {
+        return rotation == MonitorMode.ROTATE_0 || rotation == MonitorMode.ROTATE_90 ||
+               rotation == MonitorMode.ROTATE_180 || rotation == MonitorMode.ROTATE_270 ;
+    }
+
+    /**
+     * @param sizeAndRRate the surface size and refresh rate mode
+     * @param rotation the screen rotation, measured counter clockwise (CCW)
+     */
+    public MonitorMode(int nativeId, SizeAndRRate sizeAndRRate, int rotation) {
+        if ( !isRotationValid(rotation) ) {
+            throw new RuntimeException("invalid rotation: "+rotation);
+        }
+        this.nativeId = nativeId;
+        this.sizeAndRRate = sizeAndRRate;
+        this.rotation = rotation;
+        this.hashCode = getHashCode();
+    }
+    
+    /**
+     * Creates a user instance w/o {@link #getId() identity} to filter our matching modes w/ identity.
+     * <p>
+     * See {@link com.jogamp.newt.util.MonitorModeUtil} for filter utilities.
+     * </p>
+     * @param surfaceSize
+     * @param refreshRate
+     * @param flags
+     * @param rotation
+     */
+    public MonitorMode(SurfaceSize surfaceSize, float refreshRate, int flags, int rotation) {
+        this(0, new SizeAndRRate(surfaceSize, refreshRate, flags), rotation);
+    }    
+
+    /** @return the immutable native Id of this mode, may not be unique, may be 0. */
+    public final int getId() { return nativeId; }
+    
+    /** Returns the <i>surfaceSize and refreshRate</i> instance. */
+    public final SizeAndRRate getSizeAndRRate() { 
+        return sizeAndRRate;
+    }
+    
+    /** Returns the unrotated {@link SurfaceSize} */
+    public final SurfaceSize getSurfaceSize() {
+        return sizeAndRRate.surfaceSize;
+    }
+
+    /** Returns the vertical refresh rate. */
+    public final float getRefreshRate() {
+        return sizeAndRRate.refreshRate;
+    }
+
+    /** Returns bitfield w/ flags, i.e. {@link #FLAG_DOUBLESCAN}, {@link #FLAG_INTERLACE}, .. */
+    public final int getFlags() {
+        return sizeAndRRate.flags;
+    }
+    
+    /** Returns the CCW rotation of this mode */
+    public final int getRotation() {
+        return rotation;
+    }
+    
+    /** Returns the rotated screen width, 
+     *  derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
+     *  and <code>getRotation()</code> 
+     */
+    public final int getRotatedWidth() {
+        return getRotatedWH(true);
+    }
+    
+    /** Returns the rotated screen height, 
+     *  derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
+     *  and <code>getRotation()</code> 
+     */
+    public final int getRotatedHeight() {
+        return getRotatedWH(false);
+    }
+
+    public final String toString() {
+        return "[Id "+Display.toHexString(nativeId)+", " +  sizeAndRRate + ", " + rotation + " degr]";
+    }
+
+    /**
+     * Tests equality of two {@link MonitorMode} objects 
+     * by evaluating equality of it's components:<br/>
+     * <ul>
+     *  <li><code>nativeId</code></li>
+     *  <li><code>sizeAndRRate</code></li>
+     *  <li><code>rotation</code></li>
+     * </ul>
+     */
+    public final boolean equals(Object obj) {
+        if (this == obj) { return true; }
+        if (obj instanceof MonitorMode) {
+            MonitorMode sm = (MonitorMode)obj;
+            return sm.nativeId == this.nativeId &&
+                   sm.sizeAndRRate.equals(sizeAndRRate) &&
+                   sm.rotation == this.rotation ;
+        }
+        return false;
+    }
+
+    /**
+     * Returns a combined hash code of it's elements:<br/>
+     * <ul>
+     *  <li><code>nativeId</code></li>
+     *  <li><code>sizeAndRRate</code></li>
+     *  <li><code>rotation</code></li>
+     * </ul>
+     */
+    public final int hashCode() {
+        return hashCode;
+    }
+    private final int getHashCode() {
+        // 31 * x == (x << 5) - x
+        int hash = 31 + getId();
+        hash = ((hash << 5) - hash) + sizeAndRRate.hashCode();
+        hash = ((hash << 5) - hash) + getRotation();
+        return hash;
+    }
+    
+    private final int getRotatedWH(boolean width) {
+        final DimensionImmutable d = sizeAndRRate.surfaceSize.getResolution();
+        final boolean swap = MonitorMode.ROTATE_90 == rotation || MonitorMode.ROTATE_270 == rotation ;
+        if ( (  width &&  swap ) || ( !width && !swap ) ) {
+            return d.getHeight();
+        }
+        return d.getWidth();
+    }    
+}
diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java
index 1bf47f4..e66b2f6 100644
--- a/src/newt/classes/com/jogamp/newt/NewtFactory.java
+++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java
@@ -34,6 +34,9 @@
 
 package com.jogamp.newt;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
 import javax.media.nativewindow.AbstractGraphicsConfiguration;
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.AbstractGraphicsScreen;
@@ -51,11 +54,17 @@ public class NewtFactory {
 
     public static final String DRIVER_DEFAULT_ROOT_PACKAGE = "jogamp.newt.driver";
     
-    // Work-around for initialization order problems on Mac OS X
-    // between native Newt and (apparently) Fmod
     static {
-        NativeWindowFactory.initSingleton(); // last resort ..
-        WindowImpl.init(NativeWindowFactory.getNativeWindowType(true));
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            public Object run() {
+                NativeWindowFactory.initSingleton(); // last resort ..
+                
+                // Work-around for initialization order problems on Mac OS X
+                // between native Newt and (apparently) Fmod
+                WindowImpl.init(NativeWindowFactory.getNativeWindowType(true));
+                
+                return null;
+            } } );
     }
 
     public static Class<?> getCustomClass(String packageName, String classBaseName) {
diff --git a/src/newt/classes/com/jogamp/newt/NewtVersion.java b/src/newt/classes/com/jogamp/newt/NewtVersion.java
index 961ffdf..9adb7aa 100644
--- a/src/newt/classes/com/jogamp/newt/NewtVersion.java
+++ b/src/newt/classes/com/jogamp/newt/NewtVersion.java
@@ -46,9 +46,10 @@ public class NewtVersion extends JogampVersion {
         if(null == jogampCommonVersionInfo) { // volatile: ok
             synchronized(NewtVersion.class) {
                 if( null == jogampCommonVersionInfo ) {
-                    final String packageName = "com.jogamp.newt";
-                    final Manifest mf = VersionUtil.getManifest(NewtVersion.class.getClassLoader(), packageName);
-                    jogampCommonVersionInfo = new NewtVersion(packageName, mf);
+                    final String packageName1 = "com.jogamp.newt"; // atomic packaging - and identity
+                    final String packageName2 = "javax.media.opengl"; // all packaging
+                    final Manifest mf = VersionUtil.getManifest(NativeWindowVersion.class.getClassLoader(), new String[]{ packageName1, packageName2 } );
+                    jogampCommonVersionInfo = new NewtVersion(packageName1, mf);
                 }
             }
         }
diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java
index a09748d..f56aff9 100644
--- a/src/newt/classes/com/jogamp/newt/Screen.java
+++ b/src/newt/classes/com/jogamp/newt/Screen.java
@@ -27,14 +27,19 @@
  */
 package com.jogamp.newt;
 
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorModeListener;
 import jogamp.newt.Debug;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import javax.media.nativewindow.AbstractGraphicsScreen;
 import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
 
+/** 
+ * A screen may span multiple {@link MonitorDevice}s representing their combined virtual size.
+ */
 public abstract class Screen {
 
     /**
@@ -122,26 +127,31 @@ public abstract class Screen {
     public abstract int getIndex();
 
     /**
-     * @return the x position of the virtual top-left origin.
+     * @return the x position of the virtual viewport's top-left origin.
      */
     public abstract int getX();
     
     /**
-     * @return the y position of the virtual top-left origin.
+     * @return the y position of the virtual viewport's top-left origin.
      */
     public abstract int getY();
     
     /**
-     * @return the <b>rotated</b> virtual width.
+     * @return the <b>rotated</b> virtual viewport's width.
      */
     public abstract int getWidth();
 
     /**
-     * @return the <b>rotated</b> virtual height.
+     * @return the <b>rotated</b> virtual viewport's height.
      */
     public abstract int getHeight();
 
     /**
+     * @return the <b>rotated</b> virtual viewport, i.e. origin and size.
+     */
+    public abstract RectangleImmutable getViewport();
+    
+    /**
      * @return the associated Display
      */
     public abstract Display getDisplay();
@@ -152,48 +162,62 @@ public abstract class Screen {
      */
     public abstract String getFQName();
 
-    /**
-     * @param sml ScreenModeListener to be added for ScreenMode change events
-     */
-    public abstract void addScreenModeListener(ScreenModeListener sml);
-
-    /**
-     * @param sml ScreenModeListener to be removed from ScreenMode change events
+    /** 
+     * Return a list of all {@link MonitorMode}s for all {@link MonitorDevice}s.
      */
-    public abstract void removeScreenModeListener(ScreenModeListener sml);
+    public abstract List<MonitorMode> getMonitorModes();
 
     /** 
-     * Return a list of available {@link com.jogamp.newt.ScreenMode ScreenMode}s.
-     * <p>
-     * If {@link com.jogamp.newt.ScreenMode ScreenMode}s are not supported for this 
-     * native type {@link com.jogamp.newt.Display#getType()}, it returns a list of size one with the current screen size.</p>
-     * 
-     * @return a shallow copy of the internal immutable {@link com.jogamp.newt.ScreenMode ScreenMode}s.
+     * Return a list of available {@link MonitorDevice}s.
      */
-    public abstract List<ScreenMode> getScreenModes();
+    public abstract List<MonitorDevice> getMonitorDevices();
 
     /**
-     * Return the original {@link com.jogamp.newt.ScreenMode}, as used at NEWT initialization.
-     * @return original ScreenMode which is element of the list {@link #getScreenModes()}.
+     * Returns the {@link MonitorDevice} which {@link MonitorDevice#getViewport() viewport} 
+     * {@link MonitorDevice#coverage(RectangleImmutable) covers} the given rectangle the most.
+     * <p>
+     * If no coverage is detected the first {@link MonitorDevice} is returned. 
+     * </p>
      */
-    public abstract ScreenMode getOriginalScreenMode();
+    public final MonitorDevice getMainMonitor(RectangleImmutable r) {
+        MonitorDevice res = null;
+        float maxCoverage = Float.MIN_VALUE;
+        final List<MonitorDevice> monitors = getMonitorDevices();
+        for(int i=monitors.size()-1; i>=0; i--) {            
+            final MonitorDevice monitor = monitors.get(i);
+            final float coverage = monitor.coverage(r);
+            if( coverage > maxCoverage ) {
+                maxCoverage = coverage;
+                res = monitor;
+            }
+        }
+        if( maxCoverage > 0.0f && null != res ) {
+            return res;
+        }
+        return monitors.get(0);
+    }
 
     /**
-     * Return the current {@link com.jogamp.newt.ScreenMode}.
+     * Returns the union of all monitor's {@link MonitorDevice#getViewport() viewport}.
      * <p>
-     * If {@link com.jogamp.newt.ScreenMode ScreenMode}s are not supported for this 
-     * native type {@link com.jogamp.newt.Display#getType()}, it returns one with the current screen size. </p>
-     * 
-     * @return current ScreenMode which is element of the list {@link #getScreenModes()}.
+     * Should be equal to {@link #getX()}, {@link #getY()}, {@link #getWidth()} and {@link #getHeight()},
+     * however, some native toolkits may choose a different virtual screen area. 
+     * </p>
+     * @param result storage for result, will be returned
+     */
+    public final Rectangle unionOfMonitorViewportSize(final Rectangle result) {
+        return MonitorDevice.unionOfViewports(result, getMonitorDevices());
+    }
+    
+    /**
+     * @param sml {@link MonitorModeListener} to be added for {@link MonitorEvent}
      */
-    public abstract ScreenMode getCurrentScreenMode();
+    public abstract void addMonitorModeListener(MonitorModeListener sml);
 
     /**
-     * Set the current {@link com.jogamp.newt.ScreenMode}.
-     * @param screenMode to be made current, must be element of the list {@link #getScreenModes()}.
-     * @return true if successful, otherwise false
+     * @param sml {@link MonitorModeListener} to be removed from {@link MonitorEvent}
      */
-    public abstract boolean setCurrentScreenMode(ScreenMode screenMode);
+    public abstract void removeMonitorModeListener(MonitorModeListener sml);
 
     // Global Screens
     protected static ArrayList<Screen> screenList = new ArrayList<Screen>();
@@ -236,6 +260,7 @@ public abstract class Screen {
         return null;
     }
     /** Returns the global display collection */
+    @SuppressWarnings("unchecked")
     public static Collection<Screen> getAllScreens() {
         ArrayList<Screen> list;
         synchronized(screenList) {
diff --git a/src/newt/classes/com/jogamp/newt/ScreenMode.java b/src/newt/classes/com/jogamp/newt/ScreenMode.java
deleted file mode 100644
index 1f12217..0000000
--- a/src/newt/classes/com/jogamp/newt/ScreenMode.java
+++ /dev/null
@@ -1,208 +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.newt;
-
-import javax.media.nativewindow.util.DimensionImmutable;
-
-import com.jogamp.newt.util.MonitorMode;
-
-/** Immutable ScreenMode Class, consisting of it's read only components:<br>
- * <ul>
- *  <li>{@link com.jogamp.newt.util.MonitorMode}, non rotated values</li>
- *  <li><code>rotation</code>, measured counter clockwise (CCW)</li>
- * </ul>
- *
- * <i>Aquire and filter ScreenModes</i><br>
- * <ul>
- *  <li>A List of read only ScreenMode's is being returned by {@link com.jogamp.newt.Screen#getScreenModes()}.</li>
- *  <li>You may utilize {@link com.jogamp.newt.util.ScreenModeUtil} to filter and select a desired ScreenMode.</li>
- *  <li>The current ScreenMode can be obtained via {@link com.jogamp.newt.Screen#getCurrentScreenMode()}.</li>
- *  <li>The initial original ScreenMode (at startup) can be obtained via {@link com.jogamp.newt.Screen#getOriginalScreenMode()}.</li>
- * </ul>
- * <br>
- *
- * <i>Changing ScreenModes</i><br>
- * <ul>
- *  <li> Use {@link com.jogamp.newt.Screen#setCurrentScreenMode(com.jogamp.newt.ScreenMode)}</li>
- *       to change the current ScreenMode of all Screen's referenced via the full qualified name (FQN)
- *       {@link com.jogamp.newt.Screen#getFQName()}.</li>
- *  <li> When the last FQN referenced Screen closes, the original ScreenMode ({@link com.jogamp.newt.Screen#getOriginalScreenMode()})
- * is restored.</li>
- * </ul>
- * <br>
- * Example for changing the ScreenMode:
- * <pre>
-        // determine target refresh rate
-        ScreenMode orig = screen.getOriginalScreenMode();
-        int freq = orig.getMonitorMode().getRefreshRate();
-
-        // target resolution
-        Dimension res = new Dimension(800, 600);
-
-        // target rotation
-        int rot = 0;
-
-        // filter available ScreenModes
-        List screenModes = screen.getScreenModes();
-        screenModes = ScreenModeUtil.filterByRate(screenModes, freq); // get the nearest ones
-        screenModes = ScreenModeUtil.filterByRotation(screenModes, rot);
-        screenModes = ScreenModeUtil.filterByResolution(screenModes, res); // get the nearest ones
-        screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
-
-        // pick 1st one ..
-        screen.setCurrentScreenMode((ScreenMode) screenModes.get(0)); 
- * </pre>
- *
- * X11 / AMD just works<br>
- * <br>
- * X11 / NVidia difficulties
- * <pre>
-    NVidia RANDR RefreshRate Bug
-        If NVidia's 'DynamicTwinView' is enabled, all refresh rates are
-        unique, ie consequent numbers starting with the default refresh, ie 50, 51, ..
-        The only way to workaround it is to disable 'DynamicTwinView'.
-        Read: http://us.download.nvidia.com/XFree86/Linux-x86/260.19.12/README/configtwinview.html
-
-        Check to see if 'DynamicTwinView' is enable:
-            nvidia-settings -q :0/DynamicTwinview
-
-        To disable it (workaround), add the following option to your xorg.conf device section:
-            Option "DynamicTwinView" "False"
-
-    NVidia RANDR Rotation:
-        To enable it, add the following option to your xorg.conf device section:
-            Option "RandRRotation" "on"
- * </pre>
- *
- */
-public class ScreenMode {
-    /** zero rotation, compared to normal settings */
-    public static final int ROTATE_0   = 0;
-
-    /**  90 degrees CCW rotation */
-    public static final int ROTATE_90  = 90;
-
-    /** 180 degrees CCW rotation */
-    public static final int ROTATE_180 = 180;
-
-    /** 270 degrees CCW rotation */
-    public static final int ROTATE_270 = 270;
-
-    MonitorMode monitorMode;
-    int rotation;
-
-    public static boolean isRotationValid(int rotation) {
-        return rotation == ScreenMode.ROTATE_0 || rotation == ScreenMode.ROTATE_90 ||
-               rotation == ScreenMode.ROTATE_180 || rotation == ScreenMode.ROTATE_270 ;
-    }
-
-    /**
-     * @param monitorMode the monitor mode
-     * @param rotation the screen rotation, measured counter clockwise (CCW)
-     */
-    public ScreenMode(MonitorMode monitorMode, int rotation) {
-        if ( !isRotationValid(rotation) ) {
-            throw new RuntimeException("invalid rotation: "+rotation);
-        }
-        this.monitorMode = monitorMode;
-        this.rotation = rotation;
-    }
-
-    /** Returns the unrotated <code>MonitorMode</code> */
-    public final MonitorMode getMonitorMode() {
-        return monitorMode;
-    }
-
-    /** Returns the CCW rotation of this mode */
-    public final int getRotation() {
-        return rotation;
-    }
-    
-    /** Returns the rotated screen width, 
-     *  derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
-     *  and <code>getRotation()</code> 
-     */
-    public final int getRotatedWidth() {
-        return getRotatedWH(true);
-    }
-    
-    /** Returns the rotated screen height, 
-     *  derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
-     *  and <code>getRotation()</code> 
-     */
-    public final int getRotatedHeight() {
-        return getRotatedWH(false);
-    }
-
-    public final String toString() {
-        return "[ " +  getMonitorMode() + ", " + rotation + " degr ]";
-    }
-
-    /**
-     * Tests equality of two <code>ScreenMode</code> objects 
-     * by evaluating equality of it's components:<br>
-     * <ul>
-     *  <li><code>monitorMode</code></li>
-     *  <li><code>rotation</code></li>
-     * </ul>
-     * <br>
-     */
-    public final boolean equals(Object obj) {
-        if (this == obj) { return true; }
-        if (obj instanceof ScreenMode) {
-            ScreenMode sm = (ScreenMode)obj;
-            return sm.getMonitorMode().equals(getMonitorMode()) &&
-                   sm.getRotation() == this.getRotation() ;
-        }
-        return false;
-    }
-
-    /**
-     * Returns a combined hash code of it's elements:<br>
-     * <ul>
-     *  <li><code>monitorMode</code></li>
-     *  <li><code>rotation</code></li>
-     * </ul>
-     */
-    public final int hashCode() {
-        // 31 * x == (x << 5) - x
-        int hash = 31 + getMonitorMode().hashCode();
-        hash = ((hash << 5) - hash) + getRotation();
-        return hash;
-    }
-    
-    private final int getRotatedWH(boolean width) {
-        final DimensionImmutable d = getMonitorMode().getSurfaceSize().getResolution();
-        final boolean swap = ScreenMode.ROTATE_90 == rotation || ScreenMode.ROTATE_270 == rotation ;
-        if ( (  width &&  swap ) || ( !width && !swap ) ) {
-            return d.getHeight();
-        }
-        return d.getWidth();
-    }        
-}
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java
index cc42465..f63c037 100644
--- a/src/newt/classes/com/jogamp/newt/Window.java
+++ b/src/newt/classes/com/jogamp/newt/Window.java
@@ -28,16 +28,22 @@
 
 package com.jogamp.newt;
 
+import java.util.List;
+
+import com.jogamp.newt.event.WindowEvent;
 import com.jogamp.newt.event.WindowListener;
 import com.jogamp.newt.event.KeyListener;
 import com.jogamp.newt.event.KeyEvent;
 import com.jogamp.newt.event.InputEvent;
 import com.jogamp.newt.event.MouseListener;
 import jogamp.newt.Debug;
+import jogamp.newt.WindowImpl;
+
 import javax.media.nativewindow.CapabilitiesChooser;
 import javax.media.nativewindow.CapabilitiesImmutable;
 import javax.media.nativewindow.NativeWindow;
 import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.util.RectangleImmutable;
 
 /**
  * Specifying NEWT's Window functionality:
@@ -77,11 +83,20 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
     boolean isNativeValid();
 
     /**
-     * @return The associated Screen
+     * @return The associated {@link Screen}
      */
     Screen getScreen();
 
     /**
+     * Returns the {@link MonitorDevice} which {@link MonitorDevice#getViewport() viewport} 
+     * {@link MonitorDevice#coverage(RectangleImmutable) covers} this window the most.
+     * <p>
+     * If no coverage is detected the first {@link MonitorDevice} is returned. 
+     * </p>
+     */
+    MonitorDevice getMainMonitor();
+    
+    /**
      * Set the CapabilitiesChooser to help determine the native visual type.
      *
      * @param chooser the new CapabilitiesChooser
@@ -104,14 +119,26 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
     CapabilitiesImmutable getChosenCapabilities();
 
     /**
-     * Destroy the Window and it's children, incl. native destruction.<br>
-     * The Window can be recreate via {@link #setVisible(boolean) setVisible(true)}.
-     * <p>Visibility is set to false.</p>
+     * {@inheritDoc}
+     * <p>
+     * Also iterates through this window's children and destroys them.
+     * </p>
+     * <p>
+     * Visibility is set to false.
+     * </p>
+     * <p>
+     * Method sends out {@link WindowEvent#EVENT_WINDOW_DESTROY_NOTIFY pre-} and 
+     * {@link WindowEvent#EVENT_WINDOW_DESTROYED post-} destruction events
+     * to all of it's {@link WindowListener}.
+     * </p>
      * <p>
      * This method invokes {@link Screen#removeReference()} after it's own destruction,<br>
      * which will issue {@link Screen#destroy()} if the reference count becomes 0.<br>
      * This destruction sequence shall end up in {@link Display#destroy()}, if all reference counts become 0.
      * </p>
+     * <p>
+     * The Window can be recreate via {@link #setVisible(boolean) setVisible(true)}.
+     * </p>
      * @see #destroy()
      * @see #setVisible(boolean)
      */
@@ -119,6 +146,16 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
     void destroy();
 
     /**
+     * Set a custom action handling destruction issued by a {@link WindowImpl#windowDestroyNotify(boolean) toolkit triggered window destroy}
+     * replacing the default {@link #destroy()} action.
+     * <p>
+     * The custom action shall call {@link #destroy()} 
+     * but may perform further tasks before and after.
+     * </p>
+     */
+    void setWindowDestroyNotifyAction(Runnable r);
+
+    /**
      * <code>setVisible</code> makes the window and children visible if <code>visible</code> is true,
      * otherwise the window and children becomes invisible.
      * <p>
@@ -319,8 +356,32 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
 
     ReparentOperation reparentWindow(NativeWindow newParent, boolean forceDestroyCreate);
 
+    /**
+     * Enable or disable fullscreen mode for this window.
+     * <p>
+     * Fullscreen mode is established on the {@link #getMainMonitor() main monitor}. 
+     * </p>
+     * @param fullscreen enable or disable fullscreen mode
+     * @return success
+     * @see #setFullscreen(List)
+     * @see #isFullscreen()
+     */
     boolean setFullscreen(boolean fullscreen);
 
+    /**
+     * Enable fullscreen mode for this window spanning across the given {@link MonitorDevice}s
+     * or across all {@link MonitorDevice}s.
+     * <p>
+     * Disable fullscreen via {@link #setFullscreen(boolean)}.
+     * </p>
+     * @param monitors if <code>null</code> fullscreen will be spanned across all {@link MonitorDevice}s, 
+     *                 otherwise across the given list of {@link MonitorDevice}.
+     * @return success
+     * @see #setFullscreen(boolean)
+     * @see #isFullscreen()
+     */
+    boolean setFullscreen(List<MonitorDevice> monitors);
+    
     boolean isFullscreen();
 
     static interface FocusRunnable {
@@ -345,7 +406,11 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
      * Sets a {@link KeyListener} allowing focus traversal with a covered window toolkit like AWT.
      * <p>
      * The {@link KeyListener} methods are invoked prior to all other {@link KeyListener}'s
-     * allowing to suppress the {@link KeyEvent} via the {@link InputEvent#consumedTag}.
+     * allowing to suppress the {@link KeyEvent} via the {@link InputEvent#consumedTag}
+     * and to perform focus traversal with a 3rd party toolkit.
+     * </p>
+     * <p>
+     * The {@link KeyListener} methods are not invoked for {@link KeyEvent#isAutoRepeat() auto-repeat} events. 
      * </p>
      * @param l
      */
@@ -383,10 +448,13 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
     // WindowListener
     //
 
+    /**
+     * Send a {@link WindowEvent} to all {@link WindowListener}.
+     * @param eventType a {@link WindowEvent} type, e.g. {@link WindowEvent#EVENT_WINDOW_REPAINT}. 
+     */
     public void sendWindowEvent(int eventType);
 
     /**
-     *
      * Appends the given {@link com.jogamp.newt.event.WindowListener} to the end of
      * the list.
      */
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index 89a749c..6ba7a1a 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -31,9 +31,11 @@ package com.jogamp.newt.awt;
 
 import java.awt.AWTKeyStroke;
 import java.awt.Canvas;
+import java.awt.Component;
 import java.awt.Graphics;
 import java.awt.GraphicsConfiguration;
 import java.awt.KeyboardFocusManager;
+import java.beans.Beans;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.lang.reflect.Method;
@@ -42,23 +44,23 @@ import java.security.PrivilegedAction;
 import java.util.Set;
 
 import javax.media.nativewindow.NativeWindow;
-import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.nativewindow.OffscreenLayerOption;
-import javax.media.nativewindow.OffscreenLayerSurface;
 import javax.media.nativewindow.WindowClosingProtocol;
 import javax.swing.MenuSelectionManager;
 
 import jogamp.nativewindow.awt.AWTMisc;
 import jogamp.newt.Debug;
+import jogamp.newt.WindowImpl;
 import jogamp.newt.awt.NewtFactoryAWT;
 import jogamp.newt.awt.event.AWTParentWindowAdapter;
 import jogamp.newt.driver.DriverClearFocus;
 
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
 import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
 import com.jogamp.nativewindow.awt.JAWTWindow;
 import com.jogamp.newt.Display;
 import com.jogamp.newt.Window;
-import com.jogamp.newt.event.InputEvent;
 import com.jogamp.newt.event.KeyEvent;
 import com.jogamp.newt.event.KeyListener;
 import com.jogamp.newt.event.WindowAdapter;
@@ -84,18 +86,25 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
     private JAWTWindow jawtWindow = null;
     private boolean shallUseOffscreenLayer = false;
     private Window newtChild = null;
+    private boolean newtChildAttached = false;
     private boolean isOnscreen = true;
     private WindowClosingMode newtChildCloseOp;
-    private AWTAdapter awtAdapter = null;
+    private AWTParentWindowAdapter awtAdapter = null;
     private AWTAdapter awtMouseAdapter = null;
     private AWTAdapter awtKeyAdapter = null;
     
     private AWTWindowClosingProtocol awtWindowClosingProtocol =
           new AWTWindowClosingProtocol(this, new Runnable() {
                 public void run() {
-                    NewtCanvasAWT.this.destroy();
+                    NewtCanvasAWT.this.destroyImpl(false /* removeNotify */, true /* windowClosing */);
                 }
-            });
+            }, new Runnable() {
+                public void run() {
+                    if( newtChild != null ) {
+                        newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+                    }
+                }                
+            } );
 
     /**
      * Instantiates a NewtCanvas without a NEWT child.<br>
@@ -181,6 +190,10 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
     
     WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() {
           @Override
+          public void windowResized(WindowEvent e) {
+              updateLayoutSize();
+          }
+          @Override
           public void windowGainedFocus(WindowEvent arg0) {
               if( isParent() && !isFullscreen() ) {
                   MenuSelectionManager.defaultManager().clearSelectedPath();
@@ -189,8 +202,6 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
     };
 
     class FocusTraversalKeyListener implements KeyListener {
-         boolean suppress = false;
-         
          public void keyPressed(KeyEvent e) {
              if( isParent() && !isFullscreen() ) {
                  handleKey(e, false);
@@ -201,39 +212,36 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
                  handleKey(e, true);
              }
          }
-         public void keyTyped(KeyEvent e) {
-             if(suppress) {
-                 e.setAttachment(InputEvent.consumedTag);
-                 suppress = false; // reset
-             }             
-         }
          
          void handleKey(KeyEvent evt, boolean onRelease) {   
              if(null == keyboardFocusManager) {
                  throw new InternalError("XXX");
              }
              final AWTKeyStroke ks = AWTKeyStroke.getAWTKeyStroke(evt.getKeyCode(), evt.getModifiers(), onRelease);
+             boolean suppress = false;
              if(null != ks) {
                  final Set<AWTKeyStroke> fwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); 
-                 final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);         
+                 final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
                  if(fwdKeys.contains(ks)) {
+                     final Component nextFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, true /* forward */);
                      if(DEBUG) {
-                         System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner());
+                         System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", nextFocus "+nextFocus);
                      }
                      // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
-                     NewtCanvasAWT.this.transferFocus();
+                     nextFocus.requestFocus();
                      suppress = true;
                  } else if(bwdKeys.contains(ks)) {
+                     final Component prevFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, false /* forward */);
                      if(DEBUG) {
-                         System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner());
+                         System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", prevFocus "+prevFocus);
                      }
                      // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
-                     NewtCanvasAWT.this.transferFocusBackward();
+                     prevFocus.requestFocus();
                      suppress = true;
                  }
              }
              if(suppress) {
-                 evt.setAttachment(InputEvent.consumedTag);                 
+                 evt.setConsumed(true);                 
              }
              if(DEBUG) {
                  System.err.println("NewtCanvasAWT.focusKey: XXX: "+ks);
@@ -292,16 +300,26 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
         final java.awt.Container cont = AWTMisc.getContainer(this);
         // remove old one
         if(null != newtChild) {
-            reparentWindow( false, cont );
+            detachNewtChild( cont );
             newtChild = null;
         }
         // add new one, reparent only if ready
         newtChild = newChild;
-        if( isDisplayable() && null != newChild) {
-            reparentWindow( true, cont );
-        }
+
+        updateLayoutSize();
+        // will be done later at paint/display/..: attachNewtChild(cont);
+        
         return prevChild;
     }
+    
+    private final void updateLayoutSize() {
+        if( null != newtChild ) {
+            // use NEWT child's size for min/pref size!
+            java.awt.Dimension minSize = new java.awt.Dimension(newtChild.getWidth(), newtChild.getHeight());
+            setMinimumSize(minSize);
+            setPreferredSize(minSize);
+        }        
+    }
 
     /** @return the current NEWT child */
     public Window getNEWTChild() {
@@ -320,149 +338,44 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
         return awtWindowClosingProtocol.setDefaultCloseOperation(op);
     }
 
-    /* package */ void configureNewtChild(boolean attach) {
-        if(null!=awtAdapter) {
-          awtAdapter.removeFrom(this);
-          awtAdapter=null;
-        }
-        if(null!=awtMouseAdapter) {
-            awtMouseAdapter.removeFrom(this);
-            awtMouseAdapter = null;
-        }
-        if(null!=awtKeyAdapter) {
-            awtKeyAdapter.removeFrom(this);
-            awtKeyAdapter = null;
-        }
-        if(null != keyboardFocusManager) {
-            keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener);
-            keyboardFocusManager = null;
-        }
-        
-        if( null != newtChild ) {
-            newtChild.setKeyboardFocusHandler(null);
-            if(attach) {
-                if(null == jawtWindow.getGraphicsConfiguration()) {
-                    throw new InternalError("XXX");
-                }                
-                isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
-                awtAdapter = new AWTParentWindowAdapter(jawtWindow, newtChild).addTo(this);
-                newtChild.addWindowListener(clearAWTMenusOnNewtFocus);
-                newtChild.setFocusAction(focusAction); // enable AWT focus traversal
-                newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
-                awtWindowClosingProtocol.addClosingListenerOneShot();
-                keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
-                keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener);
-                if(isOnscreen) {
-                    // onscreen newt child needs to fwd AWT focus
-                    newtChild.setKeyboardFocusHandler(newtFocusTraversalKeyListener);
-                } else {
-                    // offscreen newt child requires AWT to fwd AWT key/mouse event
-                    awtMouseAdapter = new AWTMouseAdapter(newtChild).addTo(this);
-                    awtKeyAdapter = new AWTKeyAdapter(newtChild).addTo(this);
-                }
-            } else {
-                newtChild.removeWindowListener(clearAWTMenusOnNewtFocus);
-                newtChild.setFocusAction(null);
-                newtChild.setDefaultCloseOperation(newtChildCloseOp);
-                awtWindowClosingProtocol.removeClosingListener();
-            }
-        }
-    }
-
     @Override
     public void addNotify() {
-
-        // before native peer is valid: X11
-        disableBackgroundErase();
-
-        // creates the native peer
-        super.addNotify();
-
-        // after native peer is valid: Windows
-        disableBackgroundErase();
-
-        java.awt.Container cont = AWTMisc.getContainer(this);
-        if(DEBUG) {
-            // if ( isShowing() == false ) -> Container was not visible yet.
-            // if ( isShowing() == true  ) -> Container is already visible.
-            System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+
-                               ", displayable "+isDisplayable()+" -> "+cont);
+        if( Beans.isDesignTime() ) {
+            super.addNotify();
+        } else {
+            // before native peer is valid: X11
+            disableBackgroundErase();
+    
+            // creates the native peer
+            super.addNotify();
+    
+            // after native peer is valid: Windows
+            disableBackgroundErase();
+                
+            jawtWindow = NewtFactoryAWT.getNativeWindow(this, null != newtChild ? newtChild.getRequestedCapabilities() : null);          
+            jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
+            
+            if(DEBUG) {
+                // if ( isShowing() == false ) -> Container was not visible yet.
+                // if ( isShowing() == true  ) -> Container is already visible.
+                System.err.println("NewtCanvasAWT.addNotify: win "+newtWinHandleToHexString(newtChild)+
+                                   ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+
+                                   ", displayable "+isDisplayable()+", cont "+AWTMisc.getContainer(this));
+            }
         }
-        reparentWindow(true, cont);
+        awtWindowClosingProtocol.addClosingListener();
     }
 
     @Override
     public void removeNotify() {
-        java.awt.Container cont = AWTMisc.getContainer(this);
-        if(DEBUG) {
-            System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont);
-        }
-        final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(newtChild, true);
-        if(null != ols && ols.isSurfaceLayerAttached()) {
-            ols.detachSurfaceLayer();
-        }      
-        reparentWindow(false, cont);
+        awtWindowClosingProtocol.removeClosingListener();
         
-        if(null != jawtWindow) {
-            NewtFactoryAWT.destroyNativeWindow(jawtWindow);
-            jawtWindow=null;
+        if( Beans.isDesignTime() ) {
+            super.removeNotify();
+        } else {
+            destroyImpl(true /* removeNotify */, false /* windowClosing */);
+            super.removeNotify();
         }
-        
-        super.removeNotify();
-    }
-
-    void reparentWindow(boolean add, java.awt.Container cont) {
-      if(null==newtChild) {
-        return; // nop
-      }
-      if(DEBUG) {
-          System.err.println("NewtCanvasAWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
-      }
-
-      newtChild.setFocusAction(null); // no AWT focus traversal ..
-      if(add) {
-          if(DEBUG) {
-            System.err.println("NewtCanvasAWT.reparentWindow: newtChild: "+newtChild);
-          }
-          if(null == jawtWindow) {
-              jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities());          
-              jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
-          }            
-          final int w;
-          final int h;
-          if(isPreferredSizeSet()) {
-             java.awt.Dimension d = getPreferredSize();
-             w = d.width;
-             h = d.height;
-          } else {
-             final java.awt.Dimension min;
-             if(this.isMinimumSizeSet()) {
-                 min = getMinimumSize();
-             } else {
-                 min = new java.awt.Dimension(0, 0);
-             }
-             java.awt.Insets ins = cont.getInsets();
-             w = Math.max(min.width, cont.getWidth() - ins.left - ins.right);
-             h = Math.max(min.height, cont.getHeight() - ins.top - ins.bottom);
-          }
-          setSize(w, h);
-          newtChild.setSize(w, h);
-          newtChild.reparentWindow(jawtWindow);
-          newtChild.setVisible(true);
-          configureNewtChild(true);
-          newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
-          
-          // force this AWT Canvas to be focus-able, 
-          // since this it is completely covered by the newtChild (z-order).
-          setFocusable(true);        
-      } else {
-          configureNewtChild(false);
-          newtChild.setVisible(false);
-          newtChild.reparentWindow(null);
-      }
-      if(DEBUG) {
-          System.err.println("NewtCanvasAWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
-      }
     }
 
     /**
@@ -472,46 +385,63 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
      *   <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
      *   <li> Issues <code>destroy()</code> on the NEWT Child</li>
      *   <li> Remove reference to the NEWT Child</li>
-     *   <li> Remove this Canvas from it's parent.</li>
      * </ul>
      * @see Window#destroy()
      */
     public final void destroy() {
-        if(null!=newtChild) {
+        destroyImpl(false /* removeNotify */, false /* windowClosing */);
+    }
+    
+    private final void destroyImpl(boolean removeNotify, boolean windowClosing) {
+        if( null !=newtChild ) {
             java.awt.Container cont = AWTMisc.getContainer(this);
             if(DEBUG) {
-                System.err.println("NewtCanvasAWT.destroy(): "+newtChild+", from "+cont);
-            }
-            configureNewtChild(false);
-            if(null!=jawtWindow) {
-                NewtFactoryAWT.destroyNativeWindow(jawtWindow);
-                jawtWindow=null;
-            }
-            newtChild.setVisible(false);
-            newtChild.reparentWindow(null);
-            newtChild.destroy();
-            newtChild=null;
-            if(null!=cont) {
-                cont.remove(this);
+                System.err.println("NewtCanvasAWT.destroy(removeNotify "+removeNotify+", windowClosing "+windowClosing+"): nw "+newtWinHandleToHexString(newtChild)+", from "+cont);
             }
+            detachNewtChild(cont);
+            
+            if( !removeNotify ) {
+                final Window cWin = newtChild;
+                final Window dWin = cWin.getDelegatedWindow();
+                newtChild=null;
+                if( windowClosing && dWin instanceof WindowImpl ) {
+                    ((WindowImpl)dWin).windowDestroyNotify(true);
+                } else {
+                    cWin.destroy();
+                }
+            }            
         }
-    }    
-
+        if( ( removeNotify || windowClosing ) && null!=jawtWindow ) {
+            NewtFactoryAWT.destroyNativeWindow(jawtWindow);
+            jawtWindow=null;
+        }        
+    }
+    
     @Override
     public void paint(Graphics g) {
-        awtWindowClosingProtocol.addClosingListenerOneShot();
-        if(null!=newtChild) {
+        if( validateComponent(true) ) {
             newtChild.windowRepaint(0, 0, getWidth(), getHeight());
         }
     }
     @Override
     public void update(Graphics g) {
-        awtWindowClosingProtocol.addClosingListenerOneShot();
-        if(null!=newtChild) {
-            newtChild.windowRepaint(0, 0, getWidth(), getHeight());
-        }
+        paint(g);
     }
 
+    @SuppressWarnings("deprecation")
+    @Override
+    public void reshape(int x, int y, int width, int height) {
+        synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape
+            super.reshape(x, y, width, height);
+            if(DEBUG) {
+                System.err.println("NewtCanvasAWT.reshape: "+x+"/"+y+" "+width+"x"+height);
+            }
+            if( validateComponent(true) ) {
+                // newtChild.setSize(width, height);
+            }
+        }
+    }
+        
     private final void requestFocusNEWTChild() {
         if(null!=newtChild) {
             newtChild.setFocusAction(null);
@@ -556,6 +486,154 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
         return res;
     }
 
+    private final boolean validateComponent(boolean attachNewtChild) {
+        if( Beans.isDesignTime() || !isDisplayable() ) {
+            return false;
+        }
+        if ( null == newtChild || null == jawtWindow ) {
+            return false;
+        }
+        if( 0 >= getWidth() || 0 >= getHeight() ) {
+            return false;
+        }
+        
+        if( attachNewtChild && !newtChildAttached && null != newtChild ) {
+            attachNewtChild();
+        }
+
+        return true;
+    }
+    
+    private final void configureNewtChild(boolean attach) {
+        if(null!=awtAdapter) {
+          awtAdapter.removeFrom(this);
+          awtAdapter=null;
+        }
+        if(null!=awtMouseAdapter) {
+            awtMouseAdapter.removeFrom(this);
+            awtMouseAdapter = null;
+        }
+        if(null!=awtKeyAdapter) {
+            awtKeyAdapter.removeFrom(this);
+            awtKeyAdapter = null;
+        }
+        if(null != keyboardFocusManager) {
+            keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener);
+            keyboardFocusManager = null;
+        }
+        
+        if( null != newtChild ) {
+            newtChild.setKeyboardFocusHandler(null);
+            if(attach) {
+                if(null == jawtWindow.getGraphicsConfiguration()) {
+                    throw new InternalError("XXX");
+                }                
+                isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
+                awtAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter(jawtWindow, newtChild).addTo(this);
+                awtAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
+                newtChild.addWindowListener(clearAWTMenusOnNewtFocus);
+                newtChild.setFocusAction(focusAction); // enable AWT focus traversal
+                newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
+                keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+                keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener);
+                // force this AWT Canvas to be focus-able,
+                // since this it is completely covered by the newtChild (z-order).
+                setFocusable(true);
+                if(isOnscreen) {
+                    // onscreen newt child needs to fwd AWT focus
+                    newtChild.setKeyboardFocusHandler(newtFocusTraversalKeyListener);
+                } else {
+                    // offscreen newt child requires AWT to fwd AWT key/mouse event
+                    awtMouseAdapter = new AWTMouseAdapter(newtChild).addTo(this);
+                    awtKeyAdapter = new AWTKeyAdapter(newtChild).addTo(this);
+                }
+            } else {
+                newtChild.removeWindowListener(clearAWTMenusOnNewtFocus);
+                newtChild.setFocusAction(null);
+                newtChild.setDefaultCloseOperation(newtChildCloseOp);
+                setFocusable(false);
+            }
+        }
+    }
+
+    private final void attachNewtChild() {
+      if( null == newtChild || null == jawtWindow || newtChildAttached ) {
+          return; // nop
+      }
+      if(DEBUG) {
+          // if ( isShowing() == false ) -> Container was not visible yet.
+          // if ( isShowing() == true  ) -> Container is already visible.
+          System.err.println("NewtCanvasAWT.attachNewtChild.0 @ "+Thread.currentThread().getName()+": win "+newtWinHandleToHexString(newtChild)+
+                             ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
+                             ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+
+                             ", cont "+AWTMisc.getContainer(this));
+      }
+
+      newtChildAttached = true;
+      newtChild.setFocusAction(null); // no AWT focus traversal ..
+      if(DEBUG) {
+        System.err.println("NewtCanvasAWT.attachNewtChild.1: newtChild: "+newtChild);
+      }
+      final int w = getWidth();
+      final int h = getHeight();
+      System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h);
+      newtChild.setVisible(false);
+      newtChild.setSize(w, h);
+      newtChild.reparentWindow(jawtWindow);
+      newtChild.addSurfaceUpdatedListener(jawtWindow);
+      if( Platform.OSType.MACOS == Platform.getOSType() && jawtWindow.isOffscreenLayerSurfaceEnabled() ) {
+          AWTEDTExecutor.singleton.invoke(false, forceRelayout);
+      }
+      newtChild.setVisible(true);
+      configureNewtChild(true);
+      newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
+      
+      if(DEBUG) {
+          System.err.println("NewtCanvasAWT.attachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
+      }
+    }
+    private final Runnable forceRelayout = new Runnable() {
+        public void run() {
+            if(DEBUG) {
+                System.err.println("NewtCanvasAWT.forceRelayout.0");
+            }
+            // Hack to force proper native AWT layout incl. CALayer components on OSX
+            final java.awt.Component component = NewtCanvasAWT.this;
+            final int cW = component.getWidth();
+            final int cH = component.getHeight();
+            component.setSize(cW+1, cH+1);
+            component.setSize(cW, cH);
+            if(DEBUG) {
+                System.err.println("NewtCanvasAWT.forceRelayout.X");
+            }
+        }  };
+    
+    private final void detachNewtChild(java.awt.Container cont) {
+      if( null == newtChild || null == jawtWindow || !newtChildAttached ) {
+          return; // nop
+      }
+      if(DEBUG) {
+          // if ( isShowing() == false ) -> Container was not visible yet.
+          // if ( isShowing() == true  ) -> Container is already visible.
+          System.err.println("NewtCanvasAWT.detachNewtChild.0: win "+newtWinHandleToHexString(newtChild)+
+                             ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
+                             ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+
+                             ", cont "+cont);
+      }
+
+      newtChild.removeSurfaceUpdatedListener(jawtWindow);      
+      newtChildAttached = false;
+      newtChild.setFocusAction(null); // no AWT focus traversal ..
+      configureNewtChild(false);
+      newtChild.setVisible(false);
+      
+      newtChild.reparentWindow(null); // will destroy context (offscreen -> onscreen) and implicit detachSurfaceLayer
+      
+      if(DEBUG) {
+          System.err.println("NewtCanvasAWT.detachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
+      }
+    }
+
   // Disables the AWT's erasing of this Canvas's background on Windows
   // in Java SE 6. This internal API is not available in previous
   // releases, but the system property
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
old mode 100755
new mode 100644
index d06aca0..e8cd715
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
@@ -42,6 +42,7 @@ import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLEventListener;
 import javax.media.opengl.GLProfile;
 
+import com.jogamp.common.os.Platform;
 import com.jogamp.newt.awt.NewtCanvasAWT;
 import com.jogamp.newt.opengl.GLWindow;
 
@@ -94,12 +95,11 @@ import com.jogamp.newt.opengl.GLWindow;
 public class JOGLNewtApplet1Run extends Applet {
     public static final boolean DEBUG = JOGLNewtAppletBase.DEBUG;
     
-    GLWindow glWindow;
-    NewtCanvasAWT newtCanvasAWT;
-    JOGLNewtAppletBase base;
+    GLWindow glWindow = null;
+    NewtCanvasAWT newtCanvasAWT = null;
+    JOGLNewtAppletBase base = null;
     /** if valid glStandalone:=true (own window) ! */
     int glXd=Integer.MAX_VALUE, glYd=Integer.MAX_VALUE, glWidth=Integer.MAX_VALUE, glHeight=Integer.MAX_VALUE; 
-    boolean glStandalone = false;
 
     public void init() {
         if(DEBUG) {
@@ -108,7 +108,7 @@ public class JOGLNewtApplet1Run extends Applet {
         if(!(this instanceof Container)) {
             throw new RuntimeException("This Applet is not a AWT Container");
         }
-        Container container = (Container) this;
+        final Container container = (Container) this;
 
         String glEventListenerClazzName=null;
         String glProfileName=null;
@@ -147,7 +147,7 @@ public class JOGLNewtApplet1Run extends Applet {
         if(null==glEventListenerClazzName) {
             throw new RuntimeException("No applet parameter 'gl_event_listener_class'");
         }
-        glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
+        final boolean glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
         if(DEBUG) {
             System.err.println("JOGLNewtApplet1Run Configuration:");
             System.err.println("glStandalone: "+glStandalone);
@@ -209,9 +209,7 @@ public class JOGLNewtApplet1Run extends Applet {
                     addKeyListener((KeyListener)glEventListener);
                 }
             }
-            if(glStandalone) {
-                newtCanvasAWT = null;
-            } else {
+            if( !glStandalone ) {
                 newtCanvasAWT = new NewtCanvasAWT(glWindow);
                 container.add(newtCanvasAWT, BorderLayout.CENTER);
                 container.validate();
@@ -226,13 +224,15 @@ public class JOGLNewtApplet1Run extends Applet {
 
     public void start() {
         if(DEBUG) {
-            System.err.println("JOGLNewtApplet1Run.start() START");
+            System.err.println("JOGLNewtApplet1Run.start() START (isVisible "+isVisible()+", isDisplayable "+isDisplayable()+")");
         }
-        this.validate();
         this.setVisible(true);
-        
         final java.awt.Point p0 = this.getLocationOnScreen();
-        if(glStandalone) {
+        if( null != newtCanvasAWT ) {
+            newtCanvasAWT.setFocusable(true);
+            newtCanvasAWT.requestFocus();
+        } else {
+            glWindow.requestFocus();
             glWindow.setSize(glWidth, glHeight);
             glWindow.setPosition(p0.x+glXd, p0.y+glYd);
         }
@@ -251,6 +251,13 @@ public class JOGLNewtApplet1Run extends Applet {
             System.err.println("GLWindow: "+glWindow);
         }
         base.start();
+        if( null != newtCanvasAWT && Platform.OSType.MACOS == Platform.getOSType() && newtCanvasAWT.isOffscreenLayerSurfaceEnabled() ) {
+            // force relayout
+            final int cW = newtCanvasAWT.getWidth();
+            final int cH = newtCanvasAWT.getHeight();
+            newtCanvasAWT.setSize(cW+1, cH+1);
+            newtCanvasAWT.setSize(cW, cH);
+        }
         if(DEBUG) {
             System.err.println("JOGLNewtApplet1Run.start() END");
         }
@@ -271,12 +278,14 @@ public class JOGLNewtApplet1Run extends Applet {
             System.err.println("JOGLNewtApplet1Run.destroy() START");
         }
         glWindow.setVisible(false); // hide 1st
-        if(!glStandalone) {
+        if( null != newtCanvasAWT ) {
             glWindow.reparentWindow(null); // get out of newtCanvasAWT
             this.remove(newtCanvasAWT); // remove newtCanvasAWT
         }
         base.destroy(); // destroy glWindow unrecoverable
         base=null;
+        glWindow=null;
+        newtCanvasAWT=null;
         if(DEBUG) {
             System.err.println("JOGLNewtApplet1Run.destroy() END");
         }
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
old mode 100755
new mode 100644
index 082c01c..25ddfad
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
@@ -164,12 +164,14 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
                 // Closing action: back to parent!
                 @Override
                 public void windowDestroyNotify(WindowEvent e) {
-                    if( WindowClosingMode.DO_NOTHING_ON_CLOSE == glWindow.getDefaultCloseOperation() ) {
+                    if( isValid() && WindowClosingMode.DO_NOTHING_ON_CLOSE == glWindow.getDefaultCloseOperation() ) {
                         if(null == glWindow.getParent()) {
                             // we may be called directly by the native EDT
                             new Thread(new Runnable() {
                                public void run() {
-                                glWindow.reparentWindow(awtParent);
+                                if( glWindow.isNativeValid() ) {
+                                    glWindow.reparentWindow(awtParent);
+                                }
                                }
                             }).start();                         
                         }                        
@@ -208,7 +210,10 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
             glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
 
             // glAnimator = new FPSAnimator(canvas, 60);
-            glAnimator = new Animator(tg, glWindow);
+            glAnimator = new Animator();
+            glAnimator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); // No AWT thread involved!
+            glAnimator.setThreadGroup(tg);
+            glAnimator.add(glWindow);
             glAnimator.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, null);
             
         } catch (Throwable t) {
@@ -281,11 +286,11 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
     // ***********************************************************************************
     // ***********************************************************************************
 
-    public void keyPressed(KeyEvent e) { 
-    }
-    public void keyReleased(KeyEvent e) { 
-    }
-    public void keyTyped(KeyEvent e) {
+    @Override
+    public void keyPressed(KeyEvent e) {
+       if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+           return;
+       }
        if(e.getKeyChar()=='d') {
             glWindow.setUndecorated(!glWindow.isUndecorated());
        } if(e.getKeyChar()=='f') {
@@ -297,11 +302,13 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
                 glWindow.reparentWindow(awtParent);
             } else {
                 glWindow.reparentWindow(null);
-                if(glClosable) {
-                    glWindow.setDefaultCloseOperation(WindowClosingMode.DISPOSE_ON_CLOSE);
-                }
+                glWindow.setDefaultCloseOperation( glClosable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE );
             }
        }
     }
+    
+    @Override
+    public void keyReleased(KeyEvent e) { 
+    }
 }
 
diff --git a/src/newt/classes/com/jogamp/newt/event/InputEvent.java b/src/newt/classes/com/jogamp/newt/event/InputEvent.java
index 0122bda..b04ebc1 100644
--- a/src/newt/classes/com/jogamp/newt/event/InputEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/InputEvent.java
@@ -70,7 +70,7 @@ public abstract class InputEvent extends NEWTEvent
   * Returns the corresponding button mask for the given button.
   * <p>
   * In case the given button lies outside 
-  * of the valid range [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON6}],
+  * of the valid range [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON_NUMBER}],
   * null is returned.
   * </p>
   */
@@ -81,12 +81,7 @@ public abstract class InputEvent extends NEWTEvent
      return 0;
  }
  
- /** Object when attached via {@link #setAttachment(Object)} marks the event consumed,
-  * ie. stops propagating the event any further to the event listener. 
-  */
- public static final Object consumedTag = new Object();
- 
- protected InputEvent(int eventType, Object source, long when, int modifiers) {
+ protected InputEvent(short eventType, Object source, long when, int modifiers) {
     super(eventType, source, when);
     this.modifiers=modifiers;
  }
@@ -138,7 +133,7 @@ public abstract class InputEvent extends NEWTEvent
     if(isControlDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("ctrl"); }
     if(isMetaDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("meta"); }    
     if(isAltDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("alt"); }
-    if(isAltGraphDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("altg"); }
+    if(isAltGraphDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("altgr"); }
     if(isAutoRepeat()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("repeat"); }
     for(int i=1; i<=MouseEvent.BUTTON_NUMBER; i++) {
         if(isButtonDown(i)) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("button").append(i); }
@@ -154,16 +149,16 @@ public abstract class InputEvent extends NEWTEvent
   * @return Array of pressed mouse buttons  [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON6}]. 
   *         If none is down, the resulting array is of length 0.
   */
- public final int[] getButtonsDown()  {
+ public final short[] getButtonsDown()  {
      int len = 0;
      for(int i=1; i<=MouseEvent.BUTTON_NUMBER; i++) {
-         if(isButtonDown(i)) { len++; }
+         if( isButtonDown(i) ) { len++; }
      }
      
-     int[] res = new int[len];
+     short[] res = new short[len];
      int j = 0;
      for(int i=1; i<=MouseEvent.BUTTON_NUMBER; i++) {
-         if(isButtonDown(i)) { res[j++] = ( MouseEvent.BUTTON1 - 1 ) + i; }
+         if( isButtonDown(i) ) { res[j++] = (short) ( ( MouseEvent.BUTTON1 - 1 ) + i ); }
      }
      return res;
  }
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
index 93c8409..42ebea7 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
@@ -35,7 +35,5 @@ public abstract class KeyAdapter implements KeyListener
  }
  public void keyReleased(KeyEvent e) {
  }
- public void keyTyped(KeyEvent e)  {
- }
 }
 
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
index 289aa31..ec05a34 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
@@ -34,86 +34,209 @@
 
 package com.jogamp.newt.event;
 
+import com.jogamp.common.util.IntBitfield;
+
 /**
+ * <a name="eventDelivery"><h5>KeyEvent Delivery</h5></a> 
+ * 
  * Key events are delivered in the following order:
- * <ol>
- *   <li>{@link #EVENT_KEY_PRESSED}</li>
- *   <li>{@link #EVENT_KEY_RELEASED}</li>
- *   <li>{@link #EVENT_KEY_TYPED}</li>
- * </ol>
+ * <p>
+ * <table border="0">
+ *   <tr><th>#</th><th>Event Type</th>      <th>Constraints</th>  <th>Notes</th></tr>
+ *   <tr><td>1</td><td>{@link #EVENT_KEY_PRESSED}  </td><td> <i> excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys</i></td><td></td></tr>
+ *   <tr><td>2</td><td>{@link #EVENT_KEY_RELEASED} </td><td> <i> excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys</i></td><td></td></tr>
+ * </table>
+ * </p>
  * In case the native platform does not
  * deliver keyboard events in the above order or skip events, 
  * the NEWT driver will reorder and inject synthetic events if required. 
  * <p>
  * Besides regular modifiers like {@link InputEvent#SHIFT_MASK} etc., 
- * the {@link InputEvent#AUTOREPEAT_MASK} bit is added if repetition is detected.
+ * the {@link InputEvent#AUTOREPEAT_MASK} bit is added if repetition is detected, following above constraints.
  * </p>
  * <p>
  * Auto-Repeat shall behave as follow:
  * <pre>
-    D = pressed, U = released, T = typed
+    P = pressed, R = released
     0 = normal, 1 = auto-repeat
 
-    D(0), [ U(1), T(1), D(1), U(1) T(1) ..], U(0) T(0)
+    P(0), [ R(1), P(1), R(1), ..], R(0)    
  * </pre>
  * The idea is if you mask out auto-repeat in your event listener
- * you just get one long pressed key D/U/T triple.
+ * you just get one long pressed P/R tuple for {@link #isPrintableKey() printable} and {@link #isActionKey() Action} keys.
+ * </p>
+ * <p>
+ * {@link #isActionKey() Action} keys will produce {@link #EVENT_KEY_PRESSED pressed} 
+ * and {@link #EVENT_KEY_RELEASED released} events including {@link #isAutoRepeat() auto-repeat}.
+ * </p>
+ * <p>
+ * {@link #isPrintableKey() Printable} keys will produce {@link #EVENT_KEY_PRESSED pressed} and {@link #EVENT_KEY_RELEASED released} events.
+ * </p>
+ * <p>
+ * {@link #isModifierKey() Modifier} keys will produce {@link #EVENT_KEY_PRESSED pressed} and {@link #EVENT_KEY_RELEASED released} events 
+ * excluding {@link #isAutoRepeat() auto-repeat}.
+ * They will also influence subsequent event's {@link #getModifiers() modifier} bits while pressed.
+ * </p>
+ * 
+ * <a name="unicodeMapping"><h5>Unicode Mapping</h5></a>
+ * <p>
+ * {@link #getKeyChar() Key-chars}, as well as 
+ * {@link #isPrintableKey() printable} {@link #getKeyCode() key-codes} and {@link #getKeySymbol() key-symbols}
+ * use the UTF-16 unicode space w/o collision. 
+ * 
+ * </p>
+ * <p>
+ * Non-{@link #isPrintableKey() printable} {@link #getKeyCode() key-codes} and {@link #getKeySymbol() key-symbols}, 
+ * i.e. {@link #isModifierKey() modifier-} and {@link #isActionKey() action-}keys,
+ * are mapped to unicode's control and private range and do not collide w/ {@link #isPrintableKey() printable} unicode values
+ * with the following exception.
+ * </p>
+ * 
+ * <a name="unicodeCollision"><h5>Unicode Collision</h5></a>
+ * <p>
+ * The following {@link #getKeyCode() Key-code}s and {@link #getKeySymbol() key-symbol}s collide w/ unicode space:<br/>
+ * <table border="1">
+ *   <tr><th>unicode range</th>    <th>virtual key code</th>                            <th>unicode character</th></tr>
+ *   <tr><td>[0x61 .. 0x78]</td>   <td>[{@link #VK_F1}..{@link #VK_F24}]</td>           <td>['a'..'x']</td></tr>
+ * </table>
  * </p>
  * <p>
- * {@link #isModifierKey() Modifiers keys} will produce regular events (pressed, released and typed),
- * however they will not produce Auto-Repeat events itself.
+ * Collision was chosen for {@link #getKeyCode() Key-code} and {@link #getKeySymbol() key-symbol} mapping
+ * to allow a minimal code range, i.e. <code>[0..255]</code>.
+ * The reduced code range in turn allows the implementation to utilize fast and small lookup tables, 
+ * e.g. to implement a key-press state tracker. 
+ * </p>  
+ * <pre>
+ * http://www.utf8-chartable.de/unicode-utf8-table.pl
+ * http://www.unicode.org/Public/5.1.0/ucd/PropList.txt
+ * https://en.wikipedia.org/wiki/Mapping_of_Unicode_characters
+ * https://en.wikipedia.org/wiki/Unicode_control_characters
+ * https://en.wikipedia.org/wiki/Private_Use_%28Unicode%29#Private_Use_Areas
+ * </pre>
  * </p>
  */
 @SuppressWarnings("serial")
 public class KeyEvent extends InputEvent
 {
-    public KeyEvent(int eventType, Object source, long when, int modifiers, int keyCode, char keyChar) {
-        super(eventType, source, when, modifiers); 
+    private KeyEvent(short eventType, Object source, long when, int modifiers, short keyCode, short keySym, int keySymModMask, char keyChar) {
+        super(eventType, source, when, modifiers | keySymModMask);
         this.keyCode=keyCode;
+        this.keySym=keySym;
         this.keyChar=keyChar;
+        { // cache modifier and action flags
+            byte _flags = 0;
+            if( isPrintableKey(keySym, false) && isPrintableKey((short)keyChar, true) ) {
+                _flags |= F_PRINTABLE_MASK;
+            } else {
+                if( 0 != keySymModMask ) {
+                    _flags |= F_MODIFIER_MASK;
+                } else {
+                    // A = U - ( P + M )
+                    _flags |= F_ACTION_MASK;
+                }
+            }
+            flags = _flags;
+            
+            //
+            // Validate flags
+            //
+            final int pma_bits = flags & ( F_PRINTABLE_MASK | F_MODIFIER_MASK | F_ACTION_MASK ) ;
+            final int pma_count = IntBitfield.getBitCount(pma_bits);
+            if ( 1 != pma_count ) {
+                throw new InternalError("Key must be either of type printable, modifier or action - but it is of "+pma_count+" types: "+this);
+            }
+        }
+    }
+    
+    public static KeyEvent create(short eventType, Object source, long when, int modifiers, short keyCode, short keySym, char keyChar) {
+        return new KeyEvent(eventType, source, when, modifiers, keyCode, keySym, getModifierMask(keySym), keyChar);
     }
 
     /** 
-     * Returns the character matching the {@link #getKeyCode() virtual key code}, if exist.
-     * <p>
-     * <b>Disclaimer</b>: Only valid on all platforms at {@link KeyListener#keyTyped(KeyEvent)}.
-     * Precisely, on the Windows platform we currently cannot deliver the proper character
-     * in case of shifted keys where no uppercase exists, e.g. 'shift + 1' doesn't produce '!'.
-     * </p> 
+     * Returns the <i>UTF-16</i> character reflecting the {@link #getKeySymbol() key symbol}
+     * incl. active {@link #isModifierKey() modifiers}.
+     * @see #getKeySymbol()
+     * @see #getKeyCode()
      */
-    public char getKeyChar() {
+    public final char getKeyChar() {
         return keyChar;
     }
 
-    /** Returns the virtual key code. */
-    public int getKeyCode() {
+    /** 
+     * Returns the virtual <i>key symbol</i> reflecting the current <i>keyboard layout</i>.
+     * <p>
+     * For {@link #isPrintableKey() printable keys}, the <i>key symbol</i> is the {@link #isModifierKey() unmodified}
+     * representation of the UTF-16 {@link #getKeyChar() key char}.<br/> 
+     * E.g. symbol [{@link #VK_A}, 'A'] for char 'a'. 
+     * </p>
+     * @see #isPrintableKey()
+     * @see #getKeyChar()
+     * @see #getKeyCode()
+     */
+    public final short getKeySymbol() {
+        return keySym;
+    }
+    
+    /** 
+     * Returns the virtual <i>key code</i> using a fixed mapping to the <i>US keyboard layout</i>.
+     * <p>
+     * In contrast to {@link #getKeySymbol() key symbol}, <i>key code</i> 
+     * uses a fixed <i>US keyboard layout</i> and therefore is keyboard layout independent. 
+     * </p>
+     * <p>
+     * E.g. <i>virtual key code</i> {@link #VK_Y} denotes the same physical key 
+     * regardless whether <i>keyboard layout</i> <code>QWERTY</code> or 
+     * <code>QWERTZ</code> is active. The {@link #getKeySymbol() key symbol} of the former is
+     * {@link #VK_Y}, where the latter produces {@link #VK_Y}. 
+     * </p>
+     * @see #getKeyChar()
+     * @see #getKeySymbol()
+     */
+    public final short getKeyCode() {
         return keyCode;
     }
 
-    public String toString() {
+    public final String toString() {
         return toString(null).toString();
     }
 
-    public StringBuilder toString(StringBuilder sb) {
+    public final StringBuilder toString(StringBuilder sb) {
         if(null == sb) {
             sb = new StringBuilder();
         }
-        sb.append("KeyEvent[").append(getEventTypeString(getEventType())).append(", code ").append(keyCode).append("(").append(toHexString(keyCode)).append("), char '").append(keyChar).append("' (").append(toHexString((int)keyChar)).append("), isActionKey ").append(isActionKey()).append(", ");
+        sb.append("KeyEvent[").append(getEventTypeString(getEventType())).append(", code ").append(toHexString(keyCode)).append(", sym ").append(toHexString(keySym)).append(", char '").append(keyChar).append("' (").append(toHexString((short)keyChar))
+        .append("), printable ").append(isPrintableKey()).append(", modifier ").append(isModifierKey()).append(", action ").append(isActionKey()).append(", ");
         return super.toString(sb).append("]");
     }
 
-    public static String getEventTypeString(int type) {
+    public static String getEventTypeString(short type) {
         switch(type) {
         case EVENT_KEY_PRESSED: return "EVENT_KEY_PRESSED";
         case EVENT_KEY_RELEASED: return "EVENT_KEY_RELEASED";
-        case EVENT_KEY_TYPED: return "EVENT_KEY_TYPED";
         default: return "unknown (" + type + ")";
         }
     }
 
-    /** Returns true if <code>keyCode</code> represents a modifier key, i.e. one of {@link #VK_SHIFT}, {@link #VK_CONTROL}, {@link #VK_ALT}, {@link #VK_ALT_GRAPH}, {@link #VK_META}. */
-    public static boolean isModifierKey(int keyCode) {
-        switch (keyCode) {
+    /**
+     * @param keyChar UTF16 value to map. It is expected that the incoming keyChar value is unshifted and unmodified,
+     *        however, lower case a-z is mapped to {@link KeyEvent#VK_A} - {@link KeyEvent#VK_Z}.
+     * @return {@link KeyEvent} virtual key (VK) value.
+     */
+    public static short utf16ToVKey(char keyChar) {
+        if( 'a' <= keyChar && keyChar <= 'z' ) {
+            return (short) ( ( keyChar - 'a' ) + KeyEvent.VK_A );
+        }
+        return (short) keyChar;
+    }
+    
+    /** 
+     * Returns <code>true</code> if the given <code>virtualKey</code> represents a modifier key, otherwise <code>false</code>. 
+     * <p>
+     * A modifier key is one of {@link #VK_SHIFT}, {@link #VK_CONTROL}, {@link #VK_ALT}, {@link #VK_ALT_GRAPH}, {@link #VK_META}.
+     * </p>
+     */
+    public static boolean isModifierKey(short vKey) {
+        switch (vKey) {
             case VK_SHIFT:
             case VK_CONTROL:
             case VK_ALT:
@@ -125,625 +248,704 @@ public class KeyEvent extends InputEvent
         }
     }
     
-    /** Returns true if {@link #getKeyCode()} represents a modifier key, i.e. one of {@link #VK_SHIFT}, {@link #VK_CONTROL}, {@link #VK_ALT}, {@link #VK_ALT_GRAPH}, {@link #VK_META}. */
-    public boolean isModifierKey() {
-        return isModifierKey(keyCode);
-    }
-    
-    public boolean isActionKey() {
-        switch (keyCode) {
-            case VK_HOME:
-            case VK_END:
-            case VK_PAGE_UP:
-            case VK_PAGE_DOWN:
-            case VK_UP:
-            case VK_DOWN:
-            case VK_LEFT:
-            case VK_RIGHT:
-    
-            case VK_F1:
-            case VK_F2:
-            case VK_F3:
-            case VK_F4:
-            case VK_F5:
-            case VK_F6:
-            case VK_F7:
-            case VK_F8:
-            case VK_F9:
-            case VK_F10:
-            case VK_F11:
-            case VK_F12:
-            case VK_F13:
-            case VK_F14:
-            case VK_F15:
-            case VK_F16:
-            case VK_F17:
-            case VK_F18:
-            case VK_F19:
-            case VK_F20:
-            case VK_F21:
-            case VK_F22:
-            case VK_F23:
-            case VK_F24:
-            case VK_PRINTSCREEN:
-            case VK_CAPS_LOCK:
-            case VK_PAUSE:
-            case VK_INSERT:
-    
-            case VK_HELP:
-            case VK_WINDOWS:
-                return true;
-        }
-        return false;
-    }
-
-    private final int keyCode;
-    private final char keyChar;
-
-    public static final int EVENT_KEY_PRESSED = 300;
-    public static final int EVENT_KEY_RELEASED= 301;
-    public static final int EVENT_KEY_TYPED   = 302;
-
-    /* Virtual key codes. */
-
-    public static final int VK_CANCEL         = 0x03;
-    public static final int VK_BACK_SPACE     = 0x08; // '\b'
-    public static final int VK_TAB            = 0x09; // '\t'
-    public static final int VK_ENTER          = 0x0A; // '\n'
-    public static final int VK_CLEAR          = 0x0C;
-    public static final int VK_SHIFT          = 0x10;
-    public static final int VK_CONTROL        = 0x11;
-    public static final int VK_ALT            = 0x12;
-    public static final int VK_PAUSE          = 0x13;
-    public static final int VK_CAPS_LOCK      = 0x14;
-    public static final int VK_ESCAPE         = 0x1B;
-    public static final int VK_SPACE          = 0x20;
-    public static final int VK_PAGE_UP        = 0x21;
-    public static final int VK_PAGE_DOWN      = 0x22;
-    public static final int VK_END            = 0x23;
-    public static final int VK_HOME           = 0x24;
-
     /**
-     * Constant for the non-numpad <b>left</b> arrow key.
-     * @see #VK_KP_LEFT
+     * If <code>vKey</code> is a {@link #isModifierKey() modifier key}, method returns the corresponding modifier mask,
+     * otherwise 0. 
      */
-    public static final int VK_LEFT           = 0x25;
-
-    /**
-     * Constant for the non-numpad <b>up</b> arrow key.
-     * @see #VK_KP_UP
-     */
-    public static final int VK_UP             = 0x26;
-
-    /**
-     * Constant for the non-numpad <b>right</b> arrow key.
-     * @see #VK_KP_RIGHT
-     */
-    public static final int VK_RIGHT          = 0x27;
-
-    /**
-     * Constant for the non-numpad <b>down</b> arrow key.
-     * @see #VK_KP_DOWN
+    public static int getModifierMask(short vKey) {
+        switch (vKey) {
+            case VK_SHIFT:
+                return InputEvent.SHIFT_MASK;
+            case VK_CONTROL:
+                return InputEvent.CTRL_MASK;
+            case VK_ALT:
+            case VK_ALT_GRAPH:
+                return InputEvent.ALT_MASK;
+            case VK_META:
+                return InputEvent.META_MASK;
+        }
+        return 0;
+    }
+    
+    /** 
+     * Returns <code>true</code> if {@link #getKeySymbol() key symbol} represents a modifier key,
+     * otherwise <code>false</code>. 
+     * <p>
+     * See {@link #isModifierKey(short)} for details.
+     * </p>
+     * <p>
+     * Note: Implementation uses a cached value.
+     * </p>
      */
-    public static final int VK_DOWN           = 0x28;
-
+    public final boolean isModifierKey() {
+        return 0 != ( F_MODIFIER_MASK & flags ) ;
+    }
+    
+    /** 
+     * Returns <code>true</code> if {@link #getKeySymbol() key symbol} represents a non-printable and
+     * non-{@link #isModifierKey(short) modifier} action key, otherwise <code>false</code>.
+     * <p>
+     * Hence it is the set A of all keys U w/o printable P and w/o modifiers M:
+     * <code> A = U - ( P + M ) </code>
+     * </p>
+     * @see #isPrintableKey()
+     * @see #isModifierKey() 
+     */
+    public final boolean isActionKey() {
+        return 0 != ( F_ACTION_MASK & flags ) ;
+    }
+    
     /**
-     * Constant for the comma key, ","
-     */
-    public static final int VK_COMMA          = 0x2C;
+     * Returns <code>true</code> if given <code>uniChar</code> represents a printable character,
+     * i.e. a value other than {@link #VK_UNDEFINED} and not a control or non-printable private code.
+     * <p>
+     * A printable character is neither a {@link #isModifierKey(short) modifier key}, nor an {@link #isActionKey(short) action key}.
+     * </p>
+     * <p>
+     * Otherwise returns <code>false</code>.
+     * </p>
+     * <p>
+     * Distinction of key character and virtual key code is made due to <a href="#unicodeCollision">unicode collision</a>.
+     * </p>
+     * 
+     * @param uniChar the UTF-16 unicode value, which maybe a virtual key code or key character.
+     * @param isKeyChar true if <code>uniChar</code> is a key character, otherwise a virtual key code
+     */
+    public static boolean isPrintableKey(final short uniChar, final boolean isKeyChar) {
+        if( VK_UNDEFINED == uniChar  ) {
+            return false;
+        }
+        if( !isKeyChar ) {
+            if( ( nonPrintableKeys[0].min <= uniChar && uniChar <= nonPrintableKeys[0].max ) ||
+                ( nonPrintableKeys[1].min <= uniChar && uniChar <= nonPrintableKeys[1].max ) ||
+                ( nonPrintableKeys[2].min <= uniChar && uniChar <= nonPrintableKeys[2].max ) || 
+                ( nonPrintableKeys[3].min <= uniChar && uniChar <= nonPrintableKeys[3].max ) ) {
+                return false;
+            }
+        } else {
+            if( ( nonPrintableKeys[0].inclKeyChar && nonPrintableKeys[0].min <= uniChar && uniChar <= nonPrintableKeys[0].max ) ||
+                ( nonPrintableKeys[1].inclKeyChar && nonPrintableKeys[1].min <= uniChar && uniChar <= nonPrintableKeys[1].max ) ||
+                ( nonPrintableKeys[2].inclKeyChar && nonPrintableKeys[2].min <= uniChar && uniChar <= nonPrintableKeys[2].max ) ||
+                ( nonPrintableKeys[3].inclKeyChar && nonPrintableKeys[3].min <= uniChar && uniChar <= nonPrintableKeys[3].max ) ) {
+                return false;
+            }
+        }
+        return true;
+    }
 
-    /**
-     * Constant for the minus key, "-"
-     * @since 1.2
+    /** 
+     * Returns <code>true</code> if {@link #getKeySymbol() key symbol} and {@link #getKeyChar() key char} 
+     * represents a printable character, i.e. a value other than {@link #VK_UNDEFINED} 
+     * and not a control or non-printable private code.
+     * <p>
+     * A printable character is neither a {@link #isModifierKey(short) modifier key}, nor an {@link #isActionKey(short) action key}.
+     * </p>
+     * <p>
+     * Otherwise returns <code>false</code>.
+     * </p>
      */
-    public static final int VK_MINUS          = 0x2D;
+    public final boolean isPrintableKey() {
+        return 0 != ( F_PRINTABLE_MASK & flags ) ;
+    }
+    
+    private final short keyCode;
+    private final short keySym;
+    private final char keyChar;
+    private final byte flags;
+    private static final byte F_MODIFIER_MASK   = 1 << 0;
+    private static final byte F_ACTION_MASK     = 1 << 1;
+    private static final byte F_PRINTABLE_MASK  = 1 << 2;
 
-    /**
-     * Constant for the period key, "."
-     */
-    public static final int VK_PERIOD         = 0x2E;
+    /** A key has been pressed, excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys. */
+    public static final short EVENT_KEY_PRESSED = 300;
+    /** A key has been released, excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys. */
+    public static final short EVENT_KEY_RELEASED= 301;
 
     /**
-     * Constant for the forward slash key, "/"
+     * This value, {@code '\0'}, is used to indicate that the keyChar is unknown or not printable.
      */
-    public static final int VK_SLASH          = 0x2F;
-
-    /** VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */
-    public static final int VK_0              = 0x30;
-    public static final int VK_1              = 0x31;
-    public static final int VK_2              = 0x32;
-    public static final int VK_3              = 0x33;
-    public static final int VK_4              = 0x34;
-    public static final int VK_5              = 0x35;
-    public static final int VK_6              = 0x36;
-    public static final int VK_7              = 0x37;
-    public static final int VK_8              = 0x38;
-    public static final int VK_9              = 0x39;
+    public static final char  NULL_CHAR                   = '\0';
 
-    /**
-     * Constant for the semicolon key, ";"
-     */
-    public static final int VK_SEMICOLON      = 0x3B;
+    /* Virtual key codes. */
 
+    public static class NonPrintableRange {
+        /** min. unicode value, inclusive */
+        public short min; 
+        /** max. unicode value, inclusive */
+        public short max;
+        /** true if valid for keyChar values as well, otherwise only valid for keyCode and keySym due to collision. */
+        public final boolean inclKeyChar;
+        private NonPrintableRange(short min, short max, boolean inclKeyChar) {
+            this.min = min;
+            this.max = max;
+            this.inclKeyChar = inclKeyChar;
+        }
+    };
+    /** Non printable key ranges, currently fixed to an array of size 4. */
+    public final static NonPrintableRange[] nonPrintableKeys = { 
+        new NonPrintableRange( (short)0x0000, (short)0x001F, true ),  // Unicode: Non printable controls: [0x00 - 0x1F]
+        new NonPrintableRange( (short)0x0061, (short)0x0078, false),  // Small 'a' thru 'z' (0x61 - 0x7a) - Not used for keyCode / keySym - Re-used for Fn (collision)
+        new NonPrintableRange( (short)0x008F, (short)0x009F, true ),  // Unicode: Non printable controls: [0x7F - 0x9F], Numpad keys [0x7F - 0x8E] are printable! 
+        new NonPrintableRange( (short)0xE000, (short)0xF8FF, true )   // Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
+    };
+    
+    //
+    // Unicode: Non printable controls: [0x00 - 0x1F]
+    //
+    
     /**
-     * Constant for the equals key, "="
+     * This value, {@value}, is used to indicate that the keyCode is unknown.
      */
-    public static final int VK_EQUALS         = 0x3D;
-
-    /** VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
-    public static final int VK_A              = 0x41;
-    public static final int VK_B              = 0x42;
-    public static final int VK_C              = 0x43;
-    public static final int VK_D              = 0x44;
-    public static final int VK_E              = 0x45;
-    public static final int VK_F              = 0x46;
-    public static final int VK_G              = 0x47;
-    public static final int VK_H              = 0x48;
-    public static final int VK_I              = 0x49;
-    public static final int VK_J              = 0x4A;
-    public static final int VK_K              = 0x4B;
-    public static final int VK_L              = 0x4C;
-    public static final int VK_M              = 0x4D;
-    public static final int VK_N              = 0x4E;
-    public static final int VK_O              = 0x4F;
-    public static final int VK_P              = 0x50;
-    public static final int VK_Q              = 0x51;
-    public static final int VK_R              = 0x52;
-    public static final int VK_S              = 0x53;
-    public static final int VK_T              = 0x54;
-    public static final int VK_U              = 0x55;
-    public static final int VK_V              = 0x56;
-    public static final int VK_W              = 0x57;
-    public static final int VK_X              = 0x58;
-    public static final int VK_Y              = 0x59;
-    public static final int VK_Z              = 0x5A;
+    public static final short VK_UNDEFINED      = (short) 0x0;
+    
+           static final short VK_FREE01         = (short) 0x01;
+    
+    /** Constant for the HOME function key. ASCII: Start Of Text. */
+    public static final short VK_HOME           = (short) 0x02;
+    
+    /** Constant for the END function key. ASCII: End Of Text. */
+    public static final short VK_END            = (short) 0x03;
+    
+    /** Constant for the END function key. ASCII: End Of Transmission. */
+    public static final short VK_FINAL          = (short) 0x04;
 
-    /**
-     * Constant for the open bracket key, "["
-     */
-    public static final int VK_OPEN_BRACKET   = 0x5B;
+    /** Constant for the PRINT function key. ASCII: Enquiry. */
+    public static final short VK_PRINTSCREEN    = (short) 0x05;
+    
+           static final short VK_FREE06         = (short) 0x06;
+           static final short VK_FREE07         = (short) 0x07;
+    
+    /** Constant for the BACK SPACE key "\b", matching ASCII. */
+    public static final short VK_BACK_SPACE     = (short) 0x08;
+    
+    /** Constant for the HORIZ TAB key "\t", matching ASCII. */
+    public static final short VK_TAB            = (short) 0x09;
+    
+    /** Constant for the ENTER key, i.e. LINE FEED "\n", matching ASCII. */
+    public static final short VK_ENTER          = (short) 0x0A;
+    
+    /** Constant for the PAGE DOWN function key. ASCII: Vertical Tabulation. */
+    public static final short VK_PAGE_DOWN      = (short) 0x0B;
+    
+    /** Constant for the CLEAR key, i.e. FORM FEED, matching ASCII. */
+    public static final short VK_CLEAR          = (short) 0x0C;
+    
+           static final short VK_FREE0D         = (short) 0x0D;
+           static final short VK_FREE0E         = (short) 0x0E;
+    
+    /** Constant for the CTRL function key. ASCII: shift-in. */
+    public static final short VK_SHIFT          = (short) 0x0F;
 
-    /**
-     * Constant for the back slash key, "\"
-     */
-    public static final int VK_BACK_SLASH     = 0x5C;
+    /** Constant for the PAGE UP function key. ASCII: Data Link Escape. */
+    public static final short VK_PAGE_UP        = (short) 0x10;
+    
+    /** Constant for the CTRL function key. ASCII: device-ctrl-one. */
+    public static final short VK_CONTROL        = (short) 0x11;
+    
+    /** Constant for the left ALT function key. ASCII: device-ctrl-two. */
+    public static final short VK_ALT            = (short) 0x12;
+    
+    /** Constant for the ALT_GRAPH function key, i.e. right ALT key. ASCII: device-ctrl-three. */
+    public static final short VK_ALT_GRAPH      = (short) 0x13;
+    
+    /** Constant for the CAPS LOCK function key. ASCII: device-ctrl-four. */
+    public static final short VK_CAPS_LOCK      = (short) 0x14;
+    
+           static final short VK_FREE15         = (short) 0x15;
+    
+    /** Constant for the PAUSE function key. ASCII: sync-idle. */
+    public static final short VK_PAUSE          = (short) 0x16;
+    
+    /** <b>scroll lock</b> key. ASCII: End Of Transmission Block. */
+    public static final short VK_SCROLL_LOCK    = (short) 0x17;
+        
+    /** Constant for the CANCEL function key. ASCII: Cancel. */
+    public static final short VK_CANCEL         = (short) 0x18;
+    
+           static final short VK_FREE19         = (short) 0x19;
+    
+    /** Constant for the INSERT function key. ASCII: Substitute. */
+    public static final short VK_INSERT         = (short) 0x1A;
+    
+    /** Constant for the ESCAPE function key. ASCII: Escape. */
+    public static final short VK_ESCAPE         = (short) 0x1B;
+        
+    /** Constant for the Convert function key, Japanese "henkan". ASCII: File Separator. */
+    public static final short VK_CONVERT        = (short) 0x1C;
+
+    /** Constant for the Don't Convert function key, Japanese "muhenkan". ASCII: Group Separator.*/
+    public static final short VK_NONCONVERT     = (short) 0x1D;
+
+    /** Constant for the Accept or Commit function key, Japanese "kakutei". ASCII: Record Separator.*/
+    public static final short VK_ACCEPT         = (short) 0x1E;
+
+    /** Constant for the Mode Change (?). ASCII: Unit Separator.*/
+    public static final short VK_MODECHANGE     = (short) 0x1F;
+
+    //
+    // Unicode: Printable [0x20 - 0x7E]
+    // NOTE: Collision of 'a' - 'x' [0x61 .. 0x78], used for keyCode/keySym Fn function keys 
+    //
+        
+    /** Constant for the SPACE function key. ASCII: SPACE. */
+    public static final short VK_SPACE          = (short) 0x20;
+    
+    /** Constant for the "!" key. */
+    public static final short VK_EXCLAMATION_MARK = (short) 0x21;
 
-    /**
-     * Constant for the close bracket key, "]"
-     */
-    public static final int VK_CLOSE_BRACKET  = 0x5D;
-
-    public static final int VK_NUMPAD0        = 0x60;
-    public static final int VK_NUMPAD1        = 0x61;
-    public static final int VK_NUMPAD2        = 0x62;
-    public static final int VK_NUMPAD3        = 0x63;
-    public static final int VK_NUMPAD4        = 0x64;
-    public static final int VK_NUMPAD5        = 0x65;
-    public static final int VK_NUMPAD6        = 0x66;
-    public static final int VK_NUMPAD7        = 0x67;
-    public static final int VK_NUMPAD8        = 0x68;
-    public static final int VK_NUMPAD9        = 0x69;
-    public static final int VK_MULTIPLY       = 0x6A;
-    public static final int VK_ADD            = 0x6B;
+    /** Constant for the """ key. */
+    public static final short VK_QUOTEDBL       = (short) 0x22;
+    
+    /** Constant for the "#" key. */
+    public static final short VK_NUMBER_SIGN    = (short) 0x23;
 
+    /** Constant for the "$" key. */
+    public static final short VK_DOLLAR         = (short) 0x24;
+    
+    /** Constant for the "%" key. */
+    public static final short VK_PERCENT        = (short) 0x25;
+    
+    /** Constant for the "&" key. */
+    public static final short VK_AMPERSAND      = (short) 0x26;
+    
+    /** Constant for the "'" key. */
+    public static final short VK_QUOTE          = (short) 0x27;
+    
+    /** Constant for the "(" key. */
+    public static final short VK_LEFT_PARENTHESIS  = (short) 0x28;
+    
+    /** Constant for the ")" key. */
+    public static final short VK_RIGHT_PARENTHESIS = (short) 0x29;
+    
+    /** Constant for the "*" key */
+    public static final short VK_ASTERISK       = (short) 0x2A;
+    
+    /** Constant for the "+" key. */
+    public static final short VK_PLUS           = (short) 0x2B;
+    
+    /** Constant for the comma key, "," */
+    public static final short VK_COMMA          = (short) 0x2C;
+    
+    /** Constant for the minus key, "-" */
+    public static final short VK_MINUS          = (short) 0x2D;
+
+    /** Constant for the period key, "." */
+    public static final short VK_PERIOD         = (short) 0x2E;
+
+    /** Constant for the forward slash key, "/" */
+    public static final short VK_SLASH          = (short) 0x2F;
+
+    /** VK_0 thru VK_9 are the same as UTF16/ASCII '0' thru '9' [0x30 - 0x39] */
+    public static final short VK_0              = (short) 0x30;
+    /** See {@link #VK_0}. */
+    public static final short VK_1              = (short) 0x31;
+    /** See {@link #VK_0}. */
+    public static final short VK_2              = (short) 0x32;
+    /** See {@link #VK_0}. */
+    public static final short VK_3              = (short) 0x33;
+    /** See {@link #VK_0}. */
+    public static final short VK_4              = (short) 0x34;
+    /** See {@link #VK_0}. */
+    public static final short VK_5              = (short) 0x35;
+    /** See {@link #VK_0}. */
+    public static final short VK_6              = (short) 0x36;
+    /** See {@link #VK_0}. */
+    public static final short VK_7              = (short) 0x37;
+    /** See {@link #VK_0}. */
+    public static final short VK_8              = (short) 0x38;
+    /** See {@link #VK_0}. */
+    public static final short VK_9              = (short) 0x39;
+
+    /** Constant for the ":" key. */
+    public static final short VK_COLON          = (short) 0x3A;
+
+    /** Constant for the semicolon key, ";" */
+    public static final short VK_SEMICOLON      = (short) 0x3B;
+
+    /** Constant for the equals key, "<" */
+    public static final short VK_LESS           = (short) 0x3C;
+
+    /** Constant for the equals key, "=" */
+    public static final short VK_EQUALS         = (short) 0x3D;
+
+    /** Constant for the equals key, ">" */
+    public static final short VK_GREATER        = (short) 0x3E;
+    
+    /** Constant for the equals key, "?" */
+    public static final short VK_QUESTIONMARK   = (short) 0x3F;
+    
+    /** Constant for the equals key, "@" */
+    public static final short VK_AT             = (short) 0x40;
+    
+    /** VK_A thru VK_Z are the same as Capital UTF16/ASCII 'A' thru 'Z' (0x41 - 0x5A) */
+    public static final short VK_A              = (short) 0x41;
+    /** See {@link #VK_A}. */
+    public static final short VK_B              = (short) 0x42;
+    /** See {@link #VK_A}. */
+    public static final short VK_C              = (short) 0x43;
+    /** See {@link #VK_A}. */
+    public static final short VK_D              = (short) 0x44;
+    /** See {@link #VK_A}. */
+    public static final short VK_E              = (short) 0x45;
+    /** See {@link #VK_A}. */
+    public static final short VK_F              = (short) 0x46;
+    /** See {@link #VK_A}. */
+    public static final short VK_G              = (short) 0x47;
+    /** See {@link #VK_A}. */
+    public static final short VK_H              = (short) 0x48;
+    /** See {@link #VK_A}. */
+    public static final short VK_I              = (short) 0x49;
+    /** See {@link #VK_A}. */
+    public static final short VK_J              = (short) 0x4A;
+    /** See {@link #VK_A}. */
+    public static final short VK_K              = (short) 0x4B;
+    /** See {@link #VK_A}. */
+    public static final short VK_L              = (short) 0x4C;
+    /** See {@link #VK_A}. */
+    public static final short VK_M              = (short) 0x4D;
+    /** See {@link #VK_A}. */
+    public static final short VK_N              = (short) 0x4E;
+    /** See {@link #VK_A}. */
+    public static final short VK_O              = (short) 0x4F;
+    /** See {@link #VK_A}. */
+    public static final short VK_P              = (short) 0x50;
+    /** See {@link #VK_A}. */
+    public static final short VK_Q              = (short) 0x51;
+    /** See {@link #VK_A}. */
+    public static final short VK_R              = (short) 0x52;
+    /** See {@link #VK_A}. */
+    public static final short VK_S              = (short) 0x53;
+    /** See {@link #VK_A}. */
+    public static final short VK_T              = (short) 0x54;
+    /** See {@link #VK_A}. */
+    public static final short VK_U              = (short) 0x55;
+    /** See {@link #VK_A}. */
+    public static final short VK_V              = (short) 0x56;
+    /** See {@link #VK_A}. */
+    public static final short VK_W              = (short) 0x57;
+    /** See {@link #VK_A}. */
+    public static final short VK_X              = (short) 0x58;
+    /** See {@link #VK_A}. */
+    public static final short VK_Y              = (short) 0x59;
+    /** See {@link #VK_A}. */
+    public static final short VK_Z              = (short) 0x5A;
+
+    /** Constant for the open bracket key, "[" */
+    public static final short VK_OPEN_BRACKET   = (short) 0x5B;
+
+    /**Constant for the back slash key, "\" */
+    public static final short VK_BACK_SLASH     = (short) 0x5C;
+
+    /** Constant for the close bracket key, "]" */
+    public static final short VK_CLOSE_BRACKET  = (short) 0x5D;
+
+    /** Constant for the "^" key. */
+    public static final short VK_CIRCUMFLEX     = (short) 0x5E;
+
+    /** Constant for the "_" key */
+    public static final short VK_UNDERSCORE     = (short) 0x5F;
+    
+    /** Constant for the "`" key */
+    public static final short VK_BACK_QUOTE     = (short) 0x60;
+    
+    /** Small UTF/ASCII 'a' thru 'z' (0x61 - 0x7a) - Not used for keyCode / keySym. */
+    
     /** 
-     * Constant for the Numpad Separator key. 
+     * Constant for the F<i>n</i> function keys. 
+     * <p>
+     * F1..F24, i.e. F<i>n</i>, are mapped from on <code>0x60+n</code> -> <code>[0x61 .. 0x78]</code>.
+     * </p> 
+     * <p>
+     * <b>Warning:</b> The F<i>n</i> function keys <b>do collide</b> with unicode characters small 'a' thru 'x'!<br/>
+     * See <a href="#unicodeCollision">Unicode Collision</a> for details.
+     * </p>
      */
-    public static final int VK_SEPARATOR      = 0x6C;
+    public static final short VK_F1             = (short) ( 0x60+ 1 );
 
-    public static final int VK_SUBTRACT       = 0x6D;
-    public static final int VK_DECIMAL        = 0x6E;
-    public static final int VK_DIVIDE         = 0x6F;
-    public static final int VK_DELETE         = 0x7F; /* ASCII DEL */
-    public static final int VK_NUM_LOCK       = 0x90;
-    public static final int VK_SCROLL_LOCK    = 0x91;
+    /** Constant for the F2 function key. See {@link #VK_F1}. */
+    public static final short VK_F2             = (short) ( 0x60+ 2 );
 
-    /** Constant for the F1 function key. */
-    public static final int VK_F1             = 0x70;
+    /** Constant for the F3 function key. See {@link #VK_F1}. */
+    public static final short VK_F3             = (short) ( 0x60+ 3 );
 
-    /** Constant for the F2 function key. */
-    public static final int VK_F2             = 0x71;
+    /** Constant for the F4 function key. See {@link #VK_F1}. */
+    public static final short VK_F4             = (short) ( 0x60+ 4 );
 
-    /** Constant for the F3 function key. */
-    public static final int VK_F3             = 0x72;
+    /** Constant for the F5 function key. See {@link #VK_F1}. */
+    public static final short VK_F5             = (short) ( 0x60+ 5 );
 
-    /** Constant for the F4 function key. */
-    public static final int VK_F4             = 0x73;
+    /** Constant for the F6 function key. See {@link #VK_F1}. */
+    public static final short VK_F6             = (short) ( 0x60+ 6 );
 
-    /** Constant for the F5 function key. */
-    public static final int VK_F5             = 0x74;
+    /** Constant for the F7 function key. See {@link #VK_F1}. */
+    public static final short VK_F7             = (short) ( 0x60+ 7 );
 
-    /** Constant for the F6 function key. */
-    public static final int VK_F6             = 0x75;
+    /** Constant for the F8 function key. See {@link #VK_F1}. */
+    public static final short VK_F8             = (short) ( 0x60+ 8 );
 
-    /** Constant for the F7 function key. */
-    public static final int VK_F7             = 0x76;
+    /** Constant for the F9 function key. See {@link #VK_F1}. */
+    public static final short VK_F9             = (short) ( 0x60+ 9 );
 
-    /** Constant for the F8 function key. */
-    public static final int VK_F8             = 0x77;
+    /** Constant for the F11 function key. See {@link #VK_F1}. */
+    public static final short VK_F10            = (short) ( 0x60+10 );
 
-    /** Constant for the F9 function key. */
-    public static final int VK_F9             = 0x78;
+    /** Constant for the F11 function key. See {@link #VK_F1}. */
+    public static final short VK_F11            = (short) ( 0x60+11 );
 
-    /** Constant for the F10 function key. */
-    public static final int VK_F10            = 0x79;
+    /** Constant for the F12 function key. See {@link #VK_F1}.*/
+    public static final short VK_F12            = (short) ( 0x60+12 );
 
-    /** Constant for the F11 function key. */
-    public static final int VK_F11            = 0x7A;
+    /** Constant for the F13 function key. See {@link #VK_F1}. */
+    public static final short VK_F13            = (short) ( 0x60+13 );
 
-    /** Constant for the F12 function key. */
-    public static final int VK_F12            = 0x7B;
-
-    /**
-     * Constant for the F13 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F13            = 0xF000;
-
-    /**
-     * Constant for the F14 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F14            = 0xF001;
-
-    /**
-     * Constant for the F15 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F15            = 0xF002;
+    /** Constant for the F14 function key. See {@link #VK_F1}. */
+    public static final short VK_F14            = (short) ( 0x60+14 );
 
-    /**
-     * Constant for the F16 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F16            = 0xF003;
+    /** Constant for the F15 function key. See {@link #VK_F1}. */
+    public static final short VK_F15            = (short) ( 0x60+15 );
 
-    /**
-     * Constant for the F17 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F17            = 0xF004;
+    /** Constant for the F16 function key. See {@link #VK_F1}. */
+    public static final short VK_F16            = (short) ( 0x60+16 );
 
-    /**
-     * Constant for the F18 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F18            = 0xF005;
+    /** Constant for the F17 function key. See {@link #VK_F1}. */
+    public static final short VK_F17            = (short) ( 0x60+17 );
 
-    /**
-     * Constant for the F19 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F19            = 0xF006;
+    /** Constant for the F18 function key. See {@link #VK_F1}. */
+    public static final short VK_F18            = (short) ( 0x60+18 );
 
-    /**
-     * Constant for the F20 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F20            = 0xF007;
+    /** Constant for the F19 function key. See {@link #VK_F1}. */
+    public static final short VK_F19            = (short) ( 0x60+19 );
 
-    /**
-     * Constant for the F21 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F21            = 0xF008;
+    /** Constant for the F20 function key. See {@link #VK_F1}. */
+    public static final short VK_F20            = (short) ( 0x60+20 );
 
-    /**
-     * Constant for the F22 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F22            = 0xF009;
+    /** Constant for the F21 function key. See {@link #VK_F1}. */
+    public static final short VK_F21            = (short) ( 0x60+21 );
 
-    /**
-     * Constant for the F23 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F23            = 0xF00A;
+    /** Constant for the F22 function key. See {@link #VK_F1}. */
+    public static final short VK_F22            = (short) ( 0x60+22 );
 
-    /**
-     * Constant for the F24 function key.
-     * <p>F13 - F24 are used on IBM 3270 keyboard; use random range for constants.</p>
-     */
-    public static final int VK_F24            = 0xF00B;
+    /** Constant for the F23 function key. See {@link #VK_F1}. */
+    public static final short VK_F23            = (short) ( 0x60+23 );
 
-    public static final int VK_PRINTSCREEN    = 0x9A;
-    public static final int VK_INSERT         = 0x9B;
-    public static final int VK_HELP           = 0x9C;
-    public static final int VK_META           = 0x9D;
+    /** Constant for the F24 function key. See {@link #VK_F1}. */
+    public static final short VK_F24            = (short) ( 0x60+24 );
 
-    public static final int VK_BACK_QUOTE     = 0xC0;
-    public static final int VK_QUOTE          = 0xDE;
-
-    /**
-     * Constant for the numeric keypad <b>up</b> arrow key.
-     * @see #VK_UP
-     */
-    public static final int VK_KP_UP          = 0xE0;
-
-    /**
-     * Constant for the numeric keypad <b>down</b> arrow key.
-     * @see #VK_DOWN
-     */
-    public static final int VK_KP_DOWN        = 0xE1;
-
-    /**
-     * Constant for the numeric keypad <b>left</b> arrow key.
-     * @see #VK_LEFT
-     */
-    public static final int VK_KP_LEFT        = 0xE2;
+    
+    /** Constant for the "{" key */
+    public static final short VK_LEFT_BRACE     = (short) 0x7B;
+    /** Constant for the "|" key */
+    public static final short VK_PIPE           = (short) 0x7C;
+    /** Constant for the "}" key */
+    public static final short VK_RIGHT_BRACE    = (short) 0x7D;
+    
+    /** Constant for the "~" key, matching ASCII */
+    public static final short VK_TILDE          = (short) 0x7E;
+    
+    //
+    // Unicode: Non printable controls: [0x7F - 0x9F]
+    //
+    // Numpad keys [0x7F - 0x8E] are printable
+    //
+    
+    /** Numeric keypad <b>decimal separator</b> key. Non printable UTF control. */
+    public static final short VK_SEPARATOR      = (short) 0x7F;
+    
+    /** Numeric keypad VK_NUMPAD0 thru VK_NUMPAD9 are mapped to UTF control (0x80 - 0x89). Non printable UTF control. */
+    public static final short VK_NUMPAD0        = (short) 0x80;
+    /** See {@link #VK_NUMPAD0}. */
+    public static final short VK_NUMPAD1        = (short) 0x81;
+    /** See {@link #VK_NUMPAD0}. */
+    public static final short VK_NUMPAD2        = (short) 0x82;
+    /** See {@link #VK_NUMPAD0}. */
+    public static final short VK_NUMPAD3        = (short) 0x83;
+    /** See {@link #VK_NUMPAD0}. */
+    public static final short VK_NUMPAD4        = (short) 0x84;
+    /** See {@link #VK_NUMPAD0}. */
+    public static final short VK_NUMPAD5        = (short) 0x85;
+    /** See {@link #VK_NUMPAD0}. */
+    public static final short VK_NUMPAD6        = (short) 0x86;
+    /** See {@link #VK_NUMPAD0}. */
+    public static final short VK_NUMPAD7        = (short) 0x87;
+    /** See {@link #VK_NUMPAD0}. */
+    public static final short VK_NUMPAD8        = (short) 0x88;
+    /** See {@link #VK_NUMPAD0}. */
+    public static final short VK_NUMPAD9        = (short) 0x89;
+    
+    /** Numeric keypad <b>decimal separator</b> key. Non printable UTF control. */
+    public static final short VK_DECIMAL        = (short) 0x8A;
+        
+    /** Numeric keypad <b>add</b> key. Non printable UTF control. */
+    public static final short VK_ADD            = (short) 0x8B;
+
+    /** Numeric keypad <b>subtract</b> key. Non printable UTF control. */
+    public static final short VK_SUBTRACT       = (short) 0x8C;
+    
+    /** Numeric keypad <b>multiply</b> key. Non printable UTF control. */
+    public static final short VK_MULTIPLY       = (short) 0x8D;
+    
+    /** Numeric keypad <b>divide</b> key. Non printable UTF control. */
+    public static final short VK_DIVIDE         = (short) 0x8E;
+    
+    /** Constant for the DEL key, matching ASCII. Non printable UTF control. */
+    public static final short VK_DELETE         = (short) 0x93;
+    
+    /** Numeric keypad <b>num lock</b> key. Non printable UTF control. */
+    public static final short VK_NUM_LOCK       = (short) 0x94;
+    
+    /** Constant for the cursor- or numerical-pad <b>left</b> arrow key. Non printable UTF control. */
+    public static final short VK_LEFT           = (short) 0x95;
 
-    /**
-     * Constant for the numeric keypad <b>right</b> arrow key.
-     * @see #VK_RIGHT
-     */
-    public static final int VK_KP_RIGHT       = 0xE3;
-
-    /** For European keyboards */
-    public static final int VK_DEAD_GRAVE               = 0x80;
-    /** For European keyboards */
-    public static final int VK_DEAD_ACUTE               = 0x81;
-    /** For European keyboards */
-    public static final int VK_DEAD_CIRCUMFLEX          = 0x82;
-    /** For European keyboards */
-    public static final int VK_DEAD_TILDE               = 0x83;
-    /** For European keyboards */
-    public static final int VK_DEAD_MACRON              = 0x84;
-    /** For European keyboards */
-    public static final int VK_DEAD_BREVE               = 0x85;
-    /** For European keyboards */
-    public static final int VK_DEAD_ABOVEDOT            = 0x86;
-    /** For European keyboards */
-    public static final int VK_DEAD_DIAERESIS           = 0x87;
-    /** For European keyboards */
-    public static final int VK_DEAD_ABOVERING           = 0x88;
-    /** For European keyboards */
-    public static final int VK_DEAD_DOUBLEACUTE         = 0x89;
-    /** For European keyboards */
-    public static final int VK_DEAD_CARON               = 0x8a;
-    /** For European keyboards */
-    public static final int VK_DEAD_CEDILLA             = 0x8b;
-    /** For European keyboards */
-    public static final int VK_DEAD_OGONEK              = 0x8c;
-    /** For European keyboards */
-    public static final int VK_DEAD_IOTA                = 0x8d;
-    /** For European keyboards */
-    public static final int VK_DEAD_VOICED_SOUND        = 0x8e;
-    /** For European keyboards */
-    public static final int VK_DEAD_SEMIVOICED_SOUND    = 0x8f;
-
-    /** For European keyboards */
-    public static final int VK_AMPERSAND                = 0x96;
-    /** For European keyboards */
-    public static final int VK_ASTERISK                 = 0x97;
-    /** For European keyboards */
-    public static final int VK_QUOTEDBL                 = 0x98;
-    /** For European keyboards */
-    public static final int VK_LESS                     = 0x99;
-
-    /** For European keyboards */
-    public static final int VK_GREATER                  = 0xa0;
-    /** For European keyboards */
-    public static final int VK_BRACELEFT                = 0xa1;
-    /** For European keyboards */
-    public static final int VK_BRACERIGHT               = 0xa2;
+    /** Constant for the cursor- or numerical-pad <b>up</b> arrow key. Non printable UTF control. */
+    public static final short VK_UP             = (short) 0x96;
 
-    /**
-     * Constant for the "@" key.
-     */
-    public static final int VK_AT                       = 0x0200;
+    /** Constant for the cursor- or numerical-pad <b>right</b> arrow key. Non printable UTF control. */
+    public static final short VK_RIGHT          = (short) 0x97;
 
-    /**
-     * Constant for the ":" key.
-     */
-    public static final int VK_COLON                    = 0x0201;
+    /** Constant for the cursor- or numerical pad <b>down</b> arrow key. Non printable UTF control. */
+    public static final short VK_DOWN           = (short) 0x98;
+        
+    /** Constant for the Context Menu key. Non printable UTF control. */
+    public static final short VK_CONTEXT_MENU   = (short) 0x99;
 
     /**
-     * Constant for the "^" key.
+     * Constant for the MS "Windows" function key.
+     * It is used for both the left and right version of the key.  
      */
-    public static final int VK_CIRCUMFLEX               = 0x0202;
+    public static final short VK_WINDOWS        = (short) 0x9A;
 
-    /**
-     * Constant for the "$" key.
-     */
-    public static final int VK_DOLLAR                   = 0x0203;
+    /** Constant for the Meta function key. */
+    public static final short VK_META           = (short) 0x9B;
+    
+    /** Constant for the Help function key. */
+    public static final short VK_HELP           = (short) 0x9C;
+    
+    /** Constant for the Compose function key. */
+    public static final short VK_COMPOSE        = (short) 0x9D;
 
-    /**
-     * Constant for the Euro currency sign key.
-     */
-    public static final int VK_EURO_SIGN                = 0x0204;
+    /** Constant for the Begin function key. */
+    public static final short VK_BEGIN          = (short) 0x9E;
 
-    /**
-     * Constant for the "!" key.
-     */
-    public static final int VK_EXCLAMATION_MARK         = 0x0205;
-
-    /**
-     * Constant for the inverted exclamation mark key.
-     */
-    public static final int VK_INVERTED_EXCLAMATION_MARK = 0x0206;
+    /** Constant for the Stop function key. */
+    public static final short VK_STOP           = (short) 0x9F;
+    
+    //
+    // Unicode: Printable [0x00A0 - 0xDFFF]
+    //
+    
+    /** Constant for the inverted exclamation mark key. */
+    public static final short VK_INVERTED_EXCLAMATION_MARK = (short) 0xA1;
+    
+    /** Constant for the Euro currency sign key. */
+    public static final short VK_EURO_SIGN                = (short) 0x20AC;
 
-    /**
-     * Constant for the "(" key.
-     */
-    public static final int VK_LEFT_PARENTHESIS         = 0x0207;
+    //
+    // Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
+    //
+    
+    /* for Sun keyboards */
+    public static final short VK_CUT            = (short) 0xF879;
+    public static final short VK_COPY           = (short) 0xF87A;
+    public static final short VK_PASTE          = (short) 0xF87B;
+    public static final short VK_UNDO           = (short) 0xF87C;
+    public static final short VK_AGAIN          = (short) 0xF87D;
+    public static final short VK_FIND           = (short) 0xF87E;
+    public static final short VK_PROPS          = (short) 0xF87F;
 
-    /**
-     * Constant for the "#" key.
-     */
-    public static final int VK_NUMBER_SIGN              = 0x0208;
+    /* for input method support on Asian Keyboards */
 
     /**
-     * Constant for the "+" key.
+     * Constant for the input method on/off key.
      */
-    public static final int VK_PLUS                     = 0x0209;
-
+    /* Japanese PC 106 keyboard: kanji. Japanese Solaris keyboard: nihongo */
+    public static final short VK_INPUT_METHOD_ON_OFF = (short) 0xF890;
+    
     /**
-     * Constant for the ")" key.
+     * Constant for the Code Input function key.
      */
-    public static final int VK_RIGHT_PARENTHESIS        = 0x020A;
+    /* Japanese PC 106 keyboard - VK_ALPHANUMERIC + ALT: kanji bangou */
+    public static final short VK_CODE_INPUT = (short) 0xF891;
 
     /**
-     * Constant for the "_" key.
+     * Constant for the Roman Characters function key.
      */
-    public static final int VK_UNDERSCORE               = 0x020B;
+    /* Japanese PC 106 keyboard: roumaji */
+    public static final short VK_ROMAN_CHARACTERS = (short) 0xF892;
 
     /**
-     * Constant for the Microsoft Windows "Windows" key.
-     * It is used for both the left and right version of the key.  
+     * Constant for the All Candidates function key.
      */
-    public static final int VK_WINDOWS                  = 0x020C;
+    /* Japanese PC 106 keyboard - VK_CONVERT + ALT: zenkouho */
+    public static final short VK_ALL_CANDIDATES = (short) 0xF893;
 
     /**
-     * Constant for the Microsoft Windows Context Menu key.
+     * Constant for the Previous Candidate function key.
      */
-    public static final int VK_CONTEXT_MENU             = 0x020D;
-
-    /* for input method support on Asian Keyboards */
-
-    /* not clear what this means - listed in Microsoft Windows API */
-    public static final int VK_FINAL                    = 0x0018;
-
-    /** Constant for the Convert function key. */
-    /* Japanese PC 106 keyboard, Japanese Solaris keyboard: henkan */
-    public static final int VK_CONVERT                  = 0x001C;
-
-    /** Constant for the Don't Convert function key. */
-    /* Japanese PC 106 keyboard: muhenkan */
-    public static final int VK_NONCONVERT               = 0x001D;
-
-    /** Constant for the Accept or Commit function key. */
-    /* Japanese Solaris keyboard: kakutei */
-    public static final int VK_ACCEPT                   = 0x001E;
-
-    /* not clear what this means - listed in Microsoft Windows API */
-    public static final int VK_MODECHANGE               = 0x001F;
-
-    /* replaced by VK_KANA_LOCK for Microsoft Windows and Solaris; 
-       might still be used on other platforms */
-    public static final int VK_KANA                     = 0x0015;
-
-    /* replaced by VK_INPUT_METHOD_ON_OFF for Microsoft Windows and Solaris; 
-       might still be used for other platforms */
-    public static final int VK_KANJI                    = 0x0019;
+    /* Japanese PC 106 keyboard - VK_CONVERT + SHIFT: maekouho */
+    public static final short VK_PREVIOUS_CANDIDATE = (short) 0xF894;
 
     /**
      * Constant for the Alphanumeric function key.
      */
     /* Japanese PC 106 keyboard: eisuu */
-    public static final int VK_ALPHANUMERIC             = 0x00F0;
+    public static final short VK_ALPHANUMERIC   = (short) 0xF895;
 
     /**
      * Constant for the Katakana function key.
      */
     /* Japanese PC 106 keyboard: katakana */
-    public static final int VK_KATAKANA                 = 0x00F1;
+    public static final short VK_KATAKANA       = (short) 0xF896;
 
     /**
      * Constant for the Hiragana function key.
      */
     /* Japanese PC 106 keyboard: hiragana */
-    public static final int VK_HIRAGANA                 = 0x00F2;
+    public static final short VK_HIRAGANA       = (short) 0xF897;
 
     /**
      * Constant for the Full-Width Characters function key.
      */
     /* Japanese PC 106 keyboard: zenkaku */
-    public static final int VK_FULL_WIDTH               = 0x00F3;
+    public static final short VK_FULL_WIDTH     = (short) 0xF898;
 
     /**
      * Constant for the Half-Width Characters function key.
      */
     /* Japanese PC 106 keyboard: hankaku */
-    public static final int VK_HALF_WIDTH               = 0x00F4;
-
-    /**
-     * Constant for the Roman Characters function key.
-     */
-    /* Japanese PC 106 keyboard: roumaji */
-    public static final int VK_ROMAN_CHARACTERS         = 0x00F5;
-
-    /**
-     * Constant for the All Candidates function key.
-     */
-    /* Japanese PC 106 keyboard - VK_CONVERT + ALT: zenkouho */
-    public static final int VK_ALL_CANDIDATES           = 0x0100;
-
-    /**
-     * Constant for the Previous Candidate function key.
-     */
-    /* Japanese PC 106 keyboard - VK_CONVERT + SHIFT: maekouho */
-    public static final int VK_PREVIOUS_CANDIDATE       = 0x0101;
-
-    /**
-     * Constant for the Code Input function key.
-     */
-    /* Japanese PC 106 keyboard - VK_ALPHANUMERIC + ALT: kanji bangou */
-    public static final int VK_CODE_INPUT               = 0x0102;
+    public static final short VK_HALF_WIDTH     = (short) 0xF89A;
 
     /**
      * Constant for the Japanese-Katakana function key.
      * This key switches to a Japanese input method and selects its Katakana input mode.
      */
     /* Japanese Macintosh keyboard - VK_JAPANESE_HIRAGANA + SHIFT */
-    public static final int VK_JAPANESE_KATAKANA        = 0x0103;
+    public static final short VK_JAPANESE_KATAKANA = (short) 0xF89B;
 
     /**
      * Constant for the Japanese-Hiragana function key.
      * This key switches to a Japanese input method and selects its Hiragana input mode.
      */
     /* Japanese Macintosh keyboard */
-    public static final int VK_JAPANESE_HIRAGANA        = 0x0104;
+    public static final short VK_JAPANESE_HIRAGANA = (short) 0xF89C;
 
     /**
      * Constant for the Japanese-Roman function key.
      * This key switches to a Japanese input method and selects its Roman-Direct input mode.
      */
     /* Japanese Macintosh keyboard */
-    public static final int VK_JAPANESE_ROMAN           = 0x0105;
+    public static final short VK_JAPANESE_ROMAN = (short) 0xF89D;
 
     /**
      * Constant for the locking Kana function key.
      * This key locks the keyboard into a Kana layout.
      */
     /* Japanese PC 106 keyboard with special Windows driver - eisuu + Control; Japanese Solaris keyboard: kana */
-    public static final int VK_KANA_LOCK                = 0x0106;
-
-    /**
-     * Constant for the input method on/off key.
-     */
-    /* Japanese PC 106 keyboard: kanji. Japanese Solaris keyboard: nihongo */
-    public static final int VK_INPUT_METHOD_ON_OFF      = 0x0107;
-
-    /* for Sun keyboards */
-    public static final int VK_CUT                      = 0xFFD1;
-    public static final int VK_COPY                     = 0xFFCD;
-    public static final int VK_PASTE                    = 0xFFCF;
-    public static final int VK_UNDO                     = 0xFFCB;
-    public static final int VK_AGAIN                    = 0xFFC9;
-    public static final int VK_FIND                     = 0xFFD0;
-    public static final int VK_PROPS                    = 0xFFCA;
-    public static final int VK_STOP                     = 0xFFC8;
+    public static final short VK_KANA_LOCK = (short) 0xF89F;
 
     /**
-     * Constant for the Compose function key.
+     * Constant for Keyboard became invisible, e.g. Android's soft keyboard Back button hit while keyboard is visible.
      */
-    public static final int VK_COMPOSE                  = 0xFF20;
+    public static final short VK_KEYBOARD_INVISIBLE = (short) 0xF8FF;
 
-    /**
-     * Constant for the AltGraph function key.
-     */
-    public static final int VK_ALT_GRAPH                = 0xFF7E;
-
-    /**
-     * Constant for the Begin key.
-     */
-    public static final int VK_BEGIN                    = 0xFF58;
-
-    /**
-     * This value is used to indicate that the keyCode is unknown.
-     * KEY_TYPED events do not have a keyCode value; this value 
-     * is used instead.  
-     */
-    public static final int VK_UNDEFINED      = 0x0;
 }
 
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyListener.java b/src/newt/classes/com/jogamp/newt/event/KeyListener.java
index dae343d..b3927d8 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyListener.java
@@ -34,10 +34,28 @@
 
 package com.jogamp.newt.event;
 
+/**
+ * Listener for {@link KeyEvent}s.
+ * 
+ * @see KeyEvent
+ */
 public interface KeyListener extends NEWTEventListener
 {
- public void keyPressed(KeyEvent e);
- public void keyReleased(KeyEvent e);
- public void keyTyped(KeyEvent e) ;
+    /** A key has been {@link KeyEvent#EVENT_KEY_PRESSED pressed}, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. See {@link KeyEvent}. */
+    public void keyPressed(KeyEvent e);
+    
+    /** 
+     * A key has been {@link KeyEvent#EVENT_KEY_RELEASED released}, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. See {@link KeyEvent}.
+     * <p>
+     * To simulated the removed <code>keyTyped(KeyEvent e)</code> semantics,
+     * simply apply the following constraints upfront and bail out if not matched, i.e.:
+     * <pre>
+        if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+            return;
+        }            
+     * </pre>
+     * </p> 
+     */
+    public void keyReleased(KeyEvent e);
 }
 
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java b/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java
similarity index 57%
copy from src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
copy to src/newt/classes/com/jogamp/newt/event/MonitorEvent.java
index e3f0373..c47936a 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java
@@ -1,16 +1,16 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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
@@ -20,39 +20,52 @@
  * 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.newt.event;
 
-import javax.media.nativewindow.util.Rectangle;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
 
 @SuppressWarnings("serial")
-public class WindowUpdateEvent extends WindowEvent {
-    final Rectangle bounds;
-
-    public WindowUpdateEvent(int eventType, Object source, long when, Rectangle bounds)
-    {
+public class MonitorEvent extends OutputEvent {
+    public static final short EVENT_MONITOR_MODE_CHANGE_NOTIFY = 600;
+    public static final short EVENT_MONITOR_MODE_CHANGED       = 601;
+    
+    private final MonitorMode mode;
+    
+    public MonitorEvent (short eventType, MonitorDevice source, long when, MonitorMode mode) {
         super(eventType, source, when);
-        this.bounds = bounds;
+        this.mode = mode;
     }
-
-    public Rectangle getBounds() {
-        return bounds;
+    
+    /** Returns the {@link #getSource() source}, which is a {@link MonitorDevice}. */
+    public final MonitorDevice getMonitor() { return (MonitorDevice)source; }
+    
+    public final MonitorMode getMode() { return mode; }
+    
+    public static String getEventTypeString(short type) {
+        switch(type) {
+        case EVENT_MONITOR_MODE_CHANGE_NOTIFY: return "EVENT_MONITOR_MODE_CHANGE_NOTIFY";
+        case EVENT_MONITOR_MODE_CHANGED: return "EVENT_MONITOR_MODE_CHANGED";
+        default: return "unknown (" + type + ")";
+        }
     }
-
-    public String toString() {
+    
+    public final String toString() {
         return toString(null).toString();
     }
 
-    public StringBuilder toString(StringBuilder sb) {
+    public final StringBuilder toString(StringBuilder sb) {
         if(null == sb) {
             sb = new StringBuilder();
         }
-        sb.append("WindowUpdateEvent[").append(bounds).append(", ");
+        sb.append("MonitorEvent[").append(getEventTypeString(getEventType())).append(", source ").append(source)
+        .append(", mode ").append(mode).append(", ");
         return super.toString(sb).append("]");
     }
 }
diff --git a/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java b/src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java
similarity index 84%
rename from src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java
rename to src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java
index 7bca23c..11e23de 100644
--- a/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java
@@ -28,12 +28,10 @@
 
 package com.jogamp.newt.event;
 
-import com.jogamp.newt.ScreenMode;
+public interface MonitorModeListener {
+    /** called before the monitor mode will be changed */
+    void monitorModeChangeNotify(MonitorEvent me);
 
-public interface ScreenModeListener {
-    /** called before the screen mode will be changed */
-    void screenModeChangeNotify(ScreenMode sm);
-
-    /** called after the screen mode has been changed */
-    void screenModeChanged(ScreenMode sm, boolean success);
+    /** called after the monitor mode has been changed */
+    void monitorModeChanged(MonitorEvent me, boolean success);
 }
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
index 914aaa6..18c8285 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
@@ -34,52 +34,101 @@
 
 package com.jogamp.newt.event;
 
+/**
+ * Pointer event of type {@link PointerType}.
+ * <p>
+ * In case an instance represents multi-touch events, i.e. {@link #getPointerCount()} is > 1,
+ * the first data element represents the pointer which triggered the action if individual to one pointer.<br/>
+ * For example {@link #getX(int) e.getX(0)} at {@link #EVENT_MOUSE_PRESSED} returns the data of the pressed pointer, etc.
+ * </p>
+ */
 @SuppressWarnings("serial")
 public class MouseEvent extends InputEvent
 {
+    /** Class of pointer types */
+    public static enum PointerClass{
+        Offscreen, Onscreen, Undefined;
+    }
+    
+    /** Type of pointer devices */
+    public static enum PointerType{
+        /** {@link PointerClass#Offscreen} mouse. */
+        Mouse(PointerClass.Offscreen),
+        /** {@link PointerClass#Offscreen} touch pad, usually using fingers. */
+        TouchPad(PointerClass.Offscreen),
+        /** {@link PointerClass#Onscreen} touch screen, usually using fingers. */
+        TouchScreen(PointerClass.Onscreen),
+        /** {@link PointerClass#Onscreen} pen on screen ?. */
+        Pen(PointerClass.Onscreen),
+        Undefined(PointerClass.Undefined);
+        
+        public PointerClass getPointerClass() { return pc; }
+        
+        private PointerType(PointerClass pc) {
+            this.pc = pc;
+        }
+        PointerClass pc;
+    }
+    
     /** ID for button 1, value <code>1</code> */
-    public static final int BUTTON1 = 1;
+    public static final short BUTTON1 = 1;
     /** ID for button 2, value <code>2</code> */
-    public static final int BUTTON2 = 2;
+    public static final short BUTTON2 = 2;
     /** ID for button 3, value <code>3</code> */
-    public static final int BUTTON3 = 3;
+    public static final short BUTTON3 = 3;
     /** ID for button 4, value <code>4</code> */
-    public static final int BUTTON4 = 4;
+    public static final short BUTTON4 = 4;
     /** ID for button 5, value <code>5</code> */
-    public static final int BUTTON5 = 5;
+    public static final short BUTTON5 = 5;
     /** ID for button 6, value <code>6</code> */
-    public static final int BUTTON6 = 6;
+    public static final short BUTTON6 = 6;
     /** ID for button 6, value <code>7</code> */
-    public static final int BUTTON7 = 7;
+    public static final short BUTTON7 = 7;
     /** ID for button 6, value <code>8</code> */
-    public static final int BUTTON8 = 8;
+    public static final short BUTTON8 = 8;
     /** ID for button 6, value <code>9</code> */
-    public static final int BUTTON9 = 9;
+    public static final short BUTTON9 = 9;
     
     /** Maximum number of buttons, value <code>16</code> */
-    public static final int BUTTON_NUMBER =  16;
+    public static final short BUTTON_NUMBER =  16;
 
-    public static final int getClickTimeout() { 
+    /** Returns the 3-axis XYZ rotation array by given rotation on Y axis or X axis (if SHIFT_MASK is given in mods). */ 
+    public static final float[] getRotationXYZ(final float rotationXorY, final int mods) {
+        final float[] rotationXYZ = new float[] { 0f, 0f, 0f };
+        if( 0 != ( mods & InputEvent.SHIFT_MASK ) ) {
+            rotationXYZ[0] = rotationXorY;
+        } else {
+            rotationXYZ[1] = rotationXorY;
+        }
+        return rotationXYZ;
+    }
+    
+    public static final short getClickTimeout() { 
         return 300; 
     }
-
-    public MouseEvent(int eventType, Object source, long when,
-            int modifiers, int x, int y, int clickCount, int button,
-            int rotation)
+        
+    /** Constructor for tradition 1-pointer mouse events. */ 
+    public MouseEvent(short eventType, Object source, long when,
+            int modifiers, int x, int y, short clickCount, short button,
+            float[] rotationXYZ, float rotationScale)
     {
         super(eventType, source, when, modifiers); 
         this.x = new int[]{x};
         this.y = new int[]{y};
-        this.pressure = new float[]{0};
-        this.pointerids = new int[]{-1};
+        this.pressure = constMousePressure;
+        this.maxPressure= 1.0f;
+        this.pointerIDs = constMousePointerIDs;
         this.clickCount=clickCount;
         this.button=button;
-        this.wheelRotation = rotation;
+        this.rotationXYZ = rotationXYZ;
+        this.rotationScale = rotationScale;
+        this.pointerTypes = constMousePointerTypes;
     }
 
-    public MouseEvent(int eventType, Object source, long when,
-            int modifiers, int[] x, int[] y, float[] pressure, int[] pointerids, int clickCount, int button,
-            int rotation)
+    /** Constructor for multi-touch pointer events. */ 
+    public MouseEvent(short eventType, Object source, long when,
+                      int modifiers, int[] x, int[] y, float[] pressure, float maxPressure, PointerType pointerTypes[], short[] pointerids, short clickCount,
+                      short button, float[] rotationXYZ, float rotationScale)
     {
         super(eventType, source, when, modifiers); 
         this.x = x;
@@ -89,11 +138,17 @@ public class MouseEvent extends InputEvent
            pointerids.length != y.length) {
             throw new IllegalArgumentException("All multiple pointer arrays must be of same size");
         }
+        if( 0.0f >= maxPressure ) {
+            throw new IllegalArgumentException("maxPressure must be > 0.0f");
+        }
         this.pressure = pressure;
-        this.pointerids = pointerids;
+        this.maxPressure= maxPressure;
+        this.pointerIDs = pointerids;
         this.clickCount=clickCount;
         this.button=button;
-        this.wheelRotation = rotation;
+        this.rotationXYZ = rotationXYZ;
+        this.rotationScale = rotationScale;
+        this.pointerTypes = pointerTypes;
     }
     
     /**
@@ -104,20 +159,32 @@ public class MouseEvent extends InputEvent
     }
     
     /**
+     * @return the {@link PointerType} for the data at index.
+     *  return null if index not available.
+     */
+    public PointerType getPointerType(int index) {
+        if(index >= pointerIDs.length) {
+            return null;
+        }
+        return pointerTypes[index];
+    }
+    
+    /**
      * @return the pointer id for the data at index.
      *  return -1 if index not available.
      */
-    public int getPointerId(int index) {
-        if(index >= pointerids.length)
+    public short getPointerId(int index) {
+        if(index >= pointerIDs.length) {
             return -1;
-        return pointerids[index];
+        }
+        return pointerIDs[index];
     }
     
-    public int getButton() {
+    public short getButton() {
         return button;
     }
     
-    public int getClickCount() {
+    public short getClickCount() {
         return clickCount;
     }
     public int getX() {
@@ -129,48 +196,149 @@ public class MouseEvent extends InputEvent
     }
 
     /** 
-     * @return x-coord at index where index refers to the 
-     * data coming from a pointer. 
+     * @param index pointer-index within [0 .. {@link #getPointerCount()}-1]
+     * @return X-Coord associated with the pointer-index.
      * @see getPointerId(index)
      */
     public int getX(int index) {
         return x[index];
     }
 
+    /** 
+     * @param index pointer-index within [0 .. {@link #getPointerCount()}-1]
+     * @return Y-Coord associated with the pointer-index.
+     * @see getPointerId(index)
+     */
     public int getY(int index) {
         return y[index];
     }
     
-    public float getPressure(){
-        return pressure[0];
+    /**
+     * @param normalized if true, method returns the normalized pressure, i.e. <code>pressure / maxPressure</code> 
+     * @return The pressure associated with the pointer-index 0.
+     *         The value of zero is return if not available.
+     * @see #getMaxPressure()
+     */
+    public float getPressure(boolean normalized){
+        return normalized ? pressure[0] / maxPressure : pressure[0];
+    }
+    
+    /** 
+     * Returns the maximum pressure known for the input device generating this event.
+     * <p>
+     * This value may be self calibrating on devices/OS, where no known maximum pressure is known.
+     * Hence subsequent events may return a higher value. 
+     * </p>
+     * <p>
+     * Self calibrating maximum pressure is performed on:
+     * <ul>
+     *   <li>Android</li>
+     * </ul>
+     * </p>
+     */
+    public float getMaxPressure() {
+        return maxPressure;
     }
     
     /**
-     * @return the pressure associated with the pointer at index.
-     * the value of zero is return if not available.
+     * @param index pointer-index within [0 .. {@link #getPointerCount()}-1]
+     * @param normalized if true, method returns the normalized pressure, i.e. <code>pressure / maxPressure</code> 
+     * @return The pressure associated with the pointer-index.
+     *         The value of zero is return if not available.
+     * @see #getMaxPressure()
      */
-    public float getPressure(int index){
-        return pressure[index];
+    public float getPressure(int index, boolean normalized){
+        return normalized ? pressure[index] / maxPressure : pressure[index];
     }
     
     /**
-     * <i>Usually</i> a wheel rotation of <b>> 0 is up</b>,
-     * and  <b>< 0 is down</b>.<br>
+     * <i>Usually</i> a wheel rotation of <b>> 0.0f is up</b>,
+     * and <b>< 0.0f is down</b>.
+     * <p>
+     * Usually a wheel rotations is considered a vertical scroll.<br/>
+     * If {@link #isShiftDown()}, a wheel rotations is
+     * considered a horizontal scroll, where <b>shift-up = left = > 0.0f</b>,
+     * and <b>shift-down = right = < 0.0f</b>.   
+     * </p>
+     * <p>
      * <i>However</i>, on some OS this might be flipped due to the OS <i>default</i> behavior.
      * The latter is true for OS X 10.7 (Lion) for example.
+     * </p>
      * <p>
-     * The events will be send usually in steps of one, ie. <i>-1</i> and <i>1</i>.
+     * The events will be send usually in steps of one, ie. <i>-1.0f</i> and <i>1.0f</i>.
      * Higher values may result due to fast scrolling.
+     * Fractional values may result due to slow scrolling with high resolution devices.  
      * </p>
      * <p>
      * The button number refers to the wheel number.
-     * </p> 
-     * @return
+     * </p>
+     * @deprecated Use {@link #getRotation()}
      */
-    public int getWheelRotation() {
-        return wheelRotation;
+    public float getWheelRotation() {
+        return isShiftDown() ? rotationXYZ[0] : rotationXYZ[1] ;
     }
 
+    /**
+     * Returns a 3-component float array filled with the values of the rotational axis
+     * in the following order: horizontal-, vertical- and z-axis.
+     * <p> 
+     * A vertical rotation of <b>> 0.0f is up</b> and <b>< 0.0f is down</b>.
+     * </p>
+     * <p>
+     * A horizontal rotation of <b>> 0.0f is left</b> and <b>< 0.0f is right</b>.   
+     * </p>
+     * <p>
+     * A z-axis rotation of <b>> 0.0f is back</b> and <b>< 0.0f is front</b>.   
+     * </p>
+     * <p>
+     * <i>However</i>, on some OS this might be flipped due to the OS <i>default</i> behavior.
+     * The latter is true for OS X 10.7 (Lion) for example.
+     * </p>
+     * <p>
+     * On PointerClass {@link PointerClass#Onscreen onscreen} devices, i.e. {@link PointerType#TouchScreen touch screens}, 
+     * rotation events are usually produced by a 2-finger movement, where horizontal and vertical rotation values are filled.
+     * </p>
+     * <p>
+     * On PointerClass {@link PointerClass#Offscreen offscreen} devices, i.e. {@link PointerType#Mouse mouse},
+     * either the horizontal or the vertical rotation value is filled.
+     * </p>
+     * <p>
+     * The {@link InputEvent#SHIFT_MASK} modifier is set in case <b>|horizontal| > |vertical|</b> value.<br/>
+     * This can be utilized to implement only one 2d rotation direction, you may use {@link #isShiftDown()} to query it.  
+     * </p>
+     * <p>
+     * In case the pointer type is {@link PointerType#Mouse mouse},
+     * events are usually send in steps of one, ie. <i>-1.0f</i> and <i>1.0f</i>.
+     * Higher values may result due to fast scrolling.
+     * Fractional values may result due to slow scrolling with high resolution devices.<br/>  
+     * Here the button number refers to the wheel number.
+     * </p>
+     * <p>
+     * In case the pointer type is of class {@link PointerClass#Onscreen}, e.g. {@link PointerType#TouchScreen touch screen},
+     * see {@link #getRotationScale()} for semantics.
+     * </p>
+     */
+    public float[] getRotation() {
+        return rotationXYZ;
+    }
+    
+    /** 
+     * Returns the scale used to determine the {@link #getRotation() rotation value},
+     * which semantics depends on the {@link #getPointerType() pointer type's} {@link PointerClass}.
+     * <p>
+     * For {@link PointerClass#Offscreen}, the scale is usually <code>1.0f</code> and denominates
+     * an abstract value without association to a physical value.
+     * </p> 
+     * <p>
+     * For {@link PointerClass#Onscreen}, the scale varies and denominates
+     * the divisor of the distance the finger[s] have moved on the screen. 
+     * Hence <code>scale * rotation</code> reproduces the screen distance in pixels the finger[s] have moved. 
+     * </p> 
+     */
+    public float getRotationScale() {
+        return rotationScale;
+    }
+    
     public String toString() {
         return toString(null).toString();
     }
@@ -182,16 +350,16 @@ public class MouseEvent extends InputEvent
         sb.append("MouseEvent[").append(getEventTypeString(getEventType()))
         .append(", ").append(x).append("/").append(y)
         .append(", button ").append(button).append(", count ")
-        .append(clickCount).append(", wheel rotation ").append(wheelRotation);
-        if(pointerids.length>0) {
-            sb.append(", pointer<").append(pointerids.length).append(">[");
-            for(int i=0; i<pointerids.length; i++) {
+        .append(clickCount).append(", rotation [").append(rotationXYZ[0]).append(", ").append(rotationXYZ[1]).append(", ").append(rotationXYZ[2]).append("] * ").append(rotationScale);
+        if(pointerIDs.length>0) {
+            sb.append(", pointer<").append(pointerIDs.length).append(">[");
+            for(int i=0; i<pointerIDs.length; i++) {
                 if(i>0) {
                     sb.append(", ");
                 }
-                sb.append(pointerids[i]).append(": ")
-                .append(x[i]).append(" / ").append(y[i]).append(" ")
-                .append(pressure[i]).append("p");
+                sb.append(pointerIDs[i]).append("/").append(pointerTypes[i]).append(": ")
+                .append(x[i]).append("/").append(y[i]).append(", ")
+                .append("p[").append(pressure[i]).append("/").append(maxPressure).append("=").append(pressure[i]/maxPressure).append("]");
             }
             sb.append("]");
         }        
@@ -199,7 +367,7 @@ public class MouseEvent extends InputEvent
         return super.toString(sb).append("]");
     }
 
-    public static String getEventTypeString(int type) {
+    public static String getEventTypeString(short type) {
         switch(type) {
         case EVENT_MOUSE_CLICKED: return "EVENT_MOUSE_CLICKED";
         case EVENT_MOUSE_ENTERED: return "EVENT_MOUSE_ENTERED";
@@ -212,16 +380,26 @@ public class MouseEvent extends InputEvent
         default: return "unknown (" + type + ")";
         }
     }
-    private final int x[], y[], clickCount, button, wheelRotation;
+    private final int x[], y[];
+    // private final short tiltX[], tiltY[]; // TODO: A generic way for pointer axis information, see Android MotionEvent!
+    private final short clickCount, button;
+    private final float[] rotationXYZ;
+    private final float rotationScale;
     private final float pressure[];
-    private final int pointerids[];
-    
-    public static final int EVENT_MOUSE_CLICKED  = 200;
-    public static final int EVENT_MOUSE_ENTERED  = 201;
-    public static final int EVENT_MOUSE_EXITED   = 202;
-    public static final int EVENT_MOUSE_PRESSED  = 203;
-    public static final int EVENT_MOUSE_RELEASED = 204;
-    public static final int EVENT_MOUSE_MOVED    = 205;
-    public static final int EVENT_MOUSE_DRAGGED  = 206;
-    public static final int EVENT_MOUSE_WHEEL_MOVED = 207;
+    private final float maxPressure;
+    private final short pointerIDs[];
+    private final PointerType pointerTypes[];
+    
+    private static final float[] constMousePressure = new float[]{0f};
+    private static final short[] constMousePointerIDs = new short[]{0};
+    private static final PointerType[] constMousePointerTypes = new PointerType[] { PointerType.Mouse };
+    
+    public static final short EVENT_MOUSE_CLICKED  = 200;
+    public static final short EVENT_MOUSE_ENTERED  = 201;
+    public static final short EVENT_MOUSE_EXITED   = 202;
+    public static final short EVENT_MOUSE_PRESSED  = 203;
+    public static final short EVENT_MOUSE_RELEASED = 204;
+    public static final short EVENT_MOUSE_MOVED    = 205;
+    public static final short EVENT_MOUSE_DRAGGED  = 206;
+    public static final short EVENT_MOUSE_WHEEL_MOVED = 207;
 }
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseListener.java b/src/newt/classes/com/jogamp/newt/event/MouseListener.java
index 7668b75..ce67960 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseListener.java
@@ -34,6 +34,13 @@
 
 package com.jogamp.newt.event;
 
+import com.jogamp.newt.event.MouseEvent.PointerType;
+
+/**
+ * Listener for {@link MouseEvent}s.
+ * 
+ * @see MouseEvent
+ */
 public interface MouseListener extends NEWTEventListener
 {
  public void mouseClicked(MouseEvent e);
@@ -44,7 +51,13 @@ public interface MouseListener extends NEWTEventListener
  public void mouseMoved(MouseEvent e);
  public void mouseDragged(MouseEvent e);
  
- /** See {@link MouseEvent#getWheelRotation() } */
+ /**
+  * Traditional event name originally produced by a {@link PointerType#Mouse mouse} pointer type.
+  * <p>
+  * Triggered for any rotational pointer events, see
+  * {@link MouseEvent#getRotation()} and {@link MouseEvent#getRotationScale()}. 
+  * </p> 
+  */
  public void mouseWheelMoved(MouseEvent e);
 }
 
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
index 9d8d92f..c1bc791 100644
--- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
@@ -41,88 +41,34 @@ package com.jogamp.newt.event;
  *
  * Event type registry:<br>
  * <ul>
- *   <li> WindowEvent <code>100..10x</code></li>
- *   <li> MouseEvent  <code>200..20x</code></li>
- *   <li> KeyEvent    <code>300..30x</code></li>
+ *   <li> WindowEvent  <code>100..10x</code></li>
+ *   <li> MouseEvent   <code>200..20x</code></li>
+ *   <li> KeyEvent     <code>300..30x</code></li>
+ *   <li> MonitorEvent <code>600..60x</code></li>
  * </ul><br>
  */
 @SuppressWarnings("serial")
 public class NEWTEvent extends java.util.EventObject {
-    private final boolean isSystemEvent;
-    private final int eventType;
+    /** 
+     * See {@link #setConsumed(boolean)} for description.
+     */
+    public static final Object consumedTag = new Object();
+
+    private final short eventType;
     private final long when;
     private Object attachment;
 
     static final boolean DEBUG = false;
 
-    //  0: NEWTEvent.java
-    //  1:   InputEvent.java
-    //  2:       KeyEvent.java  
-    //  3:          com.jogamp.newt.Window
-    //  3:          com.jogamp.newt.event.awt.AWTNewtEventFactory
-    //  2:       MouseEvent.java  
-    //  3:          com.jogamp.newt.Window
-    //  3:          com.jogamp.newt.event.awt.AWTNewtEventFactory
-    //  1:   WindowEvent.java
-    //  2:       com.jogamp.newt.Window
-    //  2:       com.jogamp.newt.event.awt.AWTNewtEventFactory
-    //
-    // FIXME: verify the isSystemEvent evaluation
-    //
-    static final String WindowClazzName = "com.jogamp.newt.Window" ;
-    static final String AWTNewtEventFactoryClazzName = "com.jogamp.newt.event.awt.AWTNewtEventFactory" ;
-
-    /**
-    static final boolean evaluateIsSystemEvent(NEWTEvent event, Throwable t) {
-        StackTraceElement[] stack = t.getStackTrace();
-        if(stack.length==0 || null==stack[0]) {
-            return false;
-        }
-        if(DEBUG) {
-            for (int i = 0; i < stack.length && i<5; i++) {
-             System.err.println(i+": " + stack[i].getClassName()+ "." + stack[i].getMethodName());
-            }
-        }
-
-        String clazzName = null;
-
-        if( event instanceof com.jogamp.newt.event.WindowEvent ) {
-            if ( stack.length > 2 ) {
-                clazzName = stack[2].getClassName();
-            }
-        } else if( (event instanceof com.jogamp.newt.event.MouseEvent) ||
-                   (event instanceof com.jogamp.newt.event.KeyEvent) ) {
-            if ( stack.length > 3 ) {
-                clazzName = stack[3].getClassName();
-            }
-        }
-
-        boolean res = null!=clazzName && (
-                        clazzName.equals(WindowClazzName) || 
-                        clazzName.equals(AWTNewtEventFactoryClazzName) ) ;
-        if(DEBUG) {
-            System.err.println("system: "+res);
-        }
-        return res;
-    } */
-
-    protected NEWTEvent(int eventType, Object source, long when) {
+    protected NEWTEvent(short eventType, Object source, long when) {
         super(source);
-        // this.isSystemEvent = evaluateIsSystemEvent(this, new Throwable());
-        this.isSystemEvent = false; // FIXME: Need a more efficient way to determine system events
         this.eventType = eventType;
         this.when = when;
         this.attachment=null;
     }
 
-    /** Indicates whether this event was produced by the system or
-        generated by user code. */
-    public final boolean isSystemEvent() {
-        return isSystemEvent;
-    }
-
     /** Returns the event type of this event. */
-    public final int getEventType() {
+    public final short getEventType() {
         return eventType;
     }
 
@@ -140,7 +86,7 @@ public class NEWTEvent extends java.util.EventObject {
      * @param attachment User application specific object
      */
     public final void setAttachment(Object attachment) {
-        this.attachment=attachment;
+        this.attachment = attachment;
     }
 
     /** 
@@ -149,7 +95,41 @@ public class NEWTEvent extends java.util.EventObject {
     public final Object getAttachment() {
         return attachment;
     }
-
+    
+    /** 
+     * Returns <code>true</code> if this events has been {@link #setConsumed(boolean) consumed},
+     * otherwise <code>false</code>.
+     * @see #setConsumed(boolean)
+     */
+    public final boolean isConsumed() {
+        return consumedTag == attachment;
+    }
+    
+    /** 
+     * If <code>consumed</code> is <code>true</code>, this event is marked as consumed,
+     * ie. the event will not be propagated any further to potential <i>other</i> event listener.
+     * Otherwise the event will be propagated to other event listener, the default.
+     * <p>
+     * The event is marked as being consumed while {@link #setAttachment(Object) attaching}
+     * the {@link #consumedTag}.
+     * </p>
+     * <p>
+     * Events with platform specific actions will be supressed if marked as consumed.
+     * Examples are:
+     * <ul>
+     *   <li>{@link KeyEvent#VK_ESCAPE} on Android's BACK button w/ Activity::finish()</li>
+     *   <li>{@link KeyEvent#VK_HOME} on Android's HOME button w/ Intend.ACTION_MAIN[Intend.CATEGORY_HOME]</li>
+     * </ul>
+     * </p>
+     */
+    public final void setConsumed(boolean consumed) {
+        if( consumed ) {
+            setAttachment( consumedTag );
+        } else if( consumedTag == attachment ) {
+            setAttachment( null );
+        }
+    }
+    
     public String toString() {
         return toString(null).toString();
     }
@@ -158,10 +138,10 @@ public class NEWTEvent extends java.util.EventObject {
         if(null == sb) {
             sb = new StringBuilder();
         }
-        return sb.append("NEWTEvent[sys:").append(isSystemEvent()).append(", source:").append(getSource().getClass().getName()).append(", when:").append(getWhen()).append(" d ").append((System.currentTimeMillis()-getWhen())).append("ms]");
+        return sb.append("NEWTEvent[source:").append(getSource().getClass().getName()).append(", consumed ").append(isConsumed()).append(", when:").append(getWhen()).append(" d ").append((System.currentTimeMillis()-getWhen())).append("ms]");
     }
 
-    static String toHexString(int hex) {
-        return "0x" + Integer.toHexString(hex);
+    public static String toHexString(short hex) {
+        return "0x" + Integer.toHexString( (int)hex & 0x0000FFFF );
     }
 }
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java b/src/newt/classes/com/jogamp/newt/event/OutputEvent.java
similarity index 75%
copy from src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
copy to src/newt/classes/com/jogamp/newt/event/OutputEvent.java
index afb3daf..86fa958 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
+++ b/src/newt/classes/com/jogamp/newt/event/OutputEvent.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -26,20 +26,26 @@
  * or implied, of JogAmp Community.
  */
 
-package jogamp.nativewindow.windows;
+package com.jogamp.newt.event;
 
-public class RegisteredClass {
-    long hInstance;
-    String className;
+ at SuppressWarnings("serial")
+public abstract class OutputEvent extends NEWTEvent
+{
+ protected OutputEvent(short eventType, Object source, long when) {
+    super(eventType, source, when);
+ }
 
-    RegisteredClass(long hInst, String name) {
-        hInstance = hInst;
-        className = name;
-    }
-
-    public final long getHandle() { return hInstance; }
-    public final String getName() { return className; }
-
-    @Override
-    public final String toString() { return "RegisteredClass[handle 0x"+Long.toHexString(hInstance)+", "+className+"]"; }
+ /**
+ public String toString() {
+     return toString(null).toString();
+ }
+ 
+ public StringBuilder toString(StringBuilder sb) {
+     if(null == sb) {
+         sb = new StringBuilder();
+     }
+     sb.append("OutputEvent[");
+     super.toString(sb).append("]");
+     return sb;
+ } */
 }
diff --git a/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
index 98ba5a2..629dc50 100644
--- a/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
@@ -48,9 +48,5 @@ public class TraceKeyAdapter implements KeyListener {
         System.err.println(e);
         if(null!=downstream) { downstream.keyReleased(e); }
     }
-    public void keyTyped(KeyEvent e) {
-        System.err.println(e);
-        if(null!=downstream) { downstream.keyTyped(e); }
-    }
 }
 
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowEvent.java b/src/newt/classes/com/jogamp/newt/event/WindowEvent.java
index 163b514..24b3b38 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowEvent.java
@@ -41,19 +41,19 @@ package com.jogamp.newt.event;
  */
 @SuppressWarnings("serial")
 public class WindowEvent extends NEWTEvent {
-    public static final int EVENT_WINDOW_RESIZED = 100;
-    public static final int EVENT_WINDOW_MOVED   = 101; 
-    public static final int EVENT_WINDOW_DESTROY_NOTIFY = 102;
-    public static final int EVENT_WINDOW_GAINED_FOCUS = 103;
-    public static final int EVENT_WINDOW_LOST_FOCUS = 104;
-    public static final int EVENT_WINDOW_REPAINT = 105;
-    public static final int EVENT_WINDOW_DESTROYED = 106;
+    public static final short EVENT_WINDOW_RESIZED = 100;
+    public static final short EVENT_WINDOW_MOVED   = 101; 
+    public static final short EVENT_WINDOW_DESTROY_NOTIFY = 102;
+    public static final short EVENT_WINDOW_GAINED_FOCUS = 103;
+    public static final short EVENT_WINDOW_LOST_FOCUS = 104;
+    public static final short EVENT_WINDOW_REPAINT = 105;
+    public static final short EVENT_WINDOW_DESTROYED = 106;
 
-    public WindowEvent(int eventType, Object source, long when) {
+    public WindowEvent(short eventType, Object source, long when) {
         super(eventType, source, when);
     }
 
-    public static String getEventTypeString(int type) {
+    public static String getEventTypeString(short type) {
         switch(type) {
             case EVENT_WINDOW_RESIZED: return "WINDOW_RESIZED";
             case EVENT_WINDOW_MOVED: return "WINDOW_MOVED";
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowListener.java b/src/newt/classes/com/jogamp/newt/event/WindowListener.java
index e841a06..dde1825 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowListener.java
@@ -34,6 +34,9 @@
 
 package com.jogamp.newt.event;
 
+import javax.media.nativewindow.WindowClosingProtocol;
+
+/** NEWT {@link WindowEvent} listener. */
 public interface WindowListener extends NEWTEventListener {
     /** Window is resized, your application shall respect the new window dimension. A repaint is recommended. */
     public void windowResized(WindowEvent e);
@@ -41,10 +44,19 @@ public interface WindowListener extends NEWTEventListener {
     /** Window has been moved. */
     public void windowMoved(WindowEvent e);
 
-    /** Window will be destroyed. Release of resources is recommended. */
+    /** 
+     * Window destruction has been requested.
+     * <p>
+     * Depending on the {@link WindowClosingProtocol#getDefaultCloseOperation() default close operation},
+     * the window maybe destroyed or not.
+     * </p>
+     * In case the window will be destroyed (see above), release of resources is recommended. 
+     **/
     public void windowDestroyNotify(WindowEvent e);
 
-    /** Window has been destroyed.*/
+    /** 
+     * Window has been destroyed.
+     */
     public void windowDestroyed(WindowEvent e);
 
     /** Window gained focus. */
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java b/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
index e3f0373..a0f6e2c 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
@@ -34,7 +34,7 @@ import javax.media.nativewindow.util.Rectangle;
 public class WindowUpdateEvent extends WindowEvent {
     final Rectangle bounds;
 
-    public WindowUpdateEvent(int eventType, Object source, long when, Rectangle bounds)
+    public WindowUpdateEvent(short eventType, Object source, long when, Rectangle bounds)
     {
         super(eventType, source, when);
         this.bounds = bounds;
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java
index 8991203..6de2eee 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java
@@ -181,8 +181,13 @@ public abstract class AWTAdapter implements java.util.EventListener
     /** @see #addTo(java.awt.Component) */
     public abstract AWTAdapter removeFrom(java.awt.Component awtComponent);
 
+    /**
+     * Enqueues the event to the {@link #getNewtWindow()} is not null.
+     */
     void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
-        newtWindow.enqueueEvent(wait, event);
+        if( null != newtWindow ) {
+            newtWindow.enqueueEvent(wait, event);
+        }
     }
 }
 
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
index 7b0f6ba..bef2e5d 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
@@ -30,6 +30,11 @@ package com.jogamp.newt.event.awt;
 
 import jogamp.newt.awt.event.AWTNewtEventFactory;
 
+/**
+ * AWT: 
+ *   printable:     PRESSED (t0), TYPED (t0), RELEASED (t1)
+ *   non-printable: PRESSED (t0), RELEASED (t1)
+ */
 public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListener
 {
     public AWTKeyAdapter(com.jogamp.newt.event.KeyListener newtListener) {
@@ -54,8 +59,9 @@ public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListe
         return this;
     }
 
+    @Override
     public void keyPressed(java.awt.event.KeyEvent e) {
-        com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow);
+        final com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED, e, newtWindow);
         if(null!=newtListener) {
             ((com.jogamp.newt.event.KeyListener)newtListener).keyPressed(event);
         } else {
@@ -63,8 +69,9 @@ public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListe
         }
     }
 
+    @Override
     public void keyReleased(java.awt.event.KeyEvent e) {
-        com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow);
+        final com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED, e, newtWindow);
         if(null!=newtListener) {
             ((com.jogamp.newt.event.KeyListener)newtListener).keyReleased(event);
         } else {
@@ -72,13 +79,8 @@ public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListe
         }
     }
 
+    @Override
     public void keyTyped(java.awt.event.KeyEvent e) {
-        com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow);
-        if(null!=newtListener) {
-            ((com.jogamp.newt.event.KeyListener)newtListener).keyTyped(event);
-        } else {
-            enqueueEvent(false, event);
-        }
     }
 }
 
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java
index 2d63ca4..e91bb2f 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java
@@ -66,13 +66,18 @@ public class AWTWindowAdapter
         return this;        
     }
     
-    public AWTAdapter removeFrom(java.awt.Component awtComponent) {
-        awtComponent.removeFocusListener(this);
-        awtComponent.removeComponentListener(this);
+    public AWTAdapter removeWindowClosingFrom(java.awt.Component awtComponent) {
         java.awt.Window win = getWindow(awtComponent);
         if( null != win && null != windowClosingListener ) {
             win.removeWindowListener(windowClosingListener);
         }
+        return this;        
+    }
+    
+    public AWTAdapter removeFrom(java.awt.Component awtComponent) {
+        awtComponent.removeFocusListener(this);
+        awtComponent.removeComponentListener(this);
+        removeWindowClosingFrom(awtComponent);
         if(awtComponent instanceof java.awt.Window) {
             ((java.awt.Window)awtComponent).removeWindowListener(this);
         }
@@ -220,9 +225,16 @@ public class AWTWindowAdapter
                 enqueueEvent(true, event);
             }
         }
+        public void windowClosed(java.awt.event.WindowEvent e) { 
+            com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+            if(null!=newtListener) {
+                ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyed(event);
+            } else {
+                enqueueEvent(true, event);
+            }
+        }
 
         public void windowActivated(java.awt.event.WindowEvent e) { }
-        public void windowClosed(java.awt.event.WindowEvent e) { }
         public void windowDeactivated(java.awt.event.WindowEvent e) { }
         public void windowDeiconified(java.awt.event.WindowEvent e) { }
         public void windowIconified(java.awt.event.WindowEvent e) { }
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index a89ccae..25249ce 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -34,13 +34,16 @@
 
 package com.jogamp.newt.opengl;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.List;
+
 import javax.media.nativewindow.AbstractGraphicsConfiguration;
 import javax.media.nativewindow.CapabilitiesChooser;
 import javax.media.nativewindow.CapabilitiesImmutable;
 import javax.media.nativewindow.NativeSurface;
 import javax.media.nativewindow.NativeWindow;
 import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.nativewindow.SurfaceUpdatedListener;
 import javax.media.nativewindow.util.InsetsImmutable;
 import javax.media.nativewindow.util.Point;
@@ -65,6 +68,7 @@ import jogamp.opengl.GLDrawableImpl;
 import com.jogamp.common.GlueGenVersion;
 import com.jogamp.common.util.VersionUtil;
 import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.newt.MonitorDevice;
 import com.jogamp.newt.NewtFactory;
 import com.jogamp.newt.Screen;
 import com.jogamp.newt.Window;
@@ -77,11 +81,16 @@ import com.jogamp.newt.event.WindowEvent;
 import com.jogamp.newt.event.WindowListener;
 import com.jogamp.newt.event.WindowUpdateEvent;
 import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.GLStateKeeper;
 
 /**
  * An implementation of {@link GLAutoDrawable} and {@link Window} interface,
  * using a delegated {@link Window} instance, which may be an aggregation (lifecycle: created and destroyed).
  * <P>
+ * This implementation supports {@link GLStateKeeper GL state preservation},
+ * hence {@link #isGLStatePreservationSupported()} returns <code>true</code>.
+ * </P>
+ * <P>
  * This implementation does not make the OpenGL context current<br>
  * before calling the various input EventListener callbacks, ie {@link com.jogamp.newt.event.MouseListener} etc.<br>
  * This design decision is made in favor of a more performant and simplified
@@ -100,7 +109,10 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     protected GLWindow(Window window) {
         super(null, null, false /* always handle device lifecycle ourselves */);
         this.window = (WindowImpl) window;
-        this.window.setHandleDestroyNotify(false);
+        this.window.setWindowDestroyNotifyAction( new Runnable() {
+            public void run() {
+                defaultWindowDestroyNotifyOp();
+            } } );
         window.addWindowListener(new WindowAdapter() {
                 @Override
                 public void windowRepaint(WindowUpdateEvent e) {
@@ -112,10 +124,6 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
                     defaultWindowResizedOp(getWidth(), getHeight());
                 }
 
-                @Override
-                public void windowDestroyNotify(WindowEvent e) {
-                    defaultWindowDestroyNotifyOp();
-                }
             });
         this.window.setLifecycleHook(new GLLifecycleHook());
     }
@@ -227,6 +235,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     }
 
     @Override
+    public final MonitorDevice getMainMonitor() {
+        return window.getMainMonitor();
+    }
+
+    @Override
     public final void setTitle(String title) {
         window.setTitle(title);
     }
@@ -343,6 +356,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     public final boolean setFullscreen(boolean fullscreen) {
         return window.setFullscreen(fullscreen);
     }
+    
+    @Override
+    public boolean setFullscreen(List<MonitorDevice> monitors) {
+        return window.setFullscreen(monitors);
+    }
 
     @Override
     public final boolean isFullscreen() {
@@ -390,6 +408,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     }
 
     @Override
+    public void setWindowDestroyNotifyAction(Runnable r) {
+        window.setWindowDestroyNotifyAction(r);
+    }
+    
+    @Override
     public final void setVisible(boolean visible) {
         window.setVisible(visible);
     }
@@ -417,6 +440,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     protected class GLLifecycleHook implements WindowImpl.LifecycleHook {
 
         @Override
+        public void preserveGLStateAtDestroy(boolean value) {
+            GLWindow.this.preserveGLStateAtDestroy(value);
+        }
+        
+        @Override
         public synchronized void destroyActionPreLock() {
             // nop
         }
@@ -429,7 +457,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
                 //Exception e1 = new Exception(msg);
                 //e1.printStackTrace();
             }
-
+                    
             destroyImplInLock();
 
             if(Window.DEBUG_IMPLEMENTATION) {
@@ -443,6 +471,10 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
                 System.err.println("GLWindow.resetCounter() "+WindowImpl.getThreadName());
             }
             GLWindow.this.resetFPSCounter();
+            final GLAnimatorControl animator = GLWindow.this.getAnimator();
+            if( null != animator ) {
+                animator.resetFPSCounter();
+            }
         }
 
         @Override
@@ -454,27 +486,27 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
             } else {
                 t0 = 0;
             }
-
-            /* if (nativeWindowCreated && null != context) {
-                throw new GLException("InternalError: Native Windows has been just created, but context wasn't destroyed (is not null)");
-            } */
-            if (null == context && visible && 0 != window.getWindowHandle() && 0<getWidth()*getHeight()) {
-                NativeWindow nw;
-                if (window.getWrappedWindow() != null) {
-                    nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getPrivateGraphicsConfiguration());
-                } else {
-                    nw = window;
+            
+            if (null == drawable && visible && 0 != window.getWindowHandle() && 0<getWidth()*getHeight()) {
+                if( ( null != context ) ) {
+                    throw new InternalError("GLWindow.LifecycleHook.setVisiblePost: "+WindowImpl.getThreadName()+" - Null drawable, but valid context - "+GLWindow.this);
                 }
-                GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) nw.getGraphicsConfiguration().getChosenCapabilities();
+                final NativeSurface ns;
+                {
+                    final NativeSurface wrapped_ns = window.getWrappedSurface();
+                    ns = null != wrapped_ns ? wrapped_ns : window;
+                }
+                final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) ns.getGraphicsConfiguration().getChosenCapabilities();
                 if(null==factory) {
                     factory = GLDrawableFactory.getFactory(glCaps.getGLProfile());
                 }
-                if(null==drawable) {
-                    drawable = (GLDrawableImpl) factory.createGLDrawable(nw);
-                }
+                drawable = (GLDrawableImpl) factory.createGLDrawable(ns);
                 drawable.setRealized(true);
-                context = (GLContextImpl) drawable.createContext(sharedContext);
-                context.setContextCreationFlags(additionalCtxCreationFlags);
+                
+                if( !GLWindow.this.pushGLEventListenerState() ) {
+                    context = (GLContextImpl) drawable.createContext(sharedContext);
+                    context.setContextCreationFlags(additionalCtxCreationFlags);
+                }
             }
             if(Window.DEBUG_IMPLEMENTATION) {
                 System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", fin: dt "+ (System.nanoTime()-t0)/1e6 +"ms");
@@ -499,6 +531,24 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
                 savedAnimator.resume();
             }
         }
+        
+        @SuppressWarnings("deprecation")
+        @Override
+        public void shutdownRenderingAction() {
+            final GLAnimatorControl anim = GLWindow.this.getAnimator();
+            if ( null != anim && anim.isAnimating() ) {
+                AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        final Thread animThread = anim.getThread();
+                        if( null != animThread ) {
+                            try {
+                                animThread.stop();
+                            } catch(Throwable t) { }
+                        }
+                        return null;
+                    } } );
+            }
+        }
     }
 
     //----------------------------------------------------------------------
@@ -506,7 +556,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     //
 
     private GLContext sharedContext = null;
-
+    
     @Override
     protected final RecursiveLock getLock() {
         return window.getLock();
@@ -548,11 +598,20 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
         } finally {
             lock.unlock();
         }
-        if( !done && 0<getWidth()*getHeight() ) {
+        if( !done && ( 0 < getWidth() && 0 < getHeight() ) ) {
             // retry drawable and context creation, will itself issue resize -> display
             setVisible(true);
         }
     }
+    
+    /**
+     * {@inheritDoc}
+     * <p>
+     * GLWindow supports GL state preservation, hence returns <code>true</code>.
+     * </p>
+     */
+    @Override
+    public final boolean isGLStatePreservationSupported() { return true; }
 
     //----------------------------------------------------------------------
     // GLDrawable methods
@@ -565,10 +624,6 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     }
 
     @Override
-    public final void setRealized(boolean realized) {
-    }
-
-    @Override
     public final void swapBuffers() throws GLException {
          defaultSwapBuffers();
     }
diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
index 5252258..dbe7c0d 100644
--- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
+++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
@@ -26,7 +26,6 @@
  * or implied, of JogAmp Community.
  */
 
-
 package com.jogamp.newt.swt;
 
 import javax.media.nativewindow.AbstractGraphicsConfiguration;
@@ -44,18 +43,18 @@ import javax.media.nativewindow.WindowClosingProtocol;
 import javax.media.nativewindow.util.Insets;
 import javax.media.nativewindow.util.InsetsImmutable;
 import javax.media.nativewindow.util.Point;
+import javax.media.opengl.GLCapabilities;
 
 import jogamp.nativewindow.macosx.OSXUtil;
 import jogamp.newt.Debug;
+import jogamp.newt.swt.SWTEDTUtil;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ControlAdapter;
-import org.eclipse.swt.events.ControlEvent;
-import org.eclipse.swt.events.PaintEvent;
-import org.eclipse.swt.events.PaintListener;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.widgets.Canvas;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
 
 import com.jogamp.nativewindow.swt.SWTAccessor;
 import com.jogamp.newt.Display;
@@ -65,6 +64,9 @@ import com.jogamp.newt.util.EDTUtil;
 
 /**
  * SWT {@link Canvas} containing a NEWT {@link Window} using native parenting.
+ * <p>
+ * Implementation allows use of custom {@link GLCapabilities}.
+ * </p>
  */
 public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
     private static final boolean DEBUG = Debug.debug("Window");
@@ -77,6 +79,8 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
 
     private volatile SWTNativeWindow nativeWindow;
     private volatile Window newtChild = null;
+    private volatile boolean newtChildReady = false; // ready if SWTEDTUtil is set and newtChild parented
+    private volatile boolean postSetSize = false; // pending resize
 
     /** 
      * Creates an instance using {@link #NewtCanvasSWT(Composite, int, Window)} 
@@ -122,45 +126,51 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
         clientArea = getClientArea();
 
         final AbstractGraphicsDevice device = SWTAccessor.getDevice(this);
-        screen = SWTAccessor.getScreen(device, 0);
+        screen = SWTAccessor.getScreen(device, -1 /* default */);
         nativeWindow = null;
         
         if(null != child) {
             setNEWTChild(child);
         }
-        
-        /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
-        /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
-        addPaintListener(new PaintListener() {
+
+        final Listener listener = new Listener () {
             @Override
-            public void paintControl(final PaintEvent arg0) {
-                if( null != nativeWindow || validateNative() ) {
-                    if( null !=newtChild ) {
-                        newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
+            public void handleEvent (Event event) {
+                switch (event.type) {
+                case SWT.Paint:
+                    if( null != nativeWindow || validateNative() ) {
+                        if( newtChildReady ) {
+                            if( postSetSize ) {
+                                newtChild.setSize(clientArea.width, clientArea.height);
+                                postSetSize = false;
+                            }
+                            newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
+                        }
                     }
+                    break;
+                case SWT.Resize:
+                    updateSizeCheck();
+                    break;
+                case SWT.Dispose:
+                    NewtCanvasSWT.this.dispose();
+                    break;
                 }
             }
-        });
-
-        addControlListener(new ControlAdapter() {
-            @Override
-            public void controlResized(final ControlEvent arg0) {
-                updateSizeCheck();
-            }
-        });
+        };
+        addListener (SWT.Resize, listener);
+        addListener (SWT.Paint, listener);
+        addListener (SWT.Dispose, listener);
     }
     
     /** assumes nativeWindow == null ! */
     protected final boolean validateNative() {
-        if( isDisposed() ) {
-            return false;
-        }
         updateSizeCheck();
         final Rectangle nClientArea = clientArea;
         if(0 >= nClientArea.width || 0 >= nClientArea.height) {        
             return false;
         }
-        
+        screen.getDevice().open();
+
         /* Native handle for the control, used to associate with GLContext */
         final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
         final int visualID = SWTAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle);
@@ -196,12 +206,18 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
              ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
            ) {
             clientArea = nClientArea; // write back new value
-            if( null != newtChild ) {
+            if(DEBUG) {
+                final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0;
+                System.err.println("NewtCanvasSWT.sizeChanged: ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(nsh));
+            }
+            if( newtChildReady ) {
                 newtChild.setSize(clientArea.width, clientArea.height);
+            } else {
+                postSetSize = true;
             }
         }
     }
-
+    
     @Override
     public void update() {
         // don't paint background etc .. nop avoids flickering
@@ -230,6 +246,7 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
             newtChild.destroy();
             newtChild = null;
         }
+        screen.getDevice().close();
         nativeWindow = null;
         super.dispose();            
     }
@@ -238,11 +255,11 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
     public NativeWindow getNativeWindow() { return nativeWindow; }
     
     public WindowClosingMode getDefaultCloseOperation() {
-        return newtChildCloseOp; // FIXME
+        return newtChildCloseOp; // TODO: implement ?!
     }
 
     public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
-        return newtChildCloseOp = op; // FIXME
+        return newtChildCloseOp = op; // TODO: implement ?!
     }
 
 
@@ -299,7 +316,7 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
     }
 
     /* package */ void configureNewtChild(boolean attach) {
-
+        newtChildReady = attach;
         if( null != newtChild ) {
             newtChild.setKeyboardFocusHandler(null);
             if(attach) {            
@@ -324,23 +341,21 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
             updateSizeCheck();
             final int w = clientArea.width;
             final int h = clientArea.height;
-
+            
             // set SWT EDT and start it
             {
                 final Display newtDisplay = newtChild.getScreen().getDisplay();
-                final EDTUtil edt = new SWTEDTUtil(newtDisplay, getDisplay());
-                newtDisplay.setEDTUtil(edt);
-                edt.invoke(true, new Runnable() { public void run() { } } ); // start EDT
+                newtDisplay.setEDTUtil( new SWTEDTUtil(newtDisplay, getDisplay()) );
             }
             
-            newtChild.setSize(w, h);
+            newtChild.setSize(w, h);            
             newtChild.reparentWindow(nativeWindow);
             newtChild.setVisible(true);
-            configureNewtChild(true);
+            configureNewtChild(true);            
             newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
-
+            
             // force this SWT Canvas to be focus-able, 
-            // since this it is completely covered by the newtChild (z-order).
+            // since it is completely covered by the newtChild (z-order).
             setEnabled(true);
         } else {
             configureNewtChild(false);
@@ -353,7 +368,7 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
     }
 
     private final void requestFocusNEWTChild() {
-        if( null != newtChild ) {
+        if( newtChildReady ) {
             newtChild.setFocusAction(null);
             newtChild.requestFocus();
         }
diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
index 7e19d9d..0df8156 100644
--- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
+++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
@@ -70,7 +70,7 @@ public interface EDTUtil {
      * is expected.
      *
      * @see #invoke(boolean, java.lang.Runnable)
-     * @see #invokeStop(java.lang.Runnable)
+     * @see #invokeStop(boolean, java.lang.Runnable)
      */
     public void reset();
 
@@ -113,7 +113,13 @@ public interface EDTUtil {
 
     /** 
      * Append the final task to the EDT task queue,
-     * signals EDT to stop and wait until stopped.<br>
+     * signals EDT to stop.
+     * <p>
+     * If <code>wait</code> is <code>true</code> methods
+     * blocks until EDT is stopped.
+     * </p>
+     * <p>
+     * <code>task</code> maybe <code>null</code><br/>
      * Due to the nature of this method:
      * <ul>
      *   <li>All previous queued tasks will be finished.</li>
@@ -121,11 +127,12 @@ public interface EDTUtil {
      *   <li>Can be issued from within EDT, ie from within an enqueued task.</li>
      *   <li>{@link #reset()} may follow immediately, ie creating a new EDT</li>
      * </ul>
+     * </p>
      */
-    public void invokeStop(Runnable finalTask);
+    public void invokeStop(boolean wait, Runnable finalTask);
 
     /** 
-     * Shall start the thread if not running.<br>
+     * Shall start the thread if not running, <code>task</code> maybe null for this purpose.<br>
      * Append task to the EDT task queue.<br>
      * Wait until execution is finished if <code>wait == true</code>.<br>
      * Can be issued from within EDT, ie from within an enqueued task.<br>
@@ -142,7 +149,7 @@ public interface EDTUtil {
 
     /**
      * Wait until EDT task is stopped.<br>
-     * No <code>stop</code> action is performed, {@link #invokeStop(java.lang.Runnable)} should be used before.
+     * No <code>stop</code> action is performed, {@link #invokeStop(boolean, java.lang.Runnable)} should be used before.
      */
     public void waitUntilStopped();
 }
diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java b/src/newt/classes/com/jogamp/newt/util/MonitorMode.java
deleted file mode 100644
index 8104f20..0000000
--- a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java
+++ /dev/null
@@ -1,102 +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.newt.util;
-
-import javax.media.nativewindow.util.*;
-
-/** Immutable MonitorMode Class, consisting of it's read only components:<br>
- * <ul>
- *  <li>{@link javax.media.nativewindow.util.SurfaceSize} surface memory size</li>
- *  <li>{@link javax.media.nativewindow.util.DimensionImmutable} size in [mm]</li>
- *  <li><code>refresh rate</code></li>
- * </ul>
- */
-public class MonitorMode {
-    SurfaceSize surfaceSize;
-    DimensionImmutable screenSizeMM; // in [mm]
-    int refreshRate;
-
-    public MonitorMode(SurfaceSize surfaceSize, DimensionImmutable screenSizeMM, int refreshRate) {
-        // Don't validate screenSizeMM and refreshRate, since they may not be supported by the OS 
-        if(null==surfaceSize) {
-            throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")");
-        }
-        this.surfaceSize=surfaceSize;
-        this.screenSizeMM=screenSizeMM;
-        this.refreshRate=refreshRate;
-    }
-
-    public final SurfaceSize getSurfaceSize() {
-        return surfaceSize;
-    }
-
-    public final DimensionImmutable getScreenSizeMM() {
-        return screenSizeMM;
-    }
-
-    public final int getRefreshRate() {
-        return refreshRate;
-    }
-
-    public final String toString() {
-        return new String("[ "+surfaceSize+" x "+refreshRate+" Hz, "+screenSizeMM+" mm ]");
-    }
-
-    /**
-     * Checks whether two size objects are equal. Two instances
-     * of <code>MonitorMode</code> are equal if the three components
-     * <code>surfaceSize</code> and <code>refreshRate</code>
-     * are equal. <code>screenSizeMM</code> is kept out intentional to reduce the requirements for finding the current mode.
-     * @return  <code>true</code> if the two dimensions are equal;
-     *          otherwise <code>false</code>.
-     */
-    public final boolean equals(Object obj) {
-        if (this == obj) { return true; }
-        if (obj instanceof MonitorMode) {
-            MonitorMode p = (MonitorMode)obj;
-            return getSurfaceSize().equals(p.getSurfaceSize()) &&
-                   /* getScreenSizeMM().equals(p.getScreenSizeMM()) && */
-                   getRefreshRate() == p.getRefreshRate() ;
-        }
-        return false;
-    }
-
-    /**
-     * returns a hash code over <code>surfaceSize</code> and <code>refreshRate</code>.
-     * <code>screenSizeMM</code> is kept out intentional to reduce the requirements for finding the current mode.
-     */
-    public final int hashCode() {
-        // 31 * x == (x << 5) - x
-        int hash = 31 + getSurfaceSize().hashCode();
-        /* hash = ((hash << 5) - hash) + getScreenSizeMM().hashCode(); */
-        hash = ((hash << 5) - hash) + getRefreshRate();
-        return hash;
-    }
-}
-
diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java b/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java
new file mode 100644
index 0000000..16ffe75
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.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.newt.util;
+
+import com.jogamp.newt.MonitorMode;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.SurfaceSize;
+
+/**
+ * Convenient {@link com.jogamp.newt.MonitorMode} utility methods,
+ * filters etc.
+ */
+public class MonitorModeUtil {
+    
+    public static int getIndex(List<MonitorMode> monitorModes, MonitorMode search) {
+        return monitorModes.indexOf(search);
+    }
+
+    public static int getIndexByHashCode(List<MonitorMode> monitorModes, MonitorMode search) {
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            for (int i=0; i<monitorModes.size(); i++) {
+                if ( search.hashCode() == monitorModes.get(i).hashCode() ) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    public static MonitorMode getByNativeSizeRateIdAndRotation(List<MonitorMode> monitorModes, MonitorMode.SizeAndRRate sizeAndRate, int modeId, int rotation) {
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            for (int i=0; i<monitorModes.size(); i++) {
+                final MonitorMode mode = monitorModes.get(i);
+                if( mode.getSizeAndRRate().equals(sizeAndRate) && mode.getId() == modeId && mode.getRotation() == rotation ) {
+                    return mode;
+                }
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * 
+     * @param monitorModes
+     * @param surfaceSize
+     * @return modes with exact {@link SurfaceSize}. May return zero sized list for non.
+     */
+    public static List<MonitorMode> filterBySurfaceSize(List<MonitorMode> monitorModes, SurfaceSize surfaceSize) {
+        final List<MonitorMode> out = new ArrayList<MonitorMode>();
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+                final MonitorMode mode = monitorModes.get(i);
+                if(mode.getSurfaceSize().equals(surfaceSize)) {
+                    out.add(mode);
+                }
+            }
+        }
+        return out;
+    }
+
+    /**
+     * 
+     * @param monitorModes
+     * @param rotation
+     * @return modes with exact rotation. May return zero sized list for non.
+     */
+    public static List<MonitorMode> filterByRotation(List<MonitorMode> monitorModes, int rotation) {
+        final List<MonitorMode> out = new ArrayList<MonitorMode>();
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+                final MonitorMode mode = monitorModes.get(i);
+                if(mode.getRotation() == rotation) {
+                    out.add(mode);
+                }
+            }
+        }
+        return out;
+    }
+
+    /**
+     * 
+     * @param monitorModes
+     * @param bitsPerPixel
+     * @return modes with exact bpp. May return zero sized list for non.
+     */
+    public static List<MonitorMode> filterByBpp(List<MonitorMode> monitorModes, int bitsPerPixel) {
+        final List<MonitorMode> out = new ArrayList<MonitorMode>();
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+                final MonitorMode mode = monitorModes.get(i);
+                if(mode.getSurfaceSize().getBitsPerPixel() == bitsPerPixel) {
+                    out.add(mode);
+                }
+            }
+        }
+        return out;
+    }
+
+    /**
+     * 
+     * @param monitorModes
+     * @param flags
+     * @return modes with exact flags. May return zero sized list for non.
+     */
+    public static List<MonitorMode> filterByFlags(List<MonitorMode> monitorModes, int flags) {
+        final List<MonitorMode> out = new ArrayList<MonitorMode>();
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+                final MonitorMode mode = monitorModes.get(i);
+                if(mode.getFlags() == flags) {
+                    out.add(mode);
+                }
+            }
+        }
+        return out;
+    }
+
+    /**
+     * @param monitorModes
+     * @param resolution
+     * @return modes with nearest resolution, or matching ones. May return zero sized list for non.
+     */
+    public static List<MonitorMode> filterByResolution(List<MonitorMode> monitorModes, DimensionImmutable resolution) {
+        final List<MonitorMode> out = new ArrayList<MonitorMode>();
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            final int resolution_sq = resolution.getHeight()*resolution.getWidth();
+            int mode_dsq=Integer.MAX_VALUE, mode_dsq_idx=0;
+    
+            for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+                final MonitorMode mode = monitorModes.get(i);
+                final DimensionImmutable res = mode.getSurfaceSize().getResolution();
+                final int dsq = Math.abs(resolution_sq - res.getHeight()*res.getWidth());
+                if(dsq<mode_dsq) {
+                    mode_dsq = dsq;
+                    mode_dsq_idx = i;
+                }
+                if(res.equals(resolution)) {
+                    out.add(mode);
+                }
+            }
+            if(out.size() == 0 && 0 <= mode_dsq_idx ) {
+                // nearest ..
+                out.add(monitorModes.get(mode_dsq_idx));
+            }
+        }
+        return out;
+    }
+
+    /**
+     *
+     * @param monitorModes
+     * @param refreshRate
+     * @return modes with nearest refreshRate, or matching ones. May return zero sized list for non.
+     */
+    public static List<MonitorMode> filterByRate(List<MonitorMode> monitorModes, float refreshRate) {
+        final List<MonitorMode> out = new ArrayList<MonitorMode>();
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            float mode_dr = Float.MAX_VALUE;
+            int mode_dr_idx = -1;
+            for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+                final MonitorMode mode = monitorModes.get(i);
+                float dr = Math.abs(refreshRate - mode.getRefreshRate());
+                if(dr<mode_dr) {
+                    mode_dr = dr;
+                    mode_dr_idx = i;
+                }
+                if(0 == dr) {
+                    out.add(mode);
+                }
+            }
+            if(out.size() == 0 && 0 <= mode_dr_idx ) {
+                // nearest ..
+                out.add(monitorModes.get(mode_dr_idx));
+            }
+        }
+        return out;
+    }
+
+    /**
+     * @param monitorModes
+     * @return modes with highest available bpp (color depth). May return zero sized list for non.
+     */
+    public static List<MonitorMode> getHighestAvailableBpp(List<MonitorMode> monitorModes) {
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            int highest = -1;
+            for (int i=0; null!=monitorModes && i < monitorModes.size(); i++) {
+                final MonitorMode mode = monitorModes.get(i);
+                final int bpp  = mode.getSurfaceSize().getBitsPerPixel();
+                if (bpp > highest) {
+                    highest = bpp;
+                }
+            }
+            return filterByBpp(monitorModes, highest);
+        }
+        return new ArrayList<MonitorMode>();
+    }
+
+    /**
+     * 
+     * @param monitorModes
+     * @return modes with highest available refresh rate. May return zero sized list for non.
+     */
+    public static List<MonitorMode> getHighestAvailableRate(List<MonitorMode> monitorModes) {
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            float highest = -1;
+            for (int i=0; null!=monitorModes && i < monitorModes.size(); i++) {
+                final MonitorMode mode = monitorModes.get(i);
+                final float rate = mode.getRefreshRate();
+                if (rate > highest) {
+                    highest = rate;
+                }
+            }
+            return filterByRate(monitorModes, highest);
+        }
+        return new ArrayList<MonitorMode>();
+    }
+
+}
diff --git a/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java b/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java
deleted file mode 100644
index 93797c5..0000000
--- a/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java
+++ /dev/null
@@ -1,341 +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.newt.util;
-
-import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.newt.ScreenMode;
-import java.util.ArrayList;
-import java.util.List;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.SurfaceSize;
-
-/**
- * Convenient {@link com.jogamp.newt.ScreenMode} utility methods,
- * filters etc.
- */
-public class ScreenModeUtil {
-    /** WARNING: must be synchronized with ScreenMode.h, native implementation
-     * 2: width and height
-     */
-    public static final int NUM_RESOLUTION_PROPERTIES   = 2;
-
-    /** WARNING: must be synchronized with ScreenMode.h, native implementation
-     * 1: bpp
-     */
-    public static final int NUM_SURFACE_SIZE_PROPERTIES = 1;
-
-    /** WARNING: must be synchronized with ScreenMode.h, native implementation
-     * 3: ScreenSizeMM[width, height], refresh-rate
-     */
-    public static final int NUM_MONITOR_MODE_PROPERTIES = 3;
-
-    /** WARNING: must be synchronized with ScreenMode.h, native implementation
-     * 1: rotation, native_mode_id
-     */
-    public static final int NUM_SCREEN_MODE_PROPERTIES  = 1;
-
-    /** WARNING: must be synchronized with ScreenMode.h, native implementation
-     * count + all the above
-     */
-    public static final int NUM_SCREEN_MODE_PROPERTIES_ALL = 8;
-
-    public static int getIndex(List<ScreenMode> screenModes, ScreenMode search) {
-        return screenModes.indexOf(search);
-    }
-
-    public static int getIndexByHashCode(List<ScreenMode> screenModes, ScreenMode search) {
-        for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
-            if ( search.hashCode() == screenModes.get(i).hashCode() ) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * @param screenModes
-     * @param resolution
-     * @return modes with nearest resolution, or matching ones
-     */
-    public static List<ScreenMode> filterByResolution(List<ScreenMode> screenModes, DimensionImmutable resolution) {
-        if(null==screenModes || screenModes.size()==0) {
-            return null;
-        }
-        List<ScreenMode> out = new ArrayList<ScreenMode>();
-        int resolution_sq = resolution.getHeight()*resolution.getWidth();
-        int sm_dsq=resolution_sq, sm_dsq_idx=0;
-
-        for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
-            ScreenMode sm = screenModes.get(i);
-            DimensionImmutable res = sm.getMonitorMode().getSurfaceSize().getResolution();
-            int dsq = Math.abs(resolution_sq - res.getHeight()*res.getWidth());
-            if(dsq<sm_dsq) {
-                sm_dsq = dsq;
-                sm_dsq_idx = i;
-            }
-            if(res.equals(resolution)) {
-                out.add(sm);
-            }
-        }
-        if(out.size()>0) {
-            return out;
-        }
-        // nearest ..
-        resolution = screenModes.get(sm_dsq_idx).getMonitorMode().getSurfaceSize().getResolution();
-        return filterByResolution(screenModes, resolution);
-    }
-
-    public static List<ScreenMode> filterBySurfaceSize(List<ScreenMode> screenModes, SurfaceSize surfaceSize) {
-        if(null==screenModes || screenModes.size()==0) {
-            return null;
-        }
-        List<ScreenMode> out = new ArrayList<ScreenMode>();
-        for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
-            ScreenMode sm = screenModes.get(i);
-            if(sm.getMonitorMode().getSurfaceSize().equals(surfaceSize)) {
-                out.add(sm);
-            }
-        }
-        return out.size()>0 ? out : null;
-    }
-
-    public static List<ScreenMode> filterByRotation(List<ScreenMode> screenModes, int rotation) {
-        if(null==screenModes || screenModes.size()==0) {
-            return null;
-        }
-        List<ScreenMode> out = new ArrayList<ScreenMode>();
-        for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
-            ScreenMode sm = screenModes.get(i);
-            if(sm.getRotation() == rotation) {
-                out.add(sm);
-            }
-        }
-        return out.size()>0 ? out : null;
-    }
-
-    public static List<ScreenMode> filterByBpp(List<ScreenMode> screenModes, int bitsPerPixel) {
-        if(null==screenModes || screenModes.size()==0) {
-            return null;
-        }
-        List<ScreenMode> out = new ArrayList<ScreenMode>();
-        for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
-            ScreenMode sm = screenModes.get(i);
-            if(sm.getMonitorMode().getSurfaceSize().getBitsPerPixel() == bitsPerPixel) {
-                out.add(sm);
-            }
-        }
-        return out.size()>0 ? out : null;
-    }
-
-    /**
-     *
-     * @param screenModes
-     * @param refreshRate
-     * @return modes with nearest refreshRate, or matching ones
-     */
-    public static List<ScreenMode> filterByRate(List<ScreenMode> screenModes, int refreshRate) {
-        if(null==screenModes || screenModes.size()==0) {
-            return null;
-        }
-        int sm_dr = refreshRate;
-        int sm_dr_idx = -1;
-        List<ScreenMode> out = new ArrayList<ScreenMode>();
-        for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
-            ScreenMode sm = screenModes.get(i);
-            int dr = Math.abs(refreshRate - sm.getMonitorMode().getRefreshRate());
-            if(dr<sm_dr) {
-                sm_dr = dr;
-                sm_dr_idx = i;
-            }
-            if(0 == dr) {
-                out.add(sm);
-            }
-        }
-        if(out.size()>0) {
-            return out;
-        }
-        refreshRate = screenModes.get(sm_dr_idx).getMonitorMode().getRefreshRate();
-        return filterByRate(screenModes, refreshRate);
-    }
-
-    public static List<ScreenMode> getHighestAvailableBpp(List<ScreenMode> screenModes) {
-        if(null==screenModes || screenModes.size()==0) {
-            return null;
-        }
-        int highest = -1;
-        for (int i=0; null!=screenModes && i < screenModes.size(); i++) {
-            ScreenMode sm = screenModes.get(i);
-            int bpp  = sm.getMonitorMode().getSurfaceSize().getBitsPerPixel();
-            if (bpp > highest) {
-                highest = bpp;
-            }
-        }
-        return filterByBpp(screenModes, highest);
-    }
-
-    public static List<ScreenMode> getHighestAvailableRate(List<ScreenMode> screenModes) {
-        if(null==screenModes || screenModes.size()==0) {
-            return null;
-        }
-        int highest = -1;
-        for (int i=0; null!=screenModes && i < screenModes.size(); i++) {
-            ScreenMode sm = screenModes.get(i);
-            int rate = sm.getMonitorMode().getRefreshRate();
-            if (rate > highest) {
-                highest = rate;
-            }
-        }
-        return filterByRate(screenModes, highest);
-    }
-
-    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
-    public static DimensionImmutable streamInResolution(int[] resolutionProperties, int offset) {
-        Dimension resolution = new Dimension(resolutionProperties[offset++], resolutionProperties[offset++]);
-        return resolution;
-    }
-
-    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
-    public static SurfaceSize streamInSurfaceSize(DimensionImmutable resolution, int[] sizeProperties, int offset) {
-        SurfaceSize surfaceSize = new SurfaceSize(resolution, sizeProperties[offset++]);
-        return surfaceSize;
-    }
-
-    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
-    public static MonitorMode streamInMonitorMode(SurfaceSize surfaceSize, DimensionImmutable screenSizeMM, int[] monitorProperties, int offset) {
-        int refreshRate = monitorProperties[offset++];
-        return new MonitorMode(surfaceSize, screenSizeMM, refreshRate);
-    }
-
-    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
-    public static ScreenMode streamInScreenMode(MonitorMode monitorMode, int[] modeProperties, int offset) {
-        int rotation = modeProperties[offset++];
-        return new ScreenMode(monitorMode, rotation);
-    }
-
-    /**
-     *  WARNING: must be synchronized with ScreenMode.h, native implementation
-     *
-     * @param modeProperties the input data
-     * @param offset the offset to the input data
-     * @return ScreenMode element matching the input <code>modeProperties</code>, 
-     *         or null if input could not be processed.
-     */
-    public static ScreenMode streamIn(int[] modeProperties, int offset) {
-        return streamInImpl(null, null, null, null, null, modeProperties, offset);
-    }
-
-    /**
-     *  WARNING: must be synchronized with ScreenMode.h, native implementation
-     *
-     * @param resolutionPool hash array of unique resolutions, no duplicates
-     * @param surfaceSizePool hash array of unique SurfaceSize, no duplicates
-     * @param monitorModePool hash array of unique MonitorMode, no duplicates
-     * @param screenModePool hash array of unique ScreenMode, no duplicates
-     * @param modeProperties the input data
-     * @param offset the offset to the input data
-     * @return index of the identical (old or new) ScreenMode element in <code>screenModePool</code>,
-     *         matching the input <code>modeProperties</code>, or -1 if input could not be processed.
-     */
-    public static int streamIn(ArrayHashSet<DimensionImmutable> resolutionPool,
-                               ArrayHashSet<SurfaceSize>        surfaceSizePool,
-                               ArrayHashSet<DimensionImmutable> screenSizeMMPool,
-                               ArrayHashSet<MonitorMode>        monitorModePool,
-                               ArrayHashSet<ScreenMode>         screenModePool,
-                               int[] modeProperties, int offset) {
-        ScreenMode screenMode = streamInImpl(resolutionPool, surfaceSizePool, screenSizeMMPool, monitorModePool, screenModePool,
-                                         modeProperties, offset);
-        return screenModePool.indexOf(screenMode);
-    }
-
-                               
-    private static ScreenMode streamInImpl(ArrayHashSet<DimensionImmutable> resolutionPool,
-                                           ArrayHashSet<SurfaceSize>        surfaceSizePool,
-                                           ArrayHashSet<DimensionImmutable> screenSizeMMPool,
-                                           ArrayHashSet<MonitorMode>        monitorModePool,
-                                           ArrayHashSet<ScreenMode>         screenModePool,
-                                           int[] modeProperties, int offset) {
-        int count = modeProperties[offset];
-        if(NUM_SCREEN_MODE_PROPERTIES_ALL != count) {
-            throw new RuntimeException("NUM_SCREEN_MODE_PROPERTIES should be "+NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+count+", len "+(modeProperties.length-offset));
-        }
-        if(NUM_SCREEN_MODE_PROPERTIES_ALL > modeProperties.length-offset) {
-            throw new RuntimeException("properties array too short, should be >= "+NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+(modeProperties.length-offset));
-        }
-        offset++;
-        DimensionImmutable resolution = ScreenModeUtil.streamInResolution(modeProperties, offset);
-        offset += ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
-        if(null!=resolutionPool) {
-            resolution = resolutionPool.getOrAdd(resolution);
-        }
-
-        SurfaceSize surfaceSize = ScreenModeUtil.streamInSurfaceSize(resolution, modeProperties, offset);
-        offset += ScreenModeUtil.NUM_SURFACE_SIZE_PROPERTIES;
-        if(null!=surfaceSizePool) {
-            surfaceSize = surfaceSizePool.getOrAdd(surfaceSize);
-        }
-
-        DimensionImmutable screenSizeMM = ScreenModeUtil.streamInResolution(modeProperties, offset);
-        offset += ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
-        if(null!=screenSizeMMPool) {
-            screenSizeMM = screenSizeMMPool.getOrAdd(screenSizeMM);
-        }
-
-        MonitorMode monitorMode = ScreenModeUtil.streamInMonitorMode(surfaceSize, screenSizeMM, modeProperties, offset);
-        offset += ScreenModeUtil.NUM_MONITOR_MODE_PROPERTIES - ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
-        if(null!=monitorModePool) {
-            monitorMode = monitorModePool.getOrAdd(monitorMode);
-        }
-
-        ScreenMode screenMode = ScreenModeUtil.streamInScreenMode(monitorMode, modeProperties, offset);
-        if(null!=screenModePool) {
-            screenMode = screenModePool.getOrAdd(screenMode);
-        }
-        return screenMode;
-    }
-
-    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
-    public static int[] streamOut (ScreenMode screenMode) {
-        int[] data = new int[NUM_SCREEN_MODE_PROPERTIES_ALL];
-        int idx=0;
-        data[idx++] = NUM_SCREEN_MODE_PROPERTIES_ALL;
-        data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getResolution().getWidth();
-        data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getResolution().getHeight();
-        data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getBitsPerPixel();
-        data[idx++] = screenMode.getMonitorMode().getScreenSizeMM().getWidth();
-        data[idx++] = screenMode.getMonitorMode().getScreenSizeMM().getHeight();
-        data[idx++] = screenMode.getMonitorMode().getRefreshRate();
-        data[idx++] = screenMode.getRotation();
-        if(NUM_SCREEN_MODE_PROPERTIES_ALL != idx) {
-            throw new InternalError("wrong number of attributes: got "+idx+" != should "+NUM_SCREEN_MODE_PROPERTIES_ALL);
-        }
-        return data;
-    }
-
-}
diff --git a/src/newt/classes/jogamp/newt/Debug.java b/src/newt/classes/jogamp/newt/Debug.java
index 3c83da4..676d9b7 100644
--- a/src/newt/classes/jogamp/newt/Debug.java
+++ b/src/newt/classes/jogamp/newt/Debug.java
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * 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
@@ -39,6 +40,9 @@
 
 package jogamp.newt;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
 import com.jogamp.common.util.PropertyAccess;
 
 /** Helper routines for logging and debugging. */
@@ -49,7 +53,12 @@ public class Debug extends PropertyAccess {
   private static final boolean debugAll;
   
   static {
-    PropertyAccess.addTrustedPrefix("newt.", Debug.class);
+    AccessController.doPrivileged(new PrivilegedAction<Object>() {
+        public Object run() {
+            PropertyAccess.addTrustedPrefix("newt.");
+            return null;
+    } } );
+    
     verbose = isPropertyDefined("newt.verbose", true);
     debugAll = isPropertyDefined("newt.debug", true);
     if (verbose) {
@@ -60,18 +69,6 @@ public class Debug extends PropertyAccess {
     }
   }
 
-  public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) {
-    return PropertyAccess.isPropertyDefined(property, jnlpAlias, null);
-  }
-    
-  public static final int getIntProperty(final String property, final boolean jnlpAlias, int defaultValue) {
-      return PropertyAccess.getIntProperty(property, jnlpAlias, null, defaultValue);
-  }
-  
-  public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) {
-      return PropertyAccess.getBooleanProperty(property, jnlpAlias, null);
-  }
-  
   public static boolean verbose() {
     return verbose;
   }
diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
index 18418a8..c080e83 100644
--- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
@@ -81,10 +81,10 @@ public class DefaultEDTUtil implements EDTUtil {
             waitUntilStopped();
             if(DEBUG) {
                 if(edt.tasks.size()>0) {
-                    System.err.println(Thread.currentThread()+": EDT reset, remaining tasks: "+edt.tasks.size()+" - "+edt);
+                    System.err.println(Thread.currentThread()+": Default-EDT reset, remaining tasks: "+edt.tasks.size()+" - "+edt);
                     // Thread.dumpStack();
                 }
-                System.err.println(Thread.currentThread()+": EDT reset - edt: "+edt);
+                System.err.println(Thread.currentThread()+": Default-EDT reset - edt: "+edt);
             }
             this.edt = new EventDispatchThread(threadGroup, name);
             this.edt.setDaemon(true); // don't stop JVM from shutdown ..
@@ -93,13 +93,13 @@ public class DefaultEDTUtil implements EDTUtil {
 
     private final void startImpl() {
         if(edt.isAlive()) {
-            throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size());
+            throw new RuntimeException("Default-EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size());
         }
         start_iter++;
         edt.setName(name+start_iter);
         edt.shouldStop = false;
         if(DEBUG) {
-            System.err.println(Thread.currentThread()+": EDT START - edt: "+edt);
+            System.err.println(Thread.currentThread()+": Default-EDT START - edt: "+edt);
             // Thread.dumpStack();
         }
         edt.start();
@@ -126,8 +126,8 @@ public class DefaultEDTUtil implements EDTUtil {
     }
 
     @Override
-    public final void invokeStop(Runnable task) {
-        invokeImpl(true, task, true);
+    public final void invokeStop(boolean wait, Runnable task) {
+        invokeImpl(wait, task, true);
     }
 
     @Override
@@ -135,10 +135,12 @@ public class DefaultEDTUtil implements EDTUtil {
         invokeImpl(wait, task, false);
     }
 
+    private static Runnable nullTask = new Runnable() {
+        @Override
+        public void run() { }        
+    };
+    
     private void invokeImpl(boolean wait, Runnable task, boolean stop) {
-        if(task == null) {
-            throw new RuntimeException("Null Runnable");
-        }
         Throwable throwable = null;
         RunnableTask rTask = null;
         Object rTaskLock = new Object();
@@ -147,45 +149,58 @@ public class DefaultEDTUtil implements EDTUtil {
                 if( edt.shouldStop ) {
                     // drop task ..
                     if(DEBUG) {
-                        System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+edt);
+                        System.err.println(Thread.currentThread()+": Warning: Default-EDT about (1) to stop, won't enqueue new task: "+edt);
                         Thread.dumpStack();
                     }
-                    return; 
+                    return;
                 }
                 // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
                 // Thread.dumpStack();
-                if(stop) {
-                    edt.shouldStop = true;
-                    if(DEBUG) {
-                        System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - tasks: "+edt.tasks.size()+" - "+edt);
-                        // Thread.dumpStack();
-                    }
-                }
                 if( isCurrentThreadEDT() ) {
-                    task.run();
+                    if(null != task) {
+                        task.run();
+                    }
                     wait = false; // running in same thread (EDT) -> no wait
-                    if(stop && edt.tasks.size()>0) {
-                        System.err.println("Warning: EDT about (2) to stop, having remaining tasks: "+edt.tasks.size()+" - "+edt);
-                        if(DEBUG) {
-                            Thread.dumpStack();
+                    if(stop) {
+                        edt.shouldStop = true;
+                        if( edt.tasks.size()>0 ) {
+                            System.err.println(Thread.currentThread()+": Warning: Default-EDT about (2) to stop, task executed. Remaining tasks: "+edt.tasks.size()+" - "+edt);
+                            if(DEBUG) {
+                                Thread.dumpStack();
+                            }
                         }
                     }
                 } else {
-                    // start if should not stop && not started yet                    
-                    if( !stop && !edt.isRunning() ) {
-                        startImpl();
+                    if( !edt.isRunning() ) {
+                        if( !stop ) {
+                            startImpl();
+                        } else {
+                            // drop task and don't wait
+                            task = null;
+                            System.err.println(Thread.currentThread()+": Warning: Default-EDT is about (3) to stop and stopped already, dropping task. Remaining tasks: "+edt.tasks.size()+" - "+edt);
+                            if(DEBUG) {
+                                Thread.dumpStack();
+                            }
+                        }
+                    } else if(stop && null == task) {
+                        task = nullTask;
                     }
-                    synchronized(edt.tasks) {
-                        wait = wait && edt.isRunning();
-                        rTask = new RunnableTask(task,
-                                                 wait ? rTaskLock : null,
-                                                 true /* always catch and report Exceptions, don't disturb EDT */);
-                        if(stop) {
-                            rTask.setAttachment(new Boolean(true)); // mark final task
+
+                    if(null != task) {
+                        synchronized(edt.tasks) {
+                            rTask = new RunnableTask(task,
+                                                     wait ? rTaskLock : null,
+                                                     true /* always catch and report Exceptions, don't disturb EDT */, 
+                                                     wait ? null : System.err);
+                            if(stop) {
+                                rTask.setAttachment(new Boolean(true)); // mark final task, will imply shouldStop:=true
+                            }
+                            // append task ..
+                            edt.tasks.add(rTask);
+                            edt.tasks.notifyAll();
                         }
-                        // append task ..
-                        edt.tasks.add(rTask);
-                        edt.tasks.notifyAll();
+                    } else {
+                        wait = false;
                     }
                 }
             }
@@ -207,7 +222,7 @@ public class DefaultEDTUtil implements EDTUtil {
             }
         }
         if(DEBUG && stop) {
-            System.err.println(Thread.currentThread()+": EDT signal STOP X edt: "+edt);
+            System.err.println(Thread.currentThread()+": Default-EDT signal STOP X edt: "+edt);
         }
     }
 
@@ -282,7 +297,7 @@ public class DefaultEDTUtil implements EDTUtil {
         @Override
         final public void run() {
             if(DEBUG) {
-                System.err.println(getName()+": EDT run() START "+ getName());
+                System.err.println(getName()+": Default-EDT run() START "+ getName());
             }
             validateNoRecursiveLocksHold();
             RuntimeException error = null;
@@ -307,6 +322,9 @@ public class DefaultEDTUtil implements EDTUtil {
                         if(tasks.size()>0) {
                             task = tasks.remove(0);
                             tasks.notifyAll();
+                            if( null != task.getAttachment() ) {
+                                shouldStop = true;
+                            }
                         }
                     }
                     if(null!=task) {
@@ -314,6 +332,7 @@ public class DefaultEDTUtil implements EDTUtil {
                         validateNoRecursiveLocksHold();
                         if(!task.hasWaiter() && null != task.getThrowable()) {
                             // at least dump stack-trace in case nobody waits for result
+                            System.err.println("DefaultEDT.run(): Catched exception occured on thread "+Thread.currentThread().getName()+": "+task.toString());
                             task.getThrowable().printStackTrace();
                         }
                     }
@@ -324,41 +343,19 @@ public class DefaultEDTUtil implements EDTUtil {
                 if(t instanceof RuntimeException) {
                     error = (RuntimeException) t;
                 } else {
-                    error = new RuntimeException("Within EDT", t);
+                    error = new RuntimeException("Within Default-EDT", t);
                 }
             } finally {
                 if(DEBUG) {
                     RunnableTask rt = ( tasks.size() > 0 ) ? tasks.get(0) : null ;
-                    System.err.println(getName()+": EDT run() END "+ getName()+", tasks: "+tasks.size()+", "+rt+", "+error); 
+                    System.err.println(getName()+": Default-EDT run() END "+ getName()+", tasks: "+tasks.size()+", "+rt+", "+error); 
                 }
                 synchronized(edtLock) {
-                    if(null==error) {
-                        synchronized(tasks) {
-                            // drain remaining tasks (stop not on EDT), 
-                            // while having tasks and no previous-task, or previous-task is non final
-                            RunnableTask task = null;
-                            while ( ( null == task || task.getAttachment() == null ) && tasks.size() > 0 ) {
-                                task = tasks.remove(0);
-                                task.run();
-                                tasks.notifyAll();
-                            }
-                            if(DEBUG) {
-                                if(null!=task && task.getAttachment()==null) {
-                                    System.err.println(getName()+" Warning: EDT exit: Last task Not Final: "+tasks.size()+", "+task+" - "+edt);
-                                } else if(tasks.size()>0) {
-                                    System.err.println(getName()+" Warning: EDT exit: Remaining tasks Post Final: "+tasks.size());
-                                }
-                                Thread.dumpStack();
-                            }
-                        }
-                    }
-                    isRunning = !shouldStop;
-                    if(!isRunning) {
-                        edtLock.notifyAll();
-                    }
+                    isRunning = false;
+                    edtLock.notifyAll();
                 }
                 if(DEBUG) {
-                    System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error);
+                    System.err.println(getName()+": Default-EDT run() EXIT "+ getName()+", exception: "+error);
                 }
                 if(null!=error) {
                     throw error;
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index fbccc57..0d1dcf5 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -45,10 +45,24 @@ import java.util.ArrayList;
 
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
 
 public abstract class DisplayImpl extends Display {
     private static int serialno = 1;
 
+    static {
+        NativeWindowFactory.addCustomShutdownHook(true /* head */, new Runnable() {
+           public void run() {
+               WindowImpl.shutdownAll();
+               ScreenImpl.shutdownAll();
+               DisplayImpl.shutdownAll();
+           }
+        });
+    }
+        
+    /** Ensure static init has been run. */
+    /* pp */static void initSingleton() { }
+    
     private static Class<?> getDisplayClass(String type) 
         throws ClassNotFoundException 
     {
@@ -84,9 +98,8 @@ public abstract class DisplayImpl extends Display {
                 display.hashCode = display.fqname.hashCode();
                 displayList.add(display);
             }
-            if(null == display.edtUtil) {
-                display.setEDTUtil(null); // device's default if EDT is used, or null        
-            }
+            display.setEDTUtil(display.edtUtil); // device's default if EDT is used, or null
+            
             if(DEBUG) {
                 System.err.println("Display.create() NEW: "+display+" "+getThreadName());
             }
@@ -166,20 +179,24 @@ public abstract class DisplayImpl extends Display {
 
     @Override
     public EDTUtil setEDTUtil(EDTUtil newEDTUtil) {        
+        final EDTUtil oldEDTUtil = edtUtil;
         if(null == newEDTUtil) {
-            newEDTUtil = createEDTUtil();
-        } else if( newEDTUtil == edtUtil ) {
             if(DEBUG) {
-                System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!");
+                System.err.println("Display.setEDTUtil(default): "+oldEDTUtil+" -> "+newEDTUtil);
+            }
+            edtUtil = createEDTUtil();
+        } else if( newEDTUtil != edtUtil ) {
+            if(DEBUG) {
+                System.err.println("Display.setEDTUtil(custom): "+oldEDTUtil+" -> "+newEDTUtil);
             }
-            return null; // no change
+            removeEDT( null );
+            edtUtil = newEDTUtil;
+        } else if( DEBUG ) {
+            System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!");
         }
-        final EDTUtil oldEDTUtil = edtUtil;
-        if(DEBUG) {
-            System.err.println("Display.setEDTUtil: "+oldEDTUtil+" -> "+newEDTUtil);
+        if( !edtUtil.isRunning() ) { // start EDT if not running yet
+            edtUtil.invoke(true, null);
         }
-        removeEDT( new Runnable() { public void run() {} } );
-        edtUtil = newEDTUtil;
         return oldEDTUtil;
     }
 
@@ -190,7 +207,7 @@ public abstract class DisplayImpl extends Display {
 
     private void removeEDT(final Runnable task) {
         if(null!=edtUtil) {            
-            edtUtil.invokeStop(task);
+            edtUtil.invokeStop(true, task);
             // ready for restart ..
             edtUtil.waitUntilStopped();
             edtUtil.reset();
@@ -209,11 +226,7 @@ public abstract class DisplayImpl extends Display {
 
     public boolean validateEDT() {
         if(0==refCount && null==aDevice && null != edtUtil && edtUtil.isRunning()) {
-            removeEDT( new Runnable() {
-                public void run() {
-                    // nop
-                }
-            } );
+            removeEDT( null );
             return true;
         }
         return false;
@@ -233,11 +246,10 @@ public abstract class DisplayImpl extends Display {
         if(DEBUG) {
             System.err.println("Display.destroy(): "+this+" "+getThreadName());
         }
-        final AbstractGraphicsDevice f_aDevice = aDevice;
         final DisplayImpl f_dpy = this;
-        removeEDT( new Runnable() {
+        removeEDT( new Runnable() { // blocks!
             public void run() {
-                if ( null != f_aDevice ) {
+                if ( null != aDevice ) {
                     f_dpy.closeNativeImpl();
                 }
             }
@@ -248,6 +260,42 @@ public abstract class DisplayImpl extends Display {
             dumpDisplayList("Display.destroy("+getFQName()+") END");
         }
     }
+    
+    /** May be utilized at a shutdown hook, impl. does not block. */
+    /* pp */ static final void shutdownAll() {
+        final int dCount = displayList.size(); 
+        if(DEBUG) {
+            dumpDisplayList("Display.shutdownAll "+dCount+" instances, on thread "+getThreadName());
+        }
+        for(int i=0; i<dCount && displayList.size()>0; i++) { // be safe ..
+            final DisplayImpl d = (DisplayImpl) displayList.remove(0);
+            if(0 < displaysActive) {
+                displaysActive--;
+            }
+            if(DEBUG) {
+                System.err.println("Display.shutdownAll["+(i+1)+"/"+dCount+"]: "+d);
+            }
+            final Runnable closeNativeTask = new Runnable() {
+                public void run() {
+                    if ( null != d.getGraphicsDevice() ) {
+                        d.closeNativeImpl();
+                    }
+                }
+            };
+            final EDTUtil edtUtil = d.getEDTUtil();
+            if(null != edtUtil) {
+                final long coopSleep = edtUtil.getPollPeriod() * 2;
+                edtUtil.invokeStop(false, closeNativeTask); // don't block
+                try {
+                    Thread.sleep( coopSleep < 50 ? coopSleep : 50 );
+                } catch (InterruptedException e) { }
+            } else {
+                closeNativeTask.run();
+            }
+            d.aDevice = null;
+            d.refCount=0;
+        }
+    }
 
     public synchronized final int addReference() {
         if(DEBUG) {
@@ -366,22 +414,13 @@ public abstract class DisplayImpl extends Display {
     private ArrayList<NEWTEventTask> events = new ArrayList<NEWTEventTask>();
     private volatile boolean haveEvents = false;
 
-    class DispatchMessagesRunnable implements Runnable {
+    final protected Runnable dispatchMessagesRunnable = new Runnable() {
         public void run() {
             DisplayImpl.this.dispatchMessages();
-        }
-    }
-    protected DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable();
+        } };
 
-    final void dispatchMessage(final NEWTEventTask eventTask) {
-        final NEWTEvent event = eventTask.get();
+    final void dispatchMessage(final NEWTEvent event) {
         try { 
-            if(null == event) {
-                // Ooops ?
-                System.err.println("Warning: event of eventTask is NULL");
-                Thread.dumpStack();
-                return;
-            }
             final Object source = event.getSource();        
             if(source instanceof NEWTEventConsumer) {
                 final NEWTEventConsumer consumer = (NEWTEventConsumer) source ;
@@ -399,6 +438,21 @@ public abstract class DisplayImpl extends Display {
             } else {
                 re = new RuntimeException(t);
             }
+            throw re;
+        }
+    }
+    
+    final void dispatchMessage(final NEWTEventTask eventTask) {
+        final NEWTEvent event = eventTask.get();
+        try { 
+            if(null == event) {
+                // Ooops ?
+                System.err.println("Warning: event of eventTask is NULL");
+                Thread.dumpStack();
+                return;
+            }
+            dispatchMessage(event);
+        } catch (RuntimeException re) {
             if( eventTask.isCallerWaiting() ) {
                 // propagate exception to caller
                 eventTask.setException(re);
@@ -454,7 +508,7 @@ public abstract class DisplayImpl extends Display {
         
         // can't wait if we are on EDT or NEDT -> consume right away
         if(wait && edtUtil.isCurrentThreadEDTorNEDT() ) {
-            dispatchMessage(new NEWTEventTask(e, null));
+            dispatchMessage(e);
             return;
         }
         
diff --git a/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java
new file mode 100644
index 0000000..db31cc8
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.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 jogamp.newt;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.Screen;
+
+public class MonitorDeviceImpl extends MonitorDevice {
+
+    public MonitorDeviceImpl(ScreenImpl screen, int nativeId, DimensionImmutable sizeMM, Rectangle viewport, MonitorMode currentMode, ArrayHashSet<MonitorMode> supportedModes) {
+        super(screen, nativeId, sizeMM, viewport, currentMode, supportedModes);
+    }
+    
+    @Override
+    public final MonitorMode queryCurrentMode() {
+        final ScreenImpl screenImpl = (ScreenImpl)screen;
+        final ScreenMonitorState sms = screenImpl.getScreenMonitorStatus(true);
+        sms.lock();
+        try {
+            final MonitorMode mm0 = screenImpl.queryCurrentMonitorModeIntern(this);
+            if(null == mm0) {
+                throw new InternalError("getCurrentMonitorModeIntern() == null");
+            }
+            MonitorMode mmU = supportedModes.get(mm0); // unified instance
+            if( null == mmU ) {
+                // add new mode avoiding exception! 
+                mmU = sms.getMonitorModes().getOrAdd(mm0);
+                mmU = supportedModes.getOrAdd(mmU);
+                if( Screen.DEBUG ) {
+                    System.err.println("Adding new mode: "+mm0+" -> "+mmU);
+                }
+            }
+            // if mode has changed somehow, update it ..
+            if( getCurrentMode().hashCode() != mmU.hashCode() ) {
+                setCurrentModeValue(mmU);
+                sms.fireMonitorModeChanged(this, mmU, true);
+            }
+            return mmU;
+        } finally {
+            sms.unlock();
+        }
+    }
+
+    @Override
+    public final boolean setCurrentMode(MonitorMode mode) {
+        if(Screen.DEBUG) {
+            System.err.println("Screen.setCurrentMode.0: "+this+" -> "+mode);
+        }
+        final ScreenImpl screenImpl = (ScreenImpl)screen;
+        final ScreenMonitorState sms = screenImpl.getScreenMonitorStatus(true);
+        sms.lock();
+        try {
+            final MonitorMode mmC = queryCurrentMode();
+            final MonitorMode mmU = supportedModes.get(mode); // unify via value hash
+            if( null == mmU ) {
+                throw new IllegalArgumentException("Given mode not in set of modes. Current mode "+mode+", "+this);
+            }
+            if( mmU.equals( mmC ) ) {
+                if(Screen.DEBUG) {
+                    System.err.println("Screen.setCurrentMode: 0.0 is-current (skip) "+mmU+" == "+mmC);
+                }            
+                return true;
+            }
+            final long tStart;
+            if(Screen.DEBUG) {
+                tStart = System.nanoTime();                
+            } else {
+                tStart = 0;
+            }
+            
+            sms.fireMonitorModeChangeNotify(this, mmU);
+            if(Screen.DEBUG) {
+                System.err.println("Screen.setCurrentMode ("+(System.nanoTime()-tStart)/1e6+"ms): fireModeChangeNotify() "+mmU);
+            }
+
+            boolean success = screenImpl.setCurrentMonitorModeImpl(this, mmU);
+            if(success) {
+                if(Screen.DEBUG) {
+                    System.err.println("Screen.setCurrentMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentModeImpl() "+mmU+", success(1): "+success);
+                }
+            } else {
+                // 2nd attempt validate!
+                final MonitorMode queriedCurrent = queryCurrentMode(); // may fireModeChanged(..) if successful and differs!
+                success = queriedCurrent.hashCode() == mmU.hashCode() ;
+                if(Screen.DEBUG) {
+                    System.err.println("Screen.setCurrentMode.2: queried "+queriedCurrent);
+                    System.err.println("Screen.setCurrentMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentModeImpl() "+mmU+", success(2): "+success);
+                }
+            }
+            if( success ) {
+                setCurrentModeValue(mmU);
+                modeChanged = !isOriginalMode();
+            }
+            sms.fireMonitorModeChanged(this, mmU, success);
+            if(Screen.DEBUG) {
+                System.err.println("Screen.setCurrentMode ("+(System.nanoTime()-tStart)/1e6+"ms): X.X "+this+", success: "+success);
+            }
+            return success;
+        } finally {
+            sms.unlock();
+        }
+    }
+
+    private final void setCurrentModeValue(MonitorMode currentMode) {
+        this.currentMode = currentMode;
+    }
+    
+    /* pp */ final void setViewportValue(Rectangle viewport) {
+        this.viewport = viewport;
+    }
+    
+    /* pp */ ArrayHashSet<MonitorMode> getSupportedModesImpl() {
+        return supportedModes;
+    }
+    
+}
diff --git a/src/newt/classes/jogamp/newt/MonitorModeProps.java b/src/newt/classes/jogamp/newt/MonitorModeProps.java
new file mode 100644
index 0000000..820807e
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/MonitorModeProps.java
@@ -0,0 +1,355 @@
+/**
+ * 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 jogamp.newt;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+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 jogamp.newt.MonitorDeviceImpl;
+import jogamp.newt.ScreenImpl;
+
+/**
+ * Encodes and decodes {@link MonitorMode} and {@link MonitorDevice} properties.
+ */
+public class MonitorModeProps {
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation
+     * 2: width, height
+     */
+    public static final int NUM_RESOLUTION_PROPERTIES   = 2;
+
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation
+     * 1: bpp
+     */
+    public static final int NUM_SURFACE_SIZE_PROPERTIES = 1;
+    
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation
+     * 2: refresh-rate (Hz*100), flags
+     */
+    public static final int NUM_SIZEANDRATE_PROPERTIES = 2;
+    
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation
+     * 2: id, rotation
+     */
+    public static final int NUM_MONITOR_MODE_PROPERTIES  = 2;
+
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation
+     * count + all the above
+     */
+    public static final int NUM_MONITOR_MODE_PROPERTIES_ALL = 8;
+    
+    public static final int IDX_MONITOR_MODE_BPP =   1 // count
+                                                   + MonitorModeProps.NUM_RESOLUTION_PROPERTIES
+                                                   ;
+    public static final int IDX_MONITOR_MODE_ROT =   1 // count
+                                                   + MonitorModeProps.NUM_RESOLUTION_PROPERTIES
+                                                   + MonitorModeProps.NUM_SURFACE_SIZE_PROPERTIES
+                                                   + MonitorModeProps.NUM_SIZEANDRATE_PROPERTIES
+                                                   + 1 // id of MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES
+                                                   ;
+    
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation
+     * 10: count + id, ScreenSizeMM[width, height], rotated Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+     */
+    public static final int MIN_MONITOR_DEVICE_PROPERTIES = 11;
+
+    public static final int IDX_MONITOR_DEVICE_VIEWPORT =   1 // count
+                                                          + 1 // native mode
+                                                          + MonitorModeProps.NUM_RESOLUTION_PROPERTIES // sizeMM
+                                                          ;
+    
+    public static class Cache {
+        public final ArrayHashSet<DimensionImmutable>       resolutions  = new ArrayHashSet<DimensionImmutable>();
+        public final ArrayHashSet<SurfaceSize>              surfaceSizes = new ArrayHashSet<SurfaceSize>();
+        public final ArrayHashSet<MonitorMode.SizeAndRRate> sizeAndRates = new ArrayHashSet<MonitorMode.SizeAndRRate>(); 
+        public final ArrayHashSet<MonitorMode>              monitorModes = new ArrayHashSet<MonitorMode>();
+        public final ArrayHashSet<MonitorDevice>            monitorDevices = new ArrayHashSet<MonitorDevice>();
+    }
+    
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+    private static DimensionImmutable streamInResolution(int[] resolutionProperties, int offset) {
+        Dimension resolution = new Dimension(resolutionProperties[offset++], resolutionProperties[offset++]);
+        return resolution;
+    }
+
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+    private static SurfaceSize streamInSurfaceSize(DimensionImmutable resolution, int[] sizeProperties, int offset) {
+        SurfaceSize surfaceSize = new SurfaceSize(resolution, sizeProperties[offset++]);
+        return surfaceSize;
+    }
+
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+    private static MonitorMode.SizeAndRRate streamInSizeAndRRate(SurfaceSize surfaceSize, int[] sizeAndRRateProperties, int offset) {
+        final float refreshRate = sizeAndRRateProperties[offset++]/100.0f;
+        final int flags = sizeAndRRateProperties[offset++];
+        return new MonitorMode.SizeAndRRate(surfaceSize, refreshRate, flags);
+    }
+    
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+    private static MonitorMode streamInMonitorMode0(MonitorMode.SizeAndRRate sizeAndRate, int[] modeProperties, int offset) {
+        final int id = modeProperties[offset++];
+        final int rotation = modeProperties[offset++];
+        return new MonitorMode(id, sizeAndRate, rotation);
+    }
+
+    /**
+     *  WARNING: must be synchronized with ScreenMode.h, native implementation
+     *
+     * @param mode_idx if not null and cache is given, returns the index of resulting {@link MonitorMode} within {@link Cache#monitorModes}.
+     * @param cache optional hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
+     * @param modeProperties the input data
+     * @param offset the offset to the input data
+     * @return {@link MonitorMode} of the identical (old or new) element in {@link Cache#monitorModes},
+     *         matching the input <code>modeProperties</code>, or null if input could not be processed.
+     */
+    public static MonitorMode streamInMonitorMode(int[] mode_idx, Cache cache,
+                                                  int[] modeProperties, int offset) {
+        final int count = modeProperties[offset];
+        if(NUM_MONITOR_MODE_PROPERTIES_ALL != count) {
+            throw new RuntimeException("property count should be "+NUM_MONITOR_MODE_PROPERTIES_ALL+", but is "+count+", len "+(modeProperties.length-offset));
+        }
+        if(NUM_MONITOR_MODE_PROPERTIES_ALL > modeProperties.length-offset) {
+            throw new RuntimeException("properties array too short, should be >= "+NUM_MONITOR_MODE_PROPERTIES_ALL+", is "+(modeProperties.length-offset));
+        }
+        offset++;
+        DimensionImmutable resolution = MonitorModeProps.streamInResolution(modeProperties, offset);
+        offset += MonitorModeProps.NUM_RESOLUTION_PROPERTIES;
+        if(null!=cache) {
+            resolution = cache.resolutions.getOrAdd(resolution);
+        }
+
+        SurfaceSize surfaceSize = MonitorModeProps.streamInSurfaceSize(resolution, modeProperties, offset);
+        offset += MonitorModeProps.NUM_SURFACE_SIZE_PROPERTIES;
+        if(null!=cache) {
+            surfaceSize = cache.surfaceSizes.getOrAdd(surfaceSize);
+        }
+
+        MonitorMode.SizeAndRRate sizeAndRate = MonitorModeProps.streamInSizeAndRRate(surfaceSize, modeProperties, offset);
+        offset += MonitorModeProps.NUM_SIZEANDRATE_PROPERTIES;
+        if(null!=cache) {
+            sizeAndRate = cache.sizeAndRates.getOrAdd(sizeAndRate);
+        }
+        
+        MonitorMode monitorMode = MonitorModeProps.streamInMonitorMode0(sizeAndRate, modeProperties, offset);
+        if(null!=cache) {
+            monitorMode = cache.monitorModes.getOrAdd(monitorMode);
+        }
+        if( null != mode_idx && null!=cache) {
+            int _modeIdx  = cache.monitorModes.indexOf(monitorMode);
+            if( 0 > _modeIdx ) {
+                throw new InternalError("Invalid index of current unified mode "+monitorMode);
+            }
+            mode_idx[0] = _modeIdx;
+        }
+        return monitorMode;
+    }
+
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+    public static int[] streamOutMonitorMode (MonitorMode monitorMode) {
+        int[] data = new int[NUM_MONITOR_MODE_PROPERTIES_ALL];
+        int idx=0;
+        data[idx++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+        data[idx++] = monitorMode.getSurfaceSize().getResolution().getWidth();
+        data[idx++] = monitorMode.getSurfaceSize().getResolution().getHeight();
+        data[idx++] = monitorMode.getSurfaceSize().getBitsPerPixel();
+        data[idx++] = (int)(monitorMode.getRefreshRate()*100.0f); // Hz*100
+        data[idx++] = monitorMode.getFlags();
+        data[idx++] = monitorMode.getId();
+        data[idx++] = monitorMode.getRotation();
+        if(NUM_MONITOR_MODE_PROPERTIES_ALL != idx) {
+            throw new InternalError("wrong number of attributes: got "+idx+" != should "+NUM_MONITOR_MODE_PROPERTIES_ALL);
+        }
+        return data;
+    }
+    
+    /** 
+     * WARNING: must be synchronized with ScreenMode.h, native implementation
+     * <p>
+     * Note: This variant only works for impl. w/ a unique mode key pair <i>modeId, rotation</i>.
+     * </p> 
+     * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
+     * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
+     * @param modeProperties the input data
+     * @param offset the offset to the input data
+     * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices},
+     *         matching the input <code>modeProperties</code>, or null if input could not be processed.
+     */
+    public static MonitorDevice streamInMonitorDevice(int[] monitor_idx, Cache cache, ScreenImpl screen, int[] monitorProperties, int offset) {
+        // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+        final int count = monitorProperties[offset];
+        if(MIN_MONITOR_DEVICE_PROPERTIES > count) {
+            throw new RuntimeException("property count should be >= "+MIN_MONITOR_DEVICE_PROPERTIES+", but is "+count+", len "+(monitorProperties.length-offset));
+        }
+        if(MIN_MONITOR_DEVICE_PROPERTIES > monitorProperties.length-offset) {
+            throw new RuntimeException("properties array too short (min), should be >= "+MIN_MONITOR_DEVICE_PROPERTIES+", is "+(monitorProperties.length-offset));
+        }
+        if(count > monitorProperties.length-offset) {
+            throw new RuntimeException("properties array too short (count), should be >= "+count+", is "+(monitorProperties.length-offset));
+        }
+        final int limit = offset + count; 
+        offset++;
+        final List<MonitorMode> allMonitorModes = cache.monitorModes.getData();
+        final int id = monitorProperties[offset++];
+        final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES;
+        final Rectangle viewport = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
+        final MonitorMode currentMode;
+        {
+            final int modeId = monitorProperties[offset++];
+            final int rotation = monitorProperties[offset++];
+            currentMode = getByNativeIdAndRotation(allMonitorModes, modeId, rotation);
+        }
+        final ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
+        while( offset < limit ) {
+            final int modeId = monitorProperties[offset++];
+            for (int i=0; i<allMonitorModes.size(); i++) {
+                final MonitorMode mode = allMonitorModes.get(i);
+                if( mode.getId() == modeId ) {
+                    supportedModes.add(mode);
+                }
+            }
+        }
+        MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewport, currentMode, supportedModes);
+        if(null!=cache) {
+            monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice);
+        }
+        if( null != monitor_idx ) {
+            int _monitorIdx  = cache.monitorDevices.indexOf(monitorDevice);
+            if( 0 > _monitorIdx ) {
+                throw new InternalError("Invalid index of current unified mode "+monitorDevice);
+            }
+            monitor_idx[0] = _monitorIdx;
+        }
+        return monitorDevice;
+    }    
+    private static MonitorMode getByNativeIdAndRotation(List<MonitorMode> monitorModes, int modeId, int rotation) {
+        if( null!=monitorModes && monitorModes.size()>0 ) {
+            for (int i=0; i<monitorModes.size(); i++) {
+                final MonitorMode mode = monitorModes.get(i);
+                if( mode.getId() == modeId && mode.getRotation() == rotation ) {
+                    return mode;
+                }
+            }
+        }
+        return null;
+    }
+    
+    /** 
+     * WARNING: must be synchronized with ScreenMode.h, native implementation
+     * <p>
+     * This variant expects <code>count</code> to be <code>{@link MIN_MONITOR_DEVICE_PROPERTIES} - 1 - {@link NUM_MONITOR_MODE_PROPERTIES}</code>,
+     * due to lack of supported mode and current mode. 
+     * </p>
+     *
+     * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
+     * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
+     * @param supportedModes pre-assembled list of supported {@link MonitorMode}s from cache.
+     * @param currentMode pre-fetched current {@link MonitorMode}s from cache.
+     * @param modeProperties the input data minus supported modes!
+     * @param offset the offset to the input data
+     * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices},
+     *         matching the input <code>modeProperties</code>, or null if input could not be processed.
+     */
+    public static MonitorDevice streamInMonitorDevice(int[] monitor_idx, Cache cache, ScreenImpl screen, ArrayHashSet<MonitorMode> supportedModes, MonitorMode currentMode, int[] monitorProperties, int offset) {
+        // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+        final int count = monitorProperties[offset];
+        if(MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES != count) {
+            throw new RuntimeException("property count should be == "+(MIN_MONITOR_DEVICE_PROPERTIES-1-NUM_MONITOR_MODE_PROPERTIES)+", but is "+count+", len "+(monitorProperties.length-offset));
+        }
+        if(MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES > monitorProperties.length-offset) {
+            throw new RuntimeException("properties array too short (min), should be >= "+(MIN_MONITOR_DEVICE_PROPERTIES-1-NUM_MONITOR_MODE_PROPERTIES)+", is "+(monitorProperties.length-offset));
+        }
+        if(count > monitorProperties.length-offset) {
+            throw new RuntimeException("properties array too short (count), should be >= "+count+", is "+(monitorProperties.length-offset));
+        }
+        offset++;
+        final int id = monitorProperties[offset++];
+        final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES;
+        final Rectangle viewport = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
+        MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewport, currentMode, supportedModes);
+        if(null!=cache) {
+            monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice);
+        }
+        if( null != monitor_idx ) {
+            int _monitorIdx  = cache.monitorDevices.indexOf(monitorDevice);
+            if( 0 > _monitorIdx ) {
+                throw new InternalError("Invalid index of current unified mode "+monitorDevice);
+            }
+            monitor_idx[0] = _monitorIdx;
+        }
+        return monitorDevice;
+    }
+    
+    /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+    public static int[] streamOutMonitorDevice (MonitorDevice monitorDevice) {
+        // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+        int supportedModeCount = monitorDevice.getSupportedModes().size();
+        if( 0 == supportedModeCount ) {
+            throw new RuntimeException("no supported modes: "+monitorDevice);
+        }
+        int[] data = new int[MIN_MONITOR_DEVICE_PROPERTIES + supportedModeCount - 1];
+        int idx=0;
+        data[idx++] = data.length;
+        data[idx++] = monitorDevice.getId();
+        data[idx++] = monitorDevice.getSizeMM().getWidth();
+        data[idx++] = monitorDevice.getSizeMM().getHeight();
+        data[idx++] = monitorDevice.getViewport().getX();
+        data[idx++] = monitorDevice.getViewport().getY();
+        data[idx++] = monitorDevice.getViewport().getWidth();
+        data[idx++] = monitorDevice.getViewport().getHeight();
+        data[idx++] = monitorDevice.getCurrentMode().getId();
+        data[idx++] = monitorDevice.getCurrentMode().getRotation();
+        final List<MonitorMode> supportedModes = monitorDevice.getSupportedModes();
+        for(int i=0; i<supportedModes.size(); i++) {
+            data[idx++] = supportedModes.get(i).getId();
+        }
+        if(data.length != idx) {
+            throw new InternalError("wrong number of attributes: got "+idx+" != should "+data.length);
+        }
+        return data;
+    }
+    
+    public final void swapRotatePair(int rotation, int[] pairs, int offset, int numPairs) {
+        if( MonitorMode.ROTATE_0 == rotation || MonitorMode.ROTATE_180 == rotation ) {
+            // nop
+            return;
+        }
+        for(int i=0; i<numPairs; i++, offset+=2) {
+            final int tmp = pairs[offset];
+            pairs[offset] = pairs[offset+1];  
+            pairs[offset+1] = tmp;
+        }
+    }    
+    
+}
diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java
index c6c1814..911d371 100644
--- a/src/newt/classes/jogamp/newt/OffscreenWindow.java
+++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java
@@ -34,6 +34,8 @@
 
 package jogamp.newt;
 
+import java.util.List;
+
 import javax.media.nativewindow.AbstractGraphicsConfiguration;
 import javax.media.nativewindow.AbstractGraphicsScreen;
 import javax.media.nativewindow.GraphicsConfigurationFactory;
@@ -43,6 +45,8 @@ import javax.media.nativewindow.VisualIDHolder;
 import javax.media.nativewindow.util.Insets;
 import javax.media.nativewindow.util.Point;
 
+import com.jogamp.newt.MonitorDevice;
+
 public class OffscreenWindow extends WindowImpl implements MutableSurface {
 
     long surfaceHandle;
@@ -100,10 +104,15 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface {
     
     @Override
     public boolean setFullscreen(boolean fullscreen) {
-        // nop
-        return false;
+        return false; // nop
     }
 
+    @Override
+    public boolean setFullscreen(List<MonitorDevice> monitors) {
+        return false; // nop
+    }
+
+    
     protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
         sizeChanged(false, width, height, false);
         if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java
index 56d6f67..f63d149 100644
--- a/src/newt/classes/jogamp/newt/ScreenImpl.java
+++ b/src/newt/classes/jogamp/newt/ScreenImpl.java
@@ -34,8 +34,6 @@
 
 package jogamp.newt;
 
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -43,29 +41,33 @@ import java.util.List;
 import javax.media.nativewindow.AbstractGraphicsScreen;
 import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.Point;
-import javax.media.nativewindow.util.SurfaceSize;
-
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
 
 import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.common.util.IntIntHashMap;
 import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
 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.util.MonitorMode;
-import com.jogamp.newt.util.ScreenModeUtil;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
 
-public abstract class ScreenImpl extends Screen implements ScreenModeListener {
+public abstract class ScreenImpl extends Screen implements MonitorModeListener {
     protected static final boolean DEBUG_TEST_SCREENMODE_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableScreenMode", true);
 
-    protected static final int default_sm_bpp = 32;
-    protected static final int default_sm_widthmm = 519;
-    protected static final int default_sm_heightmm = 324;
-    protected static final int default_sm_rate = 60;
-    protected static final int default_sm_rotation = 0;
+    public static final int default_sm_bpp = 32;
+    public static final int default_sm_widthmm = 519;
+    public static final int default_sm_heightmm = 324;
+    public static final int default_sm_rate = 60;
+    public static final int default_sm_rotation = 0;
+    
+    static {
+        DisplayImpl.initSingleton();
+    }
+    
+    /** Ensure static init has been run. */
+    /* pp */static void initSingleton() { }
     
     protected DisplayImpl display;
     protected int screen_idx;
@@ -73,22 +75,13 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
     protected int hashCode;
     protected AbstractGraphicsScreen aScreen;
     protected int refCount; // number of Screen references by Window
-    protected Point vOrigin = new Point(0, 0); // virtual top-left origin
-    protected Dimension vSize = new Dimension(0, 0); // virtual rotated screen size
+    protected Rectangle vOriginSize = new Rectangle(0, 0, 0, 0); // virtual rotated screen origin and size
     protected static Dimension usrSize = null; // property values: newt.ws.swidth and newt.ws.sheight
     protected static volatile boolean usrSizeQueried = false;
-    private ArrayList<ScreenModeListener> referencedScreenModeListener = new ArrayList<ScreenModeListener>();
+    private ArrayList<MonitorModeListener> refMonitorModeListener = new ArrayList<MonitorModeListener>();
+    
     private long tCreated; // creationTime
 
-    static {
-        AccessController.doPrivileged(new PrivilegedAction<Object>() {
-            public Object run() {
-                registerShutdownHook();
-                return null;
-            }
-        });
-    }
-    
     private static Class<?> getScreenClass(String type) throws ClassNotFoundException 
     {
         final Class<?> screenClass = NewtFactory.getCustomClass(type, "ScreenDriver");
@@ -160,10 +153,12 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
         return true;
     }
 
+    @Override
     public int hashCode() {
         return hashCode;
     }
 
+    @Override
     public synchronized final void createNative()
             throws NativeWindowException
     {        
@@ -182,8 +177,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
                 throw new NativeWindowException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen");
             }
             
-            initScreenModeStatus();
-            updateVirtualScreenOriginAndSize();            
+            initMonitorState();
             if(DEBUG) {
                 System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+"), total "+ (System.nanoTime()-tCreated)/1e6 +"ms");
             }
@@ -191,12 +185,13 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
                 screensActive++;
             }
         }
-        ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
+        ScreenMonitorState sms = ScreenMonitorState.getScreenMonitorState(this.getFQName());
         sms.addListener(this);
     }
 
+    @Override
     public synchronized final void destroy() {
-        releaseScreenModeStatus();
+        releaseMonitorState();
 
         synchronized(screenList) {
             screenList.remove(this);
@@ -213,6 +208,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
         display.removeReference();
     }
 
+    @Override
     public synchronized final int addReference() throws NativeWindowException {
         if(DEBUG) {
             System.err.println("Screen.addReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount+1));
@@ -227,6 +223,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
         return ++refCount;
     }
 
+    @Override
     public synchronized final int removeReference() {
         if(DEBUG) {
             System.err.println("Screen.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1));
@@ -240,6 +237,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
         return refCount;
     }
 
+    @Override
     public synchronized final int getReferenceCount() {
         return refCount;
     }
@@ -259,14 +257,20 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
     /**
      * Stores the virtual origin and virtual <b>rotated</b> screen size.
      * <p>
-     * This method is called after the ScreenMode has been set, 
+     * This method is called after the MonitorMode has been set or changed, 
      * hence you may utilize it.
-     * </p> 
-     * @param virtualOrigin the store for the virtual origin
-     * @param virtualSize the store for the virtual rotated size
+     * </p>
+     * <p>
+     * Default implementation uses the union of all monitor's viewport,
+     * calculated via {@link #unionOfMonitorViewportSize()}. 
+     * </p>
+     * @param vOriginSize storage for result
      */
-    protected abstract void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize); 
+    protected void calcVirtualScreenOriginAndSize(final Rectangle vOriginSize) { 
+        unionOfMonitorViewportSize(vOriginSize);
+    }
     
+    @Override
     public final String getFQName() {
         return fqname;
     }
@@ -275,418 +279,395 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
      * Updates the <b>rotated</b> virtual ScreenSize using the native impl.
      */
     protected void updateVirtualScreenOriginAndSize() {
-        getVirtualScreenOriginAndSize(vOrigin, vSize);
-        if(DEBUG) {
-            System.err.println("Detected virtual screen origin "+vOrigin+", size "+vSize);
+        if(null != usrSize ) {
+            vOriginSize.setX(0);
+            vOriginSize.setY(0);
+            vOriginSize.setWidth(usrSize.getWidth());
+            vOriginSize.setHeight(usrSize.getHeight());
+            if(DEBUG) {
+                System.err.println("User virtual screen viewport "+vOriginSize);
+            }
+        } else {
+            calcVirtualScreenOriginAndSize(vOriginSize);
+            if(DEBUG) {
+                System.err.println("Detected virtual screen viewport "+vOriginSize);
+            }
         }
     }
 
+    @Override
     public final Display getDisplay() {
         return display;
     }
 
+    @Override
     public final int getIndex() {
         return screen_idx;
     }
 
+    @Override
     public final AbstractGraphicsScreen getGraphicsScreen() {
         return aScreen;
     }
 
+    @Override
     public synchronized final boolean isNativeValid() {
         return null != aScreen;
     }
 
-    public int getX() { return vOrigin.getX(); }
-    public int getY() { return vOrigin.getY(); }
-    
-    public final int getWidth() {
-        return (null != usrSize) ? usrSize.getWidth() : vSize.getWidth();
-    }
-
-    public final int getHeight() {
-        return (null != usrSize) ? usrSize.getHeight() : vSize.getHeight();
-    }
+    @Override
+    public final int getX() { return vOriginSize.getX(); }
+    @Override
+    public final int getY() { return vOriginSize.getY(); }
+    @Override
+    public final int getWidth() { return vOriginSize.getWidth(); }
+    @Override
+    public final int getHeight() { return vOriginSize.getHeight(); }
+    @Override
+    public final RectangleImmutable getViewport() { return vOriginSize; }
 
     @Override
     public String toString() {
-        return "NEWT-Screen["+getFQName()+", idx "+screen_idx+", refCount "+refCount+", "+getWidth()+"x"+getHeight()+", "+aScreen+", "+display+"]";
+        return "NEWT-Screen["+getFQName()+", idx "+screen_idx+", refCount "+refCount+", vsize "+vOriginSize+", "+aScreen+", "+display+
+                            ", monitors: "+getMonitorDevices()+"]";
     }
 
-    public final List<ScreenMode> getScreenModes() {
-        ArrayHashSet<ScreenMode> screenModes = getScreenModesOrig();
-        if(null != screenModes && 0 < screenModes.size()) {
-            return screenModes.toArrayList();
-        }
-        return null;
+    //
+    // MonitorDevice and MonitorMode 
+    //
+    
+    /**
+     * To be implemented by the native specification.<br>
+     * Is called within a thread safe environment.<br>
+     * Is called only to collect the {@link MonitorMode}s and {@link MonitorDevice}s, usually at startup setting up modes.<br>
+     * <br>
+     * <b>WARNING</b>: must be synchronized with 
+     * <ul>
+     *   <li>{@link MonitorModeProps#NUM_SCREEN_MODE_PROPERTIES} and </li>
+     *   <li>{@link MonitorModeProps#MIN_MONITOR_DEVICE_PROPERTIES}</li>
+     * </ul>, i.e.
+     * <ul>
+     *   <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, int[], int)}</li>
+     *   <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, ArrayHashSet, int[], int)}</li>
+     *   <li>{@link MonitorModeProps#streamInMonitorMode(int[], jogamp.newt.MonitorModeProps.Cache, int[], int)}</li>
+     * </ul>
+     * @param cache memory pool caching the result
+     */
+    protected abstract void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache);
+    
+    protected Rectangle getNativeMonitorDeviceViewportImpl(MonitorDevice monitor) { return null; }
+    
+    /**
+     * To be implemented by the native specification.<br>
+     * Is called within a thread safe environment.<br>
+     * <p>
+     * Implementation shall not unify the result w/ monitor's supported modes or a locally 
+     * saved {@link MonitorModeProps.Cache}, since caller will perform such tasks.
+     * </p>
+     */
+    protected abstract MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor);
+    
+    /**
+     * To be implemented by the native specification.<br>
+     * Is called within a thread safe environment.<br>
+     */
+    protected abstract boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode);
+
+    @Override
+    public final List<MonitorMode> getMonitorModes() {
+        final ScreenMonitorState sms = getScreenMonitorStatus(false);
+        return null != sms ? sms.getMonitorModes().getData() : null; 
+    }
+    
+    @Override
+    public final List<MonitorDevice> getMonitorDevices() {
+        final ScreenMonitorState sms = getScreenMonitorStatus(false);
+        return null != sms ? sms.getMonitorDevices().getData() : null; 
     }
 
-    private final ScreenModeStatus getScreenModeStatus(boolean throwException) {
+    final ScreenMonitorState getScreenMonitorStatus(boolean throwException) {
         final String key = this.getFQName();
-        final ScreenModeStatus res = ScreenModeStatus.getScreenModeStatus(key);
+        final ScreenMonitorState res = ScreenMonitorState.getScreenMonitorState(key);
         if(null == res & throwException) {
-            throw new InternalError("ScreenModeStatus.getScreenModeStatus("+key+") == null");
+            throw new InternalError("ScreenMonitorStatus.getMonitorModeStatus("+key+") == null");
         }
         return res;
     }
     
-    public ScreenMode getOriginalScreenMode() {
-        final ScreenModeStatus sms = getScreenModeStatus(false);
-        return ( null != sms ) ? sms.getOriginalScreenMode() : null ;
-    }
-
-    public ScreenMode getCurrentScreenMode() {
-        ScreenMode smU = null;
-        final ScreenModeStatus sms = getScreenModeStatus(true);
-        final ScreenMode sm0 = getCurrentScreenModeIntern();
-        if(null == sm0) {
-            throw new InternalError("getCurrentScreenModeImpl() == null");
+    @Override
+    public void monitorModeChangeNotify(MonitorEvent me) {
+        if(DEBUG) {
+            System.err.println("monitorModeChangeNotify: "+me);
         }
-        sms.lock();
-        try {
-            smU = sms.getScreenModes().getOrAdd(sm0); // unified instance, maybe new
-
-            // if mode has changed somehow, update it ..
-            if( sms.getCurrentScreenMode().hashCode() != smU.hashCode() ) {
-                sms.fireScreenModeChanged(smU, true);
-            }
-        } finally {
-            sms.unlock();
+        for(int i=0; i<refMonitorModeListener.size(); i++) {
+            ((MonitorModeListener)refMonitorModeListener.get(i)).monitorModeChangeNotify(me);
         }
-        return smU;
     }
 
-    public boolean setCurrentScreenMode(ScreenMode screenMode) {
-        final ScreenMode smC = getCurrentScreenMode();
-        ScreenMode smU = getScreenModesOrig().get(screenMode); // unify via value hash
-        if(smU.equals(smC)) {
-            if(DEBUG) {
-                System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tCreated)+"): 0.0 is-current (skip) "+smU+" == "+smC);
-            }            
-            return true;
-        }
-        ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
-        if(null == sms) {
-            throw new InternalError("ScreenModeStatus.getScreenModeStatus("+this.getFQName()+") == null");            
-        }
-        boolean success;
-        sms.lock();
-        try {
-            final long tStart;
-            if(DEBUG) {
-                tStart = System.nanoTime();                
-            } else {
-                tStart = 0;
-            }
-            
-            sms.fireScreenModeChangeNotify(smU);
-            if(DEBUG) {
-                System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): fireScreenModeChangeNotify() "+smU);
-            }
-
-            success = setCurrentScreenModeImpl(smU);
-            if(success) {
-                if(DEBUG) {
-                    System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentScreenModeImpl() "+smU+", success(1): "+success);
-                }
-            } else {
-                // 2nd attempt validate!
-                final ScreenMode queriedCurrent = getCurrentScreenMode(); // may fireScreenModeChanged(..) if successful and differs!
-                final ScreenMode smsCurrent = sms.getCurrentScreenMode();
-                success = smsCurrent.hashCode() == smU.hashCode() && queriedCurrent.hashCode() == smU.hashCode() ;
-                if(DEBUG) {
-                    System.err.println("Screen.setCurrentScreenMode.2: queried "+queriedCurrent);
-                    System.err.println("Screen.setCurrentScreenMode.2:     SMS "+smsCurrent);
-                    System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentScreenModeImpl() "+smU+", success(2): "+success);
-                }
+    private void updateNativeMonitorDevicesViewport() {
+        final List<MonitorDevice> monitors = getMonitorDevices();
+        for(int i=monitors.size()-1; i>=0; i--) {
+            final MonitorDeviceImpl monitor = (MonitorDeviceImpl) monitors.get(i);
+            final Rectangle newViewport = getNativeMonitorDeviceViewportImpl(monitor);
+            if( DEBUG ) {
+                System.err.println("Screen.updateMonitorViewport["+i+"]: "+monitor.getViewport()+" -> "+newViewport);
             }
-            sms.fireScreenModeChanged(smU, success);
-            if(DEBUG) {
-                System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): X.X "+smU+", success: "+success);
+            if( null != newViewport ) {
+                monitor.setViewportValue(newViewport);
             }
-        } finally {
-            sms.unlock();
-        }
-        return success;
-    }
-
-    public void screenModeChangeNotify(ScreenMode sm) {
-        for(int i=0; i<referencedScreenModeListener.size(); i++) {
-            ((ScreenModeListener)referencedScreenModeListener.get(i)).screenModeChangeNotify(sm);
-        }
+        }        
     }
-
-    public void screenModeChanged(ScreenMode sm, boolean success) {
+    
+    @Override
+    public void monitorModeChanged(MonitorEvent me, boolean success) {
         if(success) {
+            updateNativeMonitorDevicesViewport();
             updateVirtualScreenOriginAndSize();
         }
-        for(int i=0; i<referencedScreenModeListener.size(); i++) {
-            ((ScreenModeListener)referencedScreenModeListener.get(i)).screenModeChanged(sm, success);
+        if(DEBUG) {
+            System.err.println("monitorModeChanged: success "+success+", "+me);
         }
-    }
-
-    public synchronized final void addScreenModeListener(ScreenModeListener sml) {
-        referencedScreenModeListener.add(sml);
-    }
-
-    public synchronized final void removeScreenModeListener(ScreenModeListener sml) {
-        referencedScreenModeListener.remove(sml);
-    }
-
-    /** ScreenModeStatus bridge to native implementation */
-    protected final ArrayHashSet<ScreenMode> getScreenModesOrig() {
-        ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
-        if(null!=sms) {
-            return sms.getScreenModes();
+        for(int i=0; i<refMonitorModeListener.size(); i++) {
+            ((MonitorModeListener)refMonitorModeListener.get(i)).monitorModeChanged(me, success);
         }
-        return null;
     }
 
-    /** ScreenModeStatus bridge to native implementation */
-    protected final IntIntHashMap getScreenModesIdx2NativeIdx() {
-        ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
-        if(null!=sms) {
-            return sms.getScreenModesIdx2NativeIdx();
-        }
-        return null;
+    @Override
+    public synchronized final void addMonitorModeListener(MonitorModeListener sml) {
+        refMonitorModeListener.add(sml);
     }
 
-    /**
-     * To be implemented by the native specification.<br>
-     * Is called within a thread safe environment.<br>
-     * Is called only to collect the ScreenModes, usually at startup setting up modes.<br>
-     * <br>
-     * <b>WARNING</b>: must be synchronized with {@link com.jogamp.newt.util.ScreenModeUtil#NUM_SCREEN_MODE_PROPERTIES},
-     * ie {@link com.jogamp.newt.util.ScreenModeUtil#streamIn(com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, int[], int)}<br>
-     * <br>
-     * <b>Note</b>: Additional 1st element is native mode id.
-     */
-    protected int[] getScreenModeFirstImpl() {
-        return null;
+    @Override
+    public synchronized final void removeMonitorModeListener(MonitorModeListener sml) {
+        refMonitorModeListener.remove(sml);
     }
-
+    
     /**
-     * To be implemented by the native specification.<br>
-     * Is called within a thread safe environment.<br>
-     * Is called only to collect the ScreenModes, usually at startup setting up modes.<br>
-     * <br>
-     * <b>WARNING</b>: must be synchronized with {@link com.jogamp.newt.util.ScreenModeUtil#NUM_SCREEN_MODE_PROPERTIES},
-     * ie {@link com.jogamp.newt.util.ScreenModeUtil#streamIn(com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, int[], int)}<br>
-     * <br>
-     * <b>Note</b>: Additional 1st element is native mode id.
+     * 
+     * @param cache optional ..
+     * @param modeId
+     * @return
      */
-    protected int[] getScreenModeNextImpl() {
-        return null;
+    private final MonitorMode getVirtualMonitorMode(MonitorModeProps.Cache cache, int modeId) {
+        final int[] props = new int[MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL];
+        int i = 0;
+        props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+        props[i++] = getWidth();  // width
+        props[i++] = getHeight(); // height
+        props[i++] = default_sm_bpp;
+        props[i++] = default_sm_rate * 100;
+        props[i++] = 0; // flags
+        props[i++] = modeId;
+        props[i++] = default_sm_rotation;
+        if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) {
+            throw new InternalError("XX");
+        }
+        return MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
     }
 
     /**
-     * To be implemented by the native specification.<br>
-     * Is called within a thread safe environment.<br>
+     * 
+     * @param cache mandatory !
+     * @param monitorId
+     * @param currentMode
+     * @return
      */
-    protected ScreenMode getCurrentScreenModeImpl() {
-        return null;
+    private final MonitorDevice getVirtualMonitorDevice(MonitorModeProps.Cache cache, int monitorId, MonitorMode currentMode) {
+        int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES];
+        int i = 0;
+        props[i++] = MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES;
+        props[i++] = monitorId;
+        props[i++] = default_sm_widthmm;
+        props[i++] = default_sm_heightmm;
+        props[i++] = 0; // rotated viewport x
+        props[i++] = 0; // rotated viewport y
+        props[i++] = currentMode.getRotatedWidth();  // rotated viewport width
+        props[i++] = currentMode.getRotatedHeight(); // rotated viewport height
+        props[i++] = currentMode.getId(); // current mode id
+        props[i++] = currentMode.getRotation();
+        props[i++] = currentMode.getId(); // supported mode id #1
+        if( MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES != i ) {
+            throw new InternalError("XX");
+        }
+        return MonitorModeProps.streamInMonitorDevice(null, cache, this, props, 0);
     }
     
     /**
-     * Utilizes {@link #getCurrentScreenModeImpl()}, if the latter returns null it uses
+     * Utilizes {@link #getCurrentMonitorModeImpl()}, if the latter returns null it uses
      * the current screen size and dummy values.
      */
-    protected ScreenMode getCurrentScreenModeIntern() {
-        ScreenMode res;
+    protected final MonitorMode queryCurrentMonitorModeIntern(MonitorDevice monitor) {
+        MonitorMode res;
         if(DEBUG_TEST_SCREENMODE_DISABLED) {
             res = null;
         } else {
-            res = getCurrentScreenModeImpl();
+            res = queryCurrentMonitorModeImpl(monitor);
         }
         if(null == res) {
             if( 0>=getWidth() || 0>=getHeight() ) {
                 updateVirtualScreenOriginAndSize();
             }
-            int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
-            int i = 0;
-            props[i++] = 0; // set later for verification of iterator
-            props[i++] = getWidth();  // width
-            props[i++] = getHeight(); // height
-            props[i++] = default_sm_bpp;
-            props[i++] = default_sm_widthmm;
-            props[i++] = default_sm_heightmm;
-            props[i++] = default_sm_rate;
-            props[i++] = default_sm_rotation;
-            props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count
-            res = ScreenModeUtil.streamIn(props, 0);
+            res = getVirtualMonitorMode(null, monitor.getCurrentMode().getId());
         }
         return res;
     }
 
-    /**
-     * To be implemented by the native specification.<br>
-     * Is called within a thread safe environment.<br>
-     */
-    protected boolean setCurrentScreenModeImpl(ScreenMode screenMode) {
-        return false;
-    }
-
-    private ScreenModeStatus initScreenModeStatus() {
+    private final ScreenMonitorState initMonitorState() {
         long t0;
         if(DEBUG) {
             t0 = System.nanoTime();
-            System.err.println("Screen.initScreenModeStatus() START ("+DisplayImpl.getThreadName()+", "+this+")");
+            System.err.println("Screen.initMonitorState() START ("+DisplayImpl.getThreadName()+", "+this+")");
         } else {
             t0 = 0;
         }
 
-        ScreenModeStatus sms;
-        ScreenModeStatus.lockScreenModeStatus();
+        boolean vScrnSizeUpdated = false;
+        ScreenMonitorState sms;
+        ScreenMonitorState.lockScreenMonitorState();
         try {
-            sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
-            if(null==sms) {                
-                IntIntHashMap screenModesIdx2NativeIdx = new IntIntHashMap();
-                final ScreenMode currentSM = getCurrentScreenModeIntern();
-                if(null == currentSM) {
-                    throw new InternalError("getCurrentScreenModeImpl() == null");
+            sms = ScreenMonitorState.getScreenMonitorState(this.getFQName());
+            if(null==sms) {
+                final MonitorModeProps.Cache cache = new MonitorModeProps.Cache();
+                if( 0 >= collectNativeMonitorModes(cache) ) {                    
+                    updateVirtualScreenOriginAndSize();
+                    vScrnSizeUpdated = true;
+                    final MonitorMode mode = getVirtualMonitorMode(cache, 0);
+                    cache.monitorModes.getOrAdd(mode);
+                    final MonitorDevice monitor = getVirtualMonitorDevice(cache, 0, mode);
+                    cache.monitorDevices.getOrAdd(monitor);
                 }
-
-                ArrayHashSet<ScreenMode> screenModes = collectNativeScreenModes(screenModesIdx2NativeIdx);
-                screenModes.getOrAdd(currentSM);
                 if(DEBUG) {
                     int i=0;
-                    for(Iterator<ScreenMode> iter=screenModes.iterator(); iter.hasNext(); i++) {
-                        System.err.println(i+": "+iter.next());
+                    for(Iterator<MonitorMode> iMode=cache.monitorModes.iterator(); iMode.hasNext(); i++) {
+                        System.err.println("All["+i+"]: "+iMode.next());
+                    }
+                    i=0;
+                    for(Iterator<MonitorDevice> iMonitor=cache.monitorDevices.iterator(); iMonitor.hasNext(); i++) {
+                        final MonitorDevice crt = iMonitor.next();
+                        System.err.println("["+i+"]: "+crt);
+                        int j=0;
+                        for(Iterator<MonitorMode> iMode=crt.getSupportedModes().iterator(); iMode.hasNext(); j++) {
+                            System.err.println("["+i+"]["+j+"]: "+iMode.next());
+                        }
                     }
                 }
-                
-                sms = new ScreenModeStatus(screenModes, screenModesIdx2NativeIdx);
-                ScreenMode originalScreenMode0 = screenModes.get(currentSM); // unify via value hash
-                if(null == originalScreenMode0) {
-                    throw new RuntimeException(currentSM+" could not be hashed from ScreenMode list");
-                }
-                sms.setOriginalScreenMode(originalScreenMode0);
-                ScreenModeStatus.mapScreenModeStatus(this.getFQName(), sms);
+                sms = new ScreenMonitorState(cache.monitorDevices, cache.monitorModes);
+                ScreenMonitorState.mapScreenMonitorState(this.getFQName(), sms);
             }
         } finally {
-            ScreenModeStatus.unlockScreenModeStatus();
+            ScreenMonitorState.unlockScreenMonitorState();
         }
         if(DEBUG) {
-            System.err.println("Screen.initScreenModeStatus() END dt "+ (System.nanoTime()-t0)/1e6 +"ms");
+            System.err.println("Screen.initMonitorState() END dt "+ (System.nanoTime()-t0)/1e6 +"ms");
+        }
+        if( !vScrnSizeUpdated ) {
+            updateVirtualScreenOriginAndSize();
         }
+
         return sms;
     }
 
-    /** ignores bpp < 15 */
-    private ArrayHashSet<ScreenMode> collectNativeScreenModes(IntIntHashMap screenModesIdx2NativeId) {
-        ArrayHashSet<DimensionImmutable> resolutionPool   = new ArrayHashSet<DimensionImmutable>();
-        ArrayHashSet<SurfaceSize>        surfaceSizePool  = new ArrayHashSet<SurfaceSize>();
-        ArrayHashSet<DimensionImmutable> screenSizeMMPool = new ArrayHashSet<DimensionImmutable>();
-        ArrayHashSet<MonitorMode>        monitorModePool  = new ArrayHashSet<MonitorMode>();
-        ArrayHashSet<ScreenMode>         screenModePool   = new ArrayHashSet<ScreenMode>();
-
-        int[] smProps = null;
-        int num = 0;
-        final int idxBpp =   1 // native mode
-                           + 1 // count
-                           + ScreenModeUtil.NUM_RESOLUTION_PROPERTIES
-                           + ScreenModeUtil.NUM_SURFACE_SIZE_PROPERTIES
-                           - 1 ; // index 0 based
-        do {
-            if(DEBUG_TEST_SCREENMODE_DISABLED) {
-                smProps = null;
-            } else if(0 == num) {
-                smProps = getScreenModeFirstImpl();
-            } else {
-                smProps = getScreenModeNextImpl();
-            }
-            if(null != smProps && 0 < smProps.length && smProps[idxBpp] >= 15) {
-                int nativeId = smProps[0];
-                int screenModeIdx = ScreenModeUtil.streamIn(resolutionPool, surfaceSizePool, screenSizeMMPool,
-                                                            monitorModePool, screenModePool, smProps, 1);
-                if(DEBUG) {
-                    System.err.println("ScreenImpl.collectNativeScreenModes: #"+num+": idx: "+nativeId+" native -> "+screenModeIdx+" newt");
+    /**
+     * Returns the number of successful collected {@link MonitorDevice}s.
+     * <p>
+     * Collects {@link MonitorDevice}s and {@link MonitorMode}s within the given cache.
+     * </p>
+     */
+    private final int collectNativeMonitorModes(MonitorModeProps.Cache cache) { 
+        if(!DEBUG_TEST_SCREENMODE_DISABLED) {
+            collectNativeMonitorModesAndDevicesImpl(cache);
+        }
+        // filter out insufficient modes
+        for(int i=cache.monitorModes.size()-1; i>=0; i--) {
+            final MonitorMode mode = cache.monitorModes.get(i);
+            if( 16 > mode.getSurfaceSize().getBitsPerPixel() ) {
+                boolean keep = false;
+                for(int j=cache.monitorDevices.size()-1; !keep && j>=0; j--) {
+                    final MonitorDevice monitor = cache.monitorDevices.get(j);
+                    keep = monitor.getCurrentMode().equals(mode);
                 }
-                
-                if(screenModeIdx >= 0) {
-                    screenModesIdx2NativeId.put(screenModeIdx, nativeId);
+                if(!keep) {
+                    cache.monitorModes.remove(i);
+                    for(int j=cache.monitorDevices.size()-1; j>=0; j--) {
+                        final MonitorDeviceImpl monitor = (MonitorDeviceImpl) cache.monitorDevices.get(j);
+                        monitor.getSupportedModesImpl().remove(mode);
+                    }
                 }
-            } else if(DEBUG) {
-                System.err.println("ScreenImpl.collectNativeScreenModes: #"+num+": smProps: "+(null!=smProps)+
-                                   ", len: "+(null != smProps ? smProps.length : 0)+
-                                   ", bpp: "+(null != smProps && 0 < smProps.length ? smProps[idxBpp] : 0)+
-                                   " - DROPPING");
             }
-            num++;
-        } while ( null != smProps && 0 < smProps.length );
-
-        if(DEBUG) {
-            System.err.println("ScreenImpl.collectNativeScreenModes: ScreenMode number  : "+screenModePool.size());
-            System.err.println("ScreenImpl.collectNativeScreenModes: MonitorMode number : "+monitorModePool.size());
-            System.err.println("ScreenImpl.collectNativeScreenModes: ScreenSizeMM number: "+screenSizeMMPool.size());
-            System.err.println("ScreenImpl.collectNativeScreenModes: SurfaceSize number : "+surfaceSizePool.size());
-            System.err.println("ScreenImpl.collectNativeScreenModes: Resolution number  : "+resolutionPool.size());
         }
-
-        return screenModePool;
+        if( DEBUG ) {
+            System.err.println("ScreenImpl.collectNativeMonitorModes: MonitorDevice number : "+cache.monitorDevices.size());
+            System.err.println("ScreenImpl.collectNativeMonitorModes: MonitorMode number   : "+cache.monitorModes.size());
+            System.err.println("ScreenImpl.collectNativeMonitorModes: SizeAndRate number   : "+cache.sizeAndRates.size());
+            System.err.println("ScreenImpl.collectNativeMonitorModes: SurfaceSize number   : "+cache.surfaceSizes.size());
+            System.err.println("ScreenImpl.collectNativeMonitorModes: Resolution number    : "+cache.resolutions.size());
+        }
+        return cache.monitorDevices.size();
     }
 
-    private void releaseScreenModeStatus() {
-        ScreenModeStatus sms;
-        ScreenModeStatus.lockScreenModeStatus();
+    private void releaseMonitorState() {
+        ScreenMonitorState sms;
+        ScreenMonitorState.lockScreenMonitorState();
         try {
-            sms = ScreenModeStatus.getScreenModeStatus(getFQName());
+            sms = ScreenMonitorState.getScreenMonitorState(getFQName());
             if(null != sms) {
                 sms.lock();
                 try {
                     if(0 == sms.removeListener(this)) {
-                        if(sms.isOriginalModeChangedByOwner()) {
-                            System.err.println("Screen.destroy(): "+sms.getCurrentScreenMode()+" -> "+sms.getOriginalScreenMode());
-                            try {
-                                setCurrentScreenMode(sms.getOriginalScreenMode());
-                            } catch (Throwable t) {
-                                // be verbose but continue
-                                t.printStackTrace();
+                        final ArrayList<MonitorDevice> monitorDevices = sms.getMonitorDevices().getData();
+                        for(int i=0; i<monitorDevices.size(); i++) {
+                            final MonitorDevice monitor = monitorDevices.get(i);
+                            if( monitor.isModeChangedByUs() ) {
+                                System.err.println("Screen.destroy(): Reset "+monitor);
+                                try {
+                                    monitor.setCurrentMode(monitor.getOriginalMode());
+                                } catch (Throwable t) {
+                                    // be verbose but continue
+                                    t.printStackTrace();
+                                }
                             }
                         }
-                        ScreenModeStatus.unmapScreenModeStatus(getFQName());
+                        ScreenMonitorState.unmapScreenMonitorState(getFQName());
                     }
                 } finally {
                     sms.unlock();
                 }
             }            
         } finally {
-            ScreenModeStatus.unlockScreenModeStatus();
+            ScreenMonitorState.unlockScreenMonitorState();
         }
     }
     
     private final void shutdown() {
-        ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatusUnlocked(getFQName());
+        ScreenMonitorState sms = ScreenMonitorState.getScreenMonitorStateUnlocked(getFQName());
         if(null != sms) {
-            if(sms.isOriginalModeChangedByOwner()) {
-                try {
-                    System.err.println("Screen.shutdown(): "+sms.getCurrentScreenMode()+" -> "+sms.getOriginalScreenMode());
-                    setCurrentScreenModeImpl(sms.getOriginalScreenMode());
-                } catch (Throwable t) {
-                    // be quiet .. shutdown
+            final ArrayList<MonitorDevice> monitorDevices = sms.getMonitorDevices().getData();
+            for(int i=0; i<monitorDevices.size(); i++) {
+                final MonitorDevice monitor = monitorDevices.get(i);
+                if( monitor.isModeChangedByUs() ) {
+                    System.err.println("Screen.shutdown(): Reset "+monitor);
+                    try {
+                        monitor.setCurrentMode(monitor.getOriginalMode());
+                    } catch (Throwable t) {
+                        // be quiet .. shutdown
+                    }
                 }
             }
-            ScreenModeStatus.unmapScreenModeStatusUnlocked(getFQName());
+            ScreenMonitorState.unmapScreenMonitorStateUnlocked(getFQName());
         }            
     }
-    private static final void shutdownAll() {
-        for(int i=0; i < screenList.size(); i++) {
-            ((ScreenImpl)screenList.get(i)).shutdown();
-        }
-    }
     
-    private static synchronized void registerShutdownHook() {
-        final Thread shutdownHook = new Thread(new Runnable() {
-            public void run() {
-                ScreenImpl.shutdownAll();
-            }
-        });
-        AccessController.doPrivileged(new PrivilegedAction<Object>() {
-            public Object run() {
-                Runtime.getRuntime().addShutdownHook(shutdownHook);
-                return null;
+    /** pp */ static final void shutdownAll() {
+        final int sCount = screenList.size(); 
+        if(DEBUG) {
+            System.err.println("Screen.shutdownAll "+sCount+" instances, on thread "+Display.getThreadName());
+        }
+        for(int i=0; i<sCount && screenList.size()>0; i++) { // be safe ..
+            final ScreenImpl s = (ScreenImpl) screenList.remove(0);
+            if(DEBUG) {
+                System.err.println("Screen.shutdownAll["+(i+1)+"/"+sCount+"]: "+s);
             }
-        });
+            s.shutdown();
+        }
     }
 }
-
diff --git a/src/newt/classes/jogamp/newt/ScreenModeStatus.java b/src/newt/classes/jogamp/newt/ScreenModeStatus.java
deleted file mode 100644
index 4075fb1..0000000
--- a/src/newt/classes/jogamp/newt/ScreenModeStatus.java
+++ /dev/null
@@ -1,231 +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 jogamp.newt;
-
-import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.common.util.IntIntHashMap;
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
-import com.jogamp.newt.Screen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-public class ScreenModeStatus {
-    private static boolean DEBUG = Screen.DEBUG;
-
-    private RecursiveLock lock = LockFactory.createRecursiveLock();
-    private ArrayHashSet<ScreenMode> screenModes;
-    private IntIntHashMap screenModesIdx2NativeIdx;
-    private ScreenMode currentScreenMode;
-    private ScreenMode originalScreenMode;
-    private boolean screenModeChangedByOwner; 
-    private ArrayList<ScreenModeListener> listener = new ArrayList<ScreenModeListener>();
-
-    private static HashMap<String, ScreenModeStatus> screenFQN2ScreenModeStatus = new HashMap<String, ScreenModeStatus>();
-    private static RecursiveLock screen2ScreenModeStatusLock = LockFactory.createRecursiveLock();
-
-    protected static void mapScreenModeStatus(String screenFQN, ScreenModeStatus sms) {
-        screen2ScreenModeStatusLock.lock();
-        try {
-            ScreenModeStatus _sms = screenFQN2ScreenModeStatus.get(screenFQN);
-            if( null != _sms ) {
-                throw new RuntimeException("ScreenModeStatus "+_sms+" already mapped to "+screenFQN);
-            }
-            screenFQN2ScreenModeStatus.put(screenFQN, sms);
-            if(DEBUG) {
-                System.err.println("ScreenModeStatus.map "+screenFQN+" -> "+sms);
-            }
-        } finally {
-            screen2ScreenModeStatusLock.unlock();
-        }
-    }
-
-    /**
-     * @param screen the prev user
-     * @return true if mapping is empty, ie no more usage of the mapped ScreenModeStatus
-     */
-    protected static void unmapScreenModeStatus(String screenFQN) {
-        screen2ScreenModeStatusLock.lock();
-        try {
-            unmapScreenModeStatusUnlocked(screenFQN);
-        } finally {
-            screen2ScreenModeStatusLock.unlock();
-        }
-    }
-    protected static void unmapScreenModeStatusUnlocked(String screenFQN) {
-        ScreenModeStatus sms = screenFQN2ScreenModeStatus.remove(screenFQN);
-        if(DEBUG) {
-            System.err.println("ScreenModeStatus.unmap "+screenFQN+" -> "+sms);
-        }
-    }
-
-    protected static ScreenModeStatus getScreenModeStatus(String screenFQN) {
-        screen2ScreenModeStatusLock.lock();
-        try {
-            return getScreenModeStatusUnlocked(screenFQN);
-        } finally {
-            screen2ScreenModeStatusLock.unlock();
-        }
-    }
-    protected static ScreenModeStatus getScreenModeStatusUnlocked(String screenFQN) {
-        return screenFQN2ScreenModeStatus.get(screenFQN);
-    }
-
-    protected static void lockScreenModeStatus() {
-        screen2ScreenModeStatusLock.lock();
-    }
-
-    protected static void unlockScreenModeStatus() {
-        screen2ScreenModeStatusLock.unlock();
-    }
-    
-    public ScreenModeStatus(ArrayHashSet<ScreenMode> screenModes,
-                            IntIntHashMap screenModesIdx2NativeIdx) {
-        this.screenModes = screenModes;
-        this.screenModesIdx2NativeIdx = screenModesIdx2NativeIdx;
-        this.screenModeChangedByOwner = false;
-    }
-
-    protected final void setOriginalScreenMode(ScreenMode originalScreenMode) {
-        this.originalScreenMode = originalScreenMode;
-        this.currentScreenMode = originalScreenMode;
-    }
-
-    public final ScreenMode getOriginalScreenMode() {
-        return originalScreenMode;
-    }
-
-    public final ScreenMode getCurrentScreenMode() {
-        lock();
-        try {
-            return currentScreenMode;
-        } finally {
-            unlock();
-        }
-    }
-
-    /**
-     * We cannot guarantee that we won't interfere w/ another running
-     * application's screen mode change.
-     * <p>
-     * At least we only return <code>true</true> if the owner, ie. the Screen,
-     * has changed the screen mode and if the original screen mode 
-     * is not current the current one.
-     * </p>
-     * @return
-     */
-    public final boolean isOriginalModeChangedByOwner() {
-        lock();
-        try {
-            return screenModeChangedByOwner && !isCurrentModeOriginalMode();
-        } finally {
-            unlock();
-        }
-    }
-
-    protected final boolean isCurrentModeOriginalMode() {
-        if(null != currentScreenMode && null != originalScreenMode) {
-            return currentScreenMode.hashCode() == originalScreenMode.hashCode();
-        }
-        return true;
-    }
-    
-    protected final ArrayHashSet<ScreenMode> getScreenModes() {
-        return screenModes;
-    }
-
-    protected final IntIntHashMap getScreenModesIdx2NativeIdx() {
-        return screenModesIdx2NativeIdx;
-    }
-
-    protected final int addListener(ScreenModeListener l) {
-        lock();
-        try {
-            listener.add(l);
-            if(DEBUG) {
-                System.err.println("ScreenModeStatus.addListener (size: "+listener.size()+"): "+l);
-            }
-            return listener.size();
-        } finally {
-            unlock();
-        }
-    }
-
-    protected final int removeListener(ScreenModeListener l) {
-        lock();
-        try {
-            if(!listener.remove(l)) {
-                throw new RuntimeException("ScreenModeListener "+l+" not contained");
-            }
-            if(DEBUG) {
-                System.err.println("ScreenModeStatus.removeListener (size: "+listener.size()+"): "+l);
-            }
-            return listener.size();
-        } finally {
-            unlock();
-        }
-    }
-
-    protected final void fireScreenModeChangeNotify(ScreenMode desiredScreenMode) {
-        lock();
-        try {
-            for(int i=0; i<listener.size(); i++) {
-                listener.get(i).screenModeChangeNotify(desiredScreenMode);
-            }
-        } finally {
-            unlock();
-        }
-    }
-
-    protected void fireScreenModeChanged(ScreenMode currentScreenMode, boolean success) {
-        lock();
-        try {
-            if(success) {
-                this.currentScreenMode = currentScreenMode;
-                this.screenModeChangedByOwner = !isCurrentModeOriginalMode();
-            }
-            for(int i=0; i<listener.size(); i++) {
-                listener.get(i).screenModeChanged(currentScreenMode, success);
-            }
-        } finally {
-            unlock();
-        }
-    }
-
-    protected final void lock() throws RuntimeException {
-        lock.lock();
-    }
-
-    protected final void unlock() throws RuntimeException {
-        lock.unlock();
-    }
-}
diff --git a/src/newt/classes/jogamp/newt/ScreenMonitorState.java b/src/newt/classes/jogamp/newt/ScreenMonitorState.java
new file mode 100644
index 0000000..66e75be
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/ScreenMonitorState.java
@@ -0,0 +1,195 @@
+/**
+ * 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 jogamp.newt;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class ScreenMonitorState {
+    private static boolean DEBUG = Screen.DEBUG;
+    
+    private final RecursiveLock lock = LockFactory.createRecursiveLock();
+    private final ArrayHashSet<MonitorDevice> allMonitors;
+    private final ArrayHashSet<MonitorMode> allMonitorModes;
+    private ArrayList<MonitorModeListener> listener = new ArrayList<MonitorModeListener>();
+
+    private static HashMap<String, ScreenMonitorState> screenFQN2ScreenMonitorState = new HashMap<String, ScreenMonitorState>();
+    private static RecursiveLock screen2ScreenMonitorState = LockFactory.createRecursiveLock();
+
+    protected static void mapScreenMonitorState(String screenFQN, ScreenMonitorState sms) {
+        screen2ScreenMonitorState.lock();
+        try {
+            ScreenMonitorState _sms = screenFQN2ScreenMonitorState.get(screenFQN);
+            if( null != _sms ) {
+                throw new RuntimeException("ScreenMonitorState "+_sms+" already mapped to "+screenFQN);
+            }
+            screenFQN2ScreenMonitorState.put(screenFQN, sms);
+            if(DEBUG) {
+                System.err.println("ScreenMonitorState.map "+screenFQN+" -> "+sms);
+            }
+        } finally {
+            screen2ScreenMonitorState.unlock();
+        }
+    }
+
+    /**
+     * @param screen the prev user
+     * @return true if mapping is empty, ie no more usage of the mapped ScreenMonitorState
+     */
+    protected static void unmapScreenMonitorState(String screenFQN) {
+        screen2ScreenMonitorState.lock();
+        try {
+            unmapScreenMonitorStateUnlocked(screenFQN);
+        } finally {
+            screen2ScreenMonitorState.unlock();
+        }
+    }
+    protected static void unmapScreenMonitorStateUnlocked(String screenFQN) {
+        ScreenMonitorState sms = screenFQN2ScreenMonitorState.remove(screenFQN);
+        if(DEBUG) {
+            System.err.println("ScreenMonitorState.unmap "+screenFQN+" -> "+sms);
+        }
+    }
+
+    protected static ScreenMonitorState getScreenMonitorState(String screenFQN) {
+        screen2ScreenMonitorState.lock();
+        try {
+            return getScreenMonitorStateUnlocked(screenFQN);
+        } finally {
+            screen2ScreenMonitorState.unlock();
+        }
+    }
+    protected static ScreenMonitorState getScreenMonitorStateUnlocked(String screenFQN) {
+        return screenFQN2ScreenMonitorState.get(screenFQN);
+    }
+
+    protected static void lockScreenMonitorState() {
+        screen2ScreenMonitorState.lock();
+    }
+
+    protected static void unlockScreenMonitorState() {
+        screen2ScreenMonitorState.unlock();
+    }
+    
+    public ScreenMonitorState(ArrayHashSet<MonitorDevice> allMonitors,
+                              ArrayHashSet<MonitorMode> allMonitorModes) {
+        this.allMonitors = allMonitors; 
+        this.allMonitorModes = allMonitorModes;
+    }
+
+    protected ArrayHashSet<MonitorDevice> getMonitorDevices() { 
+        return allMonitors;
+    }
+    
+    protected ArrayHashSet<MonitorMode> getMonitorModes() { 
+        return allMonitorModes;
+    }
+    
+    protected final int addListener(MonitorModeListener l) {
+        lock();
+        try {
+            listener.add(l);
+            if(DEBUG) {
+                System.err.println("ScreenMonitorState.addListener (size: "+listener.size()+"): "+l);
+            }
+            return listener.size();
+        } finally {
+            unlock();
+        }
+    }
+
+    protected final int removeListener(MonitorModeListener l) {
+        lock();
+        try {
+            if(!listener.remove(l)) {
+                throw new RuntimeException("MonitorModeListener "+l+" not contained");
+            }
+            if(DEBUG) {
+                System.err.println("ScreenMonitorState.removeListener (size: "+listener.size()+"): "+l);
+            }
+            return listener.size();
+        } finally {
+            unlock();
+        }
+    }
+
+    protected final MonitorDevice getMonitor(MonitorDevice monitor) {
+        return allMonitors.get(monitor);
+    }
+    
+    protected final void validateMonitor(MonitorDevice monitor) {
+        final MonitorDevice md = allMonitors.get(monitor);
+        if( null == md ) {
+            throw new InternalError("Monitor unknown: "+monitor);
+        }
+    }
+    
+    protected final void fireMonitorModeChangeNotify(MonitorDevice monitor, MonitorMode desiredMode) {
+        lock();
+        try {
+            validateMonitor(monitor);
+            final MonitorEvent me = new MonitorEvent(MonitorEvent.EVENT_MONITOR_MODE_CHANGE_NOTIFY, monitor, System.currentTimeMillis(), desiredMode);
+            for(int i=0; i<listener.size(); i++) {
+                listener.get(i).monitorModeChangeNotify(me);
+            }
+        } finally {
+            unlock();
+        }
+    }
+
+    protected void fireMonitorModeChanged(MonitorDevice monitor, MonitorMode currentMode, boolean success) {
+        lock();
+        try {
+            validateMonitor(monitor);
+            final MonitorEvent me = new MonitorEvent(MonitorEvent.EVENT_MONITOR_MODE_CHANGED, monitor, System.currentTimeMillis(), currentMode);
+            for(int i=0; i<listener.size(); i++) {
+                listener.get(i).monitorModeChanged(me, success);
+            }
+        } finally {
+            unlock();
+        }
+    }
+
+    protected final void lock() throws RuntimeException {
+        lock.lock();
+    }
+
+    protected final void unlock() throws RuntimeException {
+        lock.unlock();
+    }
+}
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 4f8eb3d..77ff210 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -35,25 +35,27 @@
 package jogamp.newt;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.lang.reflect.Method;
 
 import com.jogamp.common.util.IntBitfield;
 import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.newt.MonitorDevice;
 import com.jogamp.newt.NewtFactory;
 import com.jogamp.newt.Display;
 import com.jogamp.newt.Screen;
 import com.jogamp.newt.Window;
 import com.jogamp.common.util.locks.LockFactory;
 import com.jogamp.common.util.locks.RecursiveLock;
-import com.jogamp.newt.ScreenMode;
 import com.jogamp.newt.event.InputEvent;
 import com.jogamp.newt.event.KeyEvent;
 import com.jogamp.newt.event.KeyListener;
+import com.jogamp.newt.event.MonitorEvent;
 import com.jogamp.newt.event.MouseEvent;
 import com.jogamp.newt.event.MouseListener;
 import com.jogamp.newt.event.NEWTEvent;
 import com.jogamp.newt.event.NEWTEventConsumer;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorModeListener;
 import com.jogamp.newt.event.WindowEvent;
 import com.jogamp.newt.event.WindowListener;
 import com.jogamp.newt.event.WindowUpdateEvent;
@@ -68,11 +70,11 @@ import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.nativewindow.SurfaceUpdatedListener;
 import javax.media.nativewindow.WindowClosingProtocol;
-import javax.media.nativewindow.util.DimensionImmutable;
 import javax.media.nativewindow.util.Insets;
 import javax.media.nativewindow.util.InsetsImmutable;
 import javax.media.nativewindow.util.Point;
 import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
 
 import jogamp.nativewindow.SurfaceUpdatedHelper;
 
@@ -80,11 +82,40 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 {
     public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE = Debug.isPropertyDefined("newt.test.Window.reparent.incompatible", true);
     
+    protected static final ArrayList<WindowImpl> windowList = new ArrayList<WindowImpl>();
+    
+    static {
+        ScreenImpl.initSingleton();
+    }
+        
+    /** Maybe utilized at a shutdown hook, impl. does not block. */
+    public static final void shutdownAll() {
+        final int wCount = windowList.size(); 
+        if(DEBUG_IMPLEMENTATION) {
+            System.err.println("Window.shutdownAll "+wCount+" instances, on thread "+getThreadName());
+        }
+        for(int i=0; i<wCount && windowList.size()>0; i++) { // be safe ..
+            final WindowImpl w = windowList.remove(0);
+            if(DEBUG_IMPLEMENTATION) {
+                System.err.println("Window.shutdownAll["+(i+1)+"/"+wCount+"]: "+toHexString(w.getWindowHandle()));
+            }
+            w.shutdown();
+        }
+    }
+    
     /** Timeout of queued events (repaint and resize) */
     static final long QUEUED_EVENT_TO = 1200; // ms    
-    
+
+    //
+    // Volatile: Multithread Mutable Access
+    //    
     private volatile long windowHandle = 0; // lifecycle critical
     private volatile boolean visible = false; // lifecycle critical
+    private volatile boolean hasFocus = false;    
+    private volatile int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user
+    private volatile int x = 64, y = 64; // client-area pos w/o insets
+    private volatile Insets insets = new Insets(); // insets of decoration (if top-level && decorated)
+        
     private RecursiveLock windowLock = LockFactory.createRecursiveLock();  // Window instance wide lock
     private int surfaceLockCount = 0; // surface lock recursion count
     
@@ -95,12 +126,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     private AbstractGraphicsConfiguration config = null; // control access due to delegation
     protected CapabilitiesImmutable capsRequested = null;
     protected CapabilitiesChooser capabilitiesChooser = null; // default null -> default
-    private boolean fullscreen = false, hasFocus = false, brokenFocusChange = false;    
-    private int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user
-    private int x = 64, y = 64; // client-area pos w/o insets
+    private boolean fullscreen = false, brokenFocusChange = false;
+    private List<MonitorDevice> fullscreenMonitors = null;
+    private boolean fullscreenUseMainMonitor = true;
     private boolean autoPosition = true; // default: true (allow WM to choose top-level position, if not set by user)
-    private Insets insets = new Insets(); // insets of decoration (if top-level && decorated)
-        
+    
     private int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets
     private NativeWindow nfs_parent = null;          // non fullscreen parent, in case explicit reparenting is performed (offscreen)
     private String title = "Newt Window";
@@ -110,7 +140,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     private boolean pointerConfined = false;
     private LifecycleHook lifecycleHook = null;
 
-    private boolean handleDestroyNotify = true;
+    private Runnable windowDestroyNotifyAction = null;
 
     private FocusRunnable focusAction = null;
     private KeyListener keyboardFocusHandler = null;
@@ -121,9 +151,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     private ArrayList<NativeWindow> childWindows = new ArrayList<NativeWindow>();
 
     private ArrayList<MouseListener> mouseListeners = new ArrayList<MouseListener>();
-    private int  mouseButtonPressed = 0;  // current pressed mouse button number
+    private short mouseButtonPressed = (short)0;  // current pressed mouse button number
+    private int mouseButtonModMask = 0;  // current pressed mouse button modifier mask
     private long lastMousePressed = 0;    // last time when a mouse button was pressed
-    private int  lastMouseClickCount = 0; // last mouse button click count
+    private short lastMouseClickCount = (short)0; // last mouse button click count
     private boolean mouseInWindow = false;// mouse entered window - is inside the window (may be synthetic)
     private Point lastMousePosition = new Point();
 
@@ -132,10 +163,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     private ArrayList<WindowListener> windowListeners  = new ArrayList<WindowListener>();
     private boolean repaintQueued = false;
 
-    // Workaround for initialization order problems on Mac OS X
-    // between native Newt and (apparently) Fmod -- if Fmod is
-    // initialized first then the connection to the window server
-    // breaks, leading to errors from deep within the AppKit
+    /**
+     * Workaround for initialization order problems on Mac OS X
+     * between native Newt and (apparently) Fmod -- if Fmod is
+     * initialized first then the connection to the window server
+     * breaks, leading to errors from deep within the AppKit
+     */
     public static void init(String type) {
         if (NativeWindowFactory.TYPE_MACOSX.equals(type)) {
             try {
@@ -173,8 +206,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             window.parentWindowHandle = parentWindowHandle;
             window.screen = (ScreenImpl) screen;
             window.capsRequested = (CapabilitiesImmutable) caps.cloneMutable();
-            window.setUndecorated(0!=parentWindowHandle);
             window.instantiationFinished();
+            synchronized( windowList ) {
+                windowList.add(window);
+            }
             return window;
         } catch (Throwable t) {
             t.printStackTrace();
@@ -196,12 +231,30 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             WindowImpl window = (WindowImpl) ReflectionUtil.createInstance( windowClass, cstrArgumentTypes, cstrArguments ) ;
             window.screen = (ScreenImpl) screen;
             window.capsRequested = (CapabilitiesImmutable) caps.cloneMutable();
+            window.instantiationFinished();
+            synchronized( windowList ) {
+                windowList.add(window);
+            }
             return window;
         } catch (Throwable t) {
             throw new NativeWindowException(t);
         }
     }
 
+    /** Fast invalidation of instance w/o any blocking function call. */
+    private final void shutdown() {
+        if(null!=lifecycleHook) {
+            lifecycleHook.shutdownRenderingAction();
+        }
+        setWindowHandle(0);
+        visible = false;
+        fullscreen = false;
+        fullscreenMonitors = null;
+        fullscreenUseMainMonitor = true;
+        hasFocus = false;
+        parentWindowHandle = 0;
+    }
+    
     protected final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) {
         config = cfg;
     }
@@ -220,6 +273,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
          */
         void setVisibleActionPost(boolean visible, boolean nativeWindowCreated);
 
+        /**
+         * Notifies the receiver to preserve resources (GL, ..)
+         * for the next destroy*() calls (only), if supported and if <code>value</code> is <code>true</code>, otherwise clears preservation flag.
+         * @param value <code>true</code> to set the one-shot preservation if supported, otherwise clears it.
+         */
+        void preserveGLStateAtDestroy(boolean value);
+        
         /** 
          * Invoked before Window destroy action, 
          * allows releasing of resources depending on the native Window.<br>
@@ -237,7 +297,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         void destroyActionInLock();
 
         /**
-         * Invoked for expensive modifications, ie while reparenting and ScreenMode change.<br>
+         * Invoked for expensive modifications, ie while reparenting and MonitorMode change.<br>
          * No lock is hold when invoked.<br>
          *
          * @return true is paused, otherwise false. If true {@link #resumeRenderingAction()} shall be issued.
@@ -247,12 +307,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         boolean pauseRenderingAction();
 
         /**
-         * Invoked for expensive modifications, ie while reparenting and ScreenMode change.
+         * Invoked for expensive modifications, ie while reparenting and MonitorMode change.
          * No lock is hold when invoked.<br>
          *
          * @see #pauseRenderingAction()
          */
         void resumeRenderingAction();
+        
+        /**
+         * Shutdown rendering action (thread) abnormally.
+         * <p>
+         * Should be called only at shutdown, if necessary.
+         * </p> 
+         */
+        void shutdownRenderingAction();
     }
 
     private boolean createNative() {
@@ -276,25 +344,45 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         boolean postParentlockFocus = false;
         try {
             if(validateParentWindowHandle()) {
-                if(screenReferenceAdded) {
-                    throw new InternalError("XXX");
-                }
-                if(canCreateNativeImpl()) {
+                if( !screenReferenceAdded ) {
                     screen.addReference();
                     screenReferenceAdded = true;
+                }
+                if(canCreateNativeImpl()) {
+                    final int wX, wY;
+                    final boolean usePosition;
+                    if( autoPosition  ) {
+                        wX = 0;
+                        wY = 0;
+                        usePosition = false;
+                    } else {
+                        wX = getX();
+                        wY = getY();
+                        usePosition = true;
+                    }
+                    final long t0 = System.currentTimeMillis();
                     createNativeImpl();
-                    screen.addScreenModeListener(screenModeListenerImpl);
+                    screen.addMonitorModeListener(monitorModeListenerImpl);
                     setTitleImpl(title);
                     setPointerVisibleImpl(pointerVisible);
                     confinePointerImpl(pointerConfined);
                     setKeyboardVisible(keyboardVisible);
-                    if(waitForVisible(true, false)) {
+                    final long remainingV = waitForVisible(true, false);
+                    if( 0 <= remainingV ) {
                         if(isFullscreen()) {
                             synchronized(fullScreenAction) {
                                 fullscreen = false; // trigger a state change
-                                fullScreenAction.init(true);
+                                fullScreenAction.init(true, fullscreenUseMainMonitor, fullscreenMonitors);
+                                fullscreenMonitors = null; // release references ASAP
+                                fullscreenUseMainMonitor = true;
                                 fullScreenAction.run();
                             }
+                        } else {
+                            // Wait until position is reached within tolerances, either auto-position or custom position.
+                            waitForPosition(usePosition, wX, wY, Window.TIMEOUT_NATIVEWINDOW);
+                        }
+                        if (DEBUG_IMPLEMENTATION) {
+                            System.err.println("Window.createNative(): elapsed "+(System.currentTimeMillis()-t0)+" ms");
                         }
                         postParentlockFocus = true;
                     }
@@ -451,8 +539,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     public static final int FLAG_HAS_PARENT             = 1 <<  8;
     public static final int FLAG_IS_UNDECORATED         = 1 <<  9;
     public static final int FLAG_IS_FULLSCREEN          = 1 << 10;
-    public static final int FLAG_IS_ALWAYSONTOP         = 1 << 11;
-    public static final int FLAG_IS_VISIBLE             = 1 << 12;
+    public static final int FLAG_IS_FULLSCREEN_SPAN     = 1 << 11;
+    public static final int FLAG_IS_ALWAYSONTOP         = 1 << 12;
+    public static final int FLAG_IS_VISIBLE             = 1 << 13;
 
     /**
      * The native implementation should invoke the referenced java state callbacks
@@ -497,6 +586,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
         sb.append("FS_");
         sb.append(0 != ( FLAG_IS_FULLSCREEN & flags));
+        sb.append("_span_");
+        sb.append(0 != ( FLAG_IS_FULLSCREEN_SPAN & flags));
         sb.append(", ");
 
         if( 0 != ( FLAG_CHANGE_DECORATION & flags) ) {
@@ -526,9 +617,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     protected void setTitleImpl(String title) {}
 
     /**
-     * Return screen coordinates of the given coordinates
-     * or null, in which case a NativeWindow traversal shall being used
+     * Translates the given window client-area coordinates with top-left origin
+     * to screen coordinates.
+     * <p>
+     * Since the position reflects the client area, it does not include the insets.
+     * </p>
+     * <p>
+     * May return <code>null</code>, in which case the caller shall traverse through the NativeWindow tree
      * as demonstrated in {@link #getLocationOnScreen(javax.media.nativewindow.util.Point)}.
+     * </p>
      *
      * @return if not null, the screen location of the given coordinates
      */
@@ -573,6 +670,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 }
             } finally {
                 if (LOCK_SURFACE_NOT_READY >= res) {
+                    surfaceLockCount--;
                     _wlock.unlock();
                 }
             }
@@ -627,10 +725,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
 
     @Override
-    public long getDisplayHandle() {
-        // Actually: return getGraphicsConfiguration().getScreen().getDevice().getHandle();
-        return screen.getDisplay().getHandle(); // shortcut
-    }
+    public final long getDisplayHandle() {
+        return config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+    }    
 
     @Override
     public final int  getScreenIndex() {
@@ -643,14 +740,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     // public final void destroy() - see below
 
+    @Override
     public final NativeWindow getParent() {
         return parentWindow;
     }
 
+    @Override
     public final long getWindowHandle() {
         return windowHandle;
     }
 
+    @Override
     public Point getLocationOnScreen(Point storage) {
         if(isNativeValid()) {
             Point d;
@@ -687,14 +787,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     // Window
     //
 
+    @Override
     public final boolean isNativeValid() {
         return 0 != windowHandle ;
     }
 
+    @Override
     public final Screen getScreen() {
         return screen;
     }
-
+    
+    @Override
+    public final MonitorDevice getMainMonitor() {
+        return screen.getMainMonitor(new Rectangle(getX(), getY(), getWidth(), getHeight()));
+    }
+    
     protected final void setVisibleImpl(boolean visible, int x, int y, int width, int height) {
         reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, visible));           
     }    
@@ -705,10 +812,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         final RecursiveLock _lock = windowLock;
         _lock.lock();
         try {
-            if(null!=lifecycleHook) {
-                lifecycleHook.resetCounter();
-            }
-
             if(!visible && null!=childWindows && childWindows.size()>0) {
               synchronized(childWindowsLock) {
                 for(int i = 0; i < childWindows.size(); i++ ) {
@@ -729,8 +832,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             } else if(WindowImpl.this.visible != visible) {
                 if(isNativeValid()) {
                     setVisibleImpl(visible, getX(), getY(), getWidth(), getHeight());
-                    WindowImpl.this.waitForVisible(visible, true);
+                    WindowImpl.this.waitForVisible(visible, false);
                     madeVisible = visible;
+                } else {
+                    WindowImpl.this.visible = true;
                 }
             }
 
@@ -752,6 +857,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 System.err.println("Window setVisible: END ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+WindowImpl.this.visible+", nativeWindowCreated: "+nativeWindowCreated+", madeVisible: "+madeVisible);
             }
         } finally {
+            if(null!=lifecycleHook) {
+                lifecycleHook.resetCounter();
+            }
             _lock.unlock();
         }
         if( nativeWindowCreated || madeVisible ) {
@@ -776,7 +884,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
         runOnEDTIfAvail(wait, new VisibleAction(visible));        
     }
-    
+
+    @Override
     public void setVisible(boolean visible) {
         setVisible(true, visible);
     }
@@ -804,11 +913,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     } else if ( visible && !isNativeValid() && 0 < width && 0 < height ) {
                         visibleAction = 2; // visible (create)
                         defineSize(width, height);
-                    } else if ( isNativeValid() ) {
+                    } else if ( visible && isNativeValid() ) {
                         visibleAction = 0;
                         // this width/height will be set by windowChanged, called by the native implementation
                         reconfigureWindowImpl(getX(), getY(), width, height, getReconfigureFlags(0, isVisible()));
+                        WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW);
                     } else {
+                        // invisible or invalid w/ 0 size
                         visibleAction = 0;
                         defineSize(width, height);
                     }
@@ -826,9 +937,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     }
 
+    @Override
     public void setSize(int width, int height) {
         runOnEDTIfAvail(true, new SetSizeAction(width, height));
     }    
+    @Override
     public void setTopLevelSize(int width, int height) {
         setSize(width - getInsets().getTotalWidth(), height - getInsets().getTotalHeight());
     }
@@ -846,8 +959,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             _lock.lock();
             try {
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("Window DestroyAction() "+getThreadName());
+                    System.err.println("Window DestroyAction() hasScreen "+(null != screen)+", isNativeValid "+isNativeValid()+" - "+getThreadName());
                 }
+                
+                // send synced destroy-notify notification
+                sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+                
                 // Childs first ..
                 synchronized(childWindowsLock) {
                   if(childWindows.size()>0) {
@@ -857,8 +974,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     while( clonedChildWindows.size() > 0 ) {
                       NativeWindow nw = clonedChildWindows.remove(0);
                       if(nw instanceof WindowImpl) {
-                          ((WindowImpl)nw).sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
-                          ((WindowImpl)nw).destroy();
+                          ((WindowImpl)nw).windowDestroyNotify(true);
                       } else {
                           nw.destroy();
                       }
@@ -871,16 +987,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     lifecycleHook.destroyActionInLock();
                 }
 
-                if( null != screen ) {
-                    if( isNativeValid() ) {
-                        screen.removeScreenModeListener(screenModeListenerImpl);
-                        closeNativeImpl();
-                        removeScreenReference();
-                    }
-                    Display dpy = screen.getDisplay();
-                    if(null != dpy) {
-                        dpy.validateEDT();
+                if( isNativeValid() ) {
+                    screen.removeMonitorModeListener(monitorModeListenerImpl);
+                    closeNativeImpl();
+                    final AbstractGraphicsDevice cfgADevice = config.getScreen().getDevice();
+                    if( cfgADevice != screen.getDisplay().getGraphicsDevice() ) { // don't pull display's device
+                        cfgADevice.close(); // ensure a cfg's device is closed
                     }
+                    setGraphicsConfiguration(null);
+                }
+                removeScreenReference();
+                Display dpy = screen.getDisplay();
+                if(null != dpy) {
+                    dpy.validateEDT();
                 }
 
                 // send synced destroyed notification
@@ -894,6 +1013,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 setWindowHandle(0);
                 visible = false;
                 fullscreen = false;
+                fullscreenMonitors = null;
+                fullscreenUseMainMonitor = true;
                 hasFocus = false;
                 parentWindowHandle = 0;
 
@@ -923,11 +1044,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
     private final DestroyAction destroyAction = new DestroyAction();
 
+    @Override
     public void destroy() {
+        synchronized( windowList ) {
+            windowList.remove(this);
+        }        
         visible = false; // Immediately mark synchronized visibility flag, avoiding possible recreation 
         runOnEDTIfAvail(true, destroyAction);
     }
 
+    protected void destroy(boolean preserveResources) {
+        if( null != lifecycleHook ) {
+            lifecycleHook.preserveGLStateAtDestroy( preserveResources );
+        }
+        destroy();
+    }
+    
     /**
      * @param cWin child window, must not be null
      * @param pWin parent window, may be null
@@ -1008,10 +1140,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     System.err.println("Window.reparent: START ("+getThreadName()+") valid "+isNativeValid()+", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+", visible "+wasVisible+", old parentWindow: "+Display.hashCodeNullSafe(parentWindow)+", new parentWindow: "+Display.hashCodeNullSafe(newParentWindow)+", forceDestroyCreate "+forceDestroyCreate+", "+x+"/"+y+" "+width+"x"+height);
                 }
 
-                if(null!=lifecycleHook) {
-                    lifecycleHook.resetCounter();
-                }
-
                 if(null!=newParentWindow) {
                     // reset position to 0/0 within parent space
                     x = 0;
@@ -1034,7 +1162,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                         }
                         // Destroy this window and use parent's Screen.
                         // It may be created properly when the parent is made visible.
-                        destroy();
+                        destroy( false );
                         setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
                         operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING;
                     } else if(newParentWindow != getParent()) {
@@ -1045,8 +1173,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                             if(null!=newParentWindowNEWT) {
                                 setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
                             } else {
-                                Screen newScreen = NewtFactory.createCompatibleScreen(newParentWindow, getScreen());
-                                if( getScreen() != newScreen ) {
+                                final Screen newScreen = NewtFactory.createCompatibleScreen(newParentWindow, screen);
+                                if( screen != newScreen ) {
                                     // auto destroy on-the-fly created Screen/Display
                                     setScreen( (ScreenImpl) newScreen );
                                 }
@@ -1056,14 +1184,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                             } else {
                                 operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING;
                             }
-                        } else if ( forceDestroyCreate || !NewtFactory.isScreenCompatible(newParentWindow, getScreen()) ) {
-                            // Destroy this window, may create a new compatible Screen/Display,
-                            // and mark it for creation.
-                            destroy();
+                        } else if ( forceDestroyCreate || !NewtFactory.isScreenCompatible(newParentWindow, screen) ) {
+                            // Destroy this window, may create a new compatible Screen/Display, while trying to preserve resources if becoming visible again.                            
+                            destroy( wasVisible );
                             if(null!=newParentWindowNEWT) {
                                 setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
                             } else {
-                                setScreen( (ScreenImpl) NewtFactory.createCompatibleScreen(newParentWindow, getScreen()) );
+                                setScreen( (ScreenImpl) NewtFactory.createCompatibleScreen(newParentWindow, screen) );
                             }
                             operation = ReparentOperation.ACTION_NATIVE_CREATION;
                         } else {
@@ -1078,7 +1205,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     if( null != parentWindow ) {
                         // child -> top
                         // put client to current parent+child position
-                        Point p = getLocationOnScreen(null);
+                        final Point p = getLocationOnScreen(null);
                         x = p.getX();
                         y = p.getY();
                     }
@@ -1089,7 +1216,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                         operation = ReparentOperation.ACTION_NOP;
                     } else if( !isNativeValid() || forceDestroyCreate ) {
                         // Destroy this window and mark it for [pending] creation.
-                        destroy();
+                        // If isNativeValid() and becoming visible again - try to preserve resources, i.e. b/c on-/offscreen switch.
+                        destroy( isNativeValid() && wasVisible );
                         if( 0 < width && 0 < height ) {
                             operation = ReparentOperation.ACTION_NATIVE_CREATION;
                         } else {
@@ -1134,13 +1262,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 }
 
                 if( ReparentOperation.ACTION_NATIVE_REPARENTING == operation ) {
-                    DisplayImpl display = (DisplayImpl) screen.getDisplay();
+                    final DisplayImpl display = (DisplayImpl) screen.getDisplay();
                     display.dispatchMessagesNative(); // status up2date
 
                     if(wasVisible) {
                         setVisibleImpl(false, x, y, width, height);
-                        WindowImpl.this.waitForVisible(false, true);
-                        // some composite WM behave slacky .. give 'em chance to change state -> invisible,
+                        WindowImpl.this.waitForVisible(false, false);
+                        // FIXME: Some composite WM behave slacky .. give 'em chance to change state -> invisible,
                         // even though we do exactly that (KDE+Composite)
                         try { Thread.sleep(100); } catch (InterruptedException e) { }
                         display.dispatchMessagesNative(); // status up2date
@@ -1166,14 +1294,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                             parentWindowLocked.unlockSurface();
                         }
                     }
+                    definePosition(x, y); // position might not get updated by WM events (SWT parent apparently)
 
                     // set visible again
                     if(ok) {
                         display.dispatchMessagesNative(); // status up2date
                         if(wasVisible) {
                             setVisibleImpl(true, x, y, width, height);
-                            ok = WindowImpl.this.waitForVisible(true, false);
-                            display.dispatchMessagesNative(); // status up2date
+                            ok = 0 <= WindowImpl.this.waitForVisible(true, false);
                             if(ok) {
                                 ok = WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW);
                             }
@@ -1192,19 +1320,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     }
                     
                     if(!ok) {
-                        // native reparent failed -> try creation
+                        // native reparent failed -> try creation, while trying to preserve resources if becoming visible again.
                         if(DEBUG_IMPLEMENTATION) {
                             System.err.println("Window.reparent: native reparenting failed ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentWindowHandle)+" - Trying recreation");
                         }
-                        destroy();
+                        destroy( wasVisible );
                         operation = ReparentOperation.ACTION_NATIVE_CREATION ;
                     }
                 }
                 
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("Window.reparentWindow: END-1 ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height);
+                    System.err.println("Window.reparentWindow: END-1 ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
                 }
             } finally {
+                if(null!=lifecycleHook) {
+                    lifecycleHook.resetCounter();
+                }
                 _lock.unlock();
             }
             if(wasVisible) {
@@ -1223,7 +1354,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 }
             }
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window.reparentWindow: END-X ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height);
+                System.err.println("Window.reparentWindow: END-X ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
             }
         }
     }
@@ -1233,7 +1364,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             final RecursiveLock _lock = windowLock;
             _lock.lock();
             try {
-                visible = true;
                 if(DEBUG_IMPLEMENTATION) {
                     System.err.println("Window.reparentWindow: ReparentActionRecreate ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+Display.hashCodeNullSafe(parentWindow));
                 }
@@ -1245,6 +1375,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
     private final ReparentActionRecreate reparentActionRecreate = new ReparentActionRecreate();
 
+    @Override
     public final ReparentOperation reparentWindow(NativeWindow newParent) {
         return reparentWindow(newParent, false);
     }
@@ -1255,16 +1386,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         return reparentAction.getOp();
     }
 
+    @Override
     public CapabilitiesChooser setCapabilitiesChooser(CapabilitiesChooser chooser) {
         CapabilitiesChooser old = this.capabilitiesChooser;
         this.capabilitiesChooser = chooser;
         return old;
     }
 
+    @Override
     public final CapabilitiesImmutable getChosenCapabilities() {
         return getGraphicsConfiguration().getChosenCapabilities();
     }
 
+    @Override
     public final CapabilitiesImmutable getRequestedCapabilities() {
         return capsRequested;
     }
@@ -1304,10 +1438,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     }
 
+    @Override
     public void setUndecorated(boolean value) {
         runOnEDTIfAvail(true, new DecorationAction(value));
     }
 
+    @Override
     public final boolean isUndecorated() {
         return 0 != parentWindowHandle || undecorated || fullscreen ;
     }
@@ -1347,17 +1483,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     }
 
+    @Override
     public final void setAlwaysOnTop(boolean value) {
         runOnEDTIfAvail(true, new AlwaysOnTopAction(value));
     }
     
+    @Override
     public final boolean isAlwaysOnTop() {
         return alwaysOnTop;
     }
         
+    @Override
     public String getTitle() {
         return title;
     }
+    @Override
     public void setTitle(String title) {
         if (title == null) {
             title = "";
@@ -1368,9 +1508,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     }
 
+    @Override
     public boolean isPointerVisible() {
         return pointerVisible;
     }
+    @Override
     public void setPointerVisible(boolean pointerVisible) {
         if(this.pointerVisible != pointerVisible) {
             boolean setVal = 0 == getWindowHandle();
@@ -1382,10 +1524,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             }
         }
     }
+    @Override
     public boolean isPointerConfined() {
         return pointerConfined;
     }
     
+    @Override
     public void confinePointer(boolean confine) {
         if(this.pointerConfined != confine) {
             boolean setVal = 0 == getWindowHandle();
@@ -1409,12 +1553,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }        
     }
     
+    @Override
     public void warpPointer(int x, int y) {
         if(0 != getWindowHandle()) {
             warpPointerImpl(x, y);
         }
     }
     
+    @Override
     public final InsetsImmutable getInsets() {
         if(isUndecorated()) {
             return Insets.getZero();
@@ -1423,18 +1569,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         return insets;
     }
     
+    @Override
     public final int getWidth() {
         return width;
     }
 
+    @Override
     public final int getHeight() {
         return height;
     }
 
+    @Override
     public final int getX() {
         return x;
     }
 
+    @Override
     public final int getY() {
         return y;
     }
@@ -1460,10 +1610,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         this.width = width; this.height = height;
     }
     
+    @Override
     public final boolean isVisible() {
         return visible;
     }
 
+    @Override
     public final boolean isFullscreen() {
         return fullscreen;
     }
@@ -1472,6 +1624,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     // Window
     //
 
+    @Override
+    public final Window getDelegatedWindow() {
+        return this;
+    }
+    
+    //----------------------------------------------------------------------
+    // WindowImpl
+    //
+
     /**
      * If the implementation is capable of detecting a device change
      * return true and clear the status/reason of the change.
@@ -1490,28 +1651,18 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         return old;
     }
 
-    /** If this Window actually wraps one from another toolkit such as
-        the AWT, this will return a non-null value. */
-    public Object getWrappedWindow() {
-        return null;
-    }
-    
-    public final Window getDelegatedWindow() {
-        return this;
-    }
-    
-    /**
-     * If set to true, the default value, this NEWT Window implementation will
-     * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify(boolean)} implementation.<br>
-     * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify(boolean)}.
+    /** 
+     * If this Window actually wraps a {@link NativeSurface} from another instance or toolkit, 
+     * it will return such reference. Otherwise returns null.
      */
-    public void setHandleDestroyNotify(boolean b) {
-        handleDestroyNotify = b;
+    public NativeSurface getWrappedSurface() {
+        return null;
     }
 
-    //----------------------------------------------------------------------
-    // WindowImpl
-    //
+    @Override
+    public void setWindowDestroyNotifyAction(Runnable r) {
+        windowDestroyNotifyAction = r;
+    }
 
     /** 
      * Returns the non delegated {@link AbstractGraphicsConfiguration}, 
@@ -1538,7 +1689,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     "\n, Visible "+isVisible()+", focus "+hasFocus()+
                     "\n, Undecorated "+undecorated+" ("+isUndecorated()+")"+
                     "\n, AlwaysOnTop "+alwaysOnTop+", Fullscreen "+fullscreen+
-                    "\n, WrappedWindow "+getWrappedWindow()+
+                    "\n, WrappedSurface "+getWrappedSurface()+
                     "\n, ChildWindows "+childWindows.size());
 
         sb.append(", SurfaceUpdatedListeners num "+surfaceUpdatedHelper.size()+" [");
@@ -1557,7 +1708,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         for (int i = 0; i < keyListeners.size(); i++ ) {
           sb.append(keyListeners.get(i)+", ");
         }
-        sb.append("], windowLock "+windowLock+"]");
+        sb.append("], windowLock "+windowLock+", surfaceLockCount "+surfaceLockCount+"]");
         return sb.toString();
     }
 
@@ -1565,16 +1716,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         windowHandle = handle;
     }
 
+    @Override
     public void runOnEDTIfAvail(boolean wait, final Runnable task) {
-        if(windowLock.isOwner(Thread.currentThread())) {
+        if( windowLock.isOwner( Thread.currentThread() ) ) {
             task.run();
         } else {
-            Screen scrn = getScreen();
-            if(null==scrn) {
-                throw new RuntimeException("Null screen of inner class: "+this);
-            }
-            DisplayImpl d = (DisplayImpl) scrn.getDisplay();
-            d.runOnEDTIfAvail(wait, task);
+            ( (DisplayImpl) screen.getDisplay() ).runOnEDTIfAvail(wait, task);
         }
     }
 
@@ -1595,14 +1742,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     };
 
+    @Override
     public final boolean hasFocus() {
         return hasFocus;
     }
 
+    @Override
     public void requestFocus() {
         requestFocus(true);
     }
 
+    @Override
     public void requestFocus(boolean wait) {
         requestFocus(wait /* wait */, false /* skipFocusAction */, brokenFocusChange /* force */);
     }
@@ -1625,6 +1775,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }        
     }
     
+    @Override
     public void setFocusAction(FocusRunnable focusAction) {
         this.focusAction = focusAction;
     }
@@ -1649,6 +1800,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         brokenFocusChange = v;
     }
     
+    @Override
     public void setKeyboardFocusHandler(KeyListener l) {
         keyboardFocusHandler = l;
     }
@@ -1672,6 +1824,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     if(isNativeValid()) {
                         // this.x/this.y will be set by sizeChanged, triggered by windowing event system
                         reconfigureWindowImpl(x, y, getWidth(), getHeight(), getReconfigureFlags(0, isVisible()));
+                        
+                        // Wait until custom position is reached within tolerances
+                        waitForPosition(true, x, y, Window.TIMEOUT_NATIVEWINDOW);
                     } else {
                         definePosition(x, y); // set pos for createNative(..)
                     }
@@ -1682,24 +1837,38 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     }
 
+    @Override
     public void setPosition(int x, int y) {
         autoPosition = false;
         runOnEDTIfAvail(true, new SetPositionAction(x, y));
     }
     
+    @Override
     public void setTopLevelPosition(int x, int y) {
         setPosition(x + getInsets().getLeftWidth(), y + getInsets().getTopHeight());
     }
     
     private class FullScreenAction implements Runnable {
         boolean fullscreen;
+        List<MonitorDevice> monitors;
+        boolean useMainMonitor;
 
-        private boolean init(boolean fullscreen) {            
+        private boolean init(boolean fullscreen, boolean useMainMonitor, List<MonitorDevice> monitors) {            
             if(isNativeValid()) {
                 this.fullscreen = fullscreen;
-                return isFullscreen() != fullscreen;
+                if( isFullscreen() != fullscreen ) {
+                    this.monitors = monitors;
+                    this.useMainMonitor = useMainMonitor;
+                    return true;
+                } else {
+                    this.monitors = null;
+                    this.useMainMonitor = true;
+                    return false;
+                }
             } else {
                 WindowImpl.this.fullscreen = fullscreen; // set current state for createNative(..)
+                WindowImpl.this.fullscreenMonitors = monitors;
+                WindowImpl.this.fullscreenUseMainMonitor = useMainMonitor;
                 return false;
             }
         }                
@@ -1712,19 +1881,32 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 // set current state
                 WindowImpl.this.fullscreen = fullscreen;
 
-                final ScreenMode sm = screen.getCurrentScreenMode();
                 int x,y,w,h;
                 
+                final RectangleImmutable viewport; 
+                final int fs_span_flag;
                 if(fullscreen) {
+                    if( null == monitors ) {
+                        if( useMainMonitor ) {
+                            monitors = new ArrayList<MonitorDevice>();
+                            monitors.add( getMainMonitor() );
+                        } else {
+                            monitors = getScreen().getMonitorDevices();
+                        }
+                    }
+                    fs_span_flag = monitors.size() > 1 ? FLAG_IS_FULLSCREEN_SPAN : 0 ;
+                    viewport = MonitorDevice.unionOfViewports(new Rectangle(), monitors);
                     nfs_x = getX();
                     nfs_y = getY();
                     nfs_width = getWidth();
                     nfs_height = getHeight();
-                    x = screen.getX(); 
-                    y = screen.getY();
-                    w = sm.getRotatedWidth();
-                    h = sm.getRotatedHeight();
+                    x = viewport.getX(); 
+                    y = viewport.getY();
+                    w = viewport.getWidth();
+                    h = viewport.getHeight();
                 } else {
+                    fs_span_flag = 0;
+                    viewport = null;
                     x = nfs_x;
                     y = nfs_y;
                     w = nfs_width;
@@ -1744,9 +1926,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                         }
                     }
                 }
+                monitors = null; // clear references ASAP
+                useMainMonitor = true;
                 if(DEBUG_IMPLEMENTATION) {
                     System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+
-                                       ", virtl-size: "+screen.getWidth()+"x"+screen.getHeight()+", SM "+sm.getRotatedWidth()+"x"+sm.getRotatedHeight());
+                                       ", virtl-size: "+screen.getWidth()+"x"+screen.getHeight()+", monitorsViewport "+viewport);
                 }
 
                 DisplayImpl display = (DisplayImpl) screen.getDisplay();
@@ -1766,7 +1950,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 try {
                     reconfigureWindowImpl(x, y, w, h, 
                                           getReconfigureFlags( ( ( null != parentWindowLocked ) ? FLAG_CHANGE_PARENTING : 0 ) | 
-                                                               FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) ); 
+                                                               fs_span_flag | FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) );
                 } finally {
                     if(null!=parentWindowLocked) {
                         parentWindowLocked.unlockSurface();
@@ -1793,9 +1977,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
     private final FullScreenAction fullScreenAction = new FullScreenAction();
 
+    @Override
     public boolean setFullscreen(boolean fullscreen) {
+        return setFullscreenImpl(fullscreen, true, null);
+    }
+    
+    @Override
+    public boolean setFullscreen(List<MonitorDevice> monitors) {
+        return setFullscreenImpl(true, false, monitors);
+    }
+    
+    private boolean setFullscreenImpl(boolean fullscreen, boolean useMainMonitor, List<MonitorDevice> monitors) {
         synchronized(fullScreenAction) {
-            if( fullScreenAction.init(fullscreen) ) {               
+            if( fullScreenAction.init(fullscreen, useMainMonitor, monitors) ) {               
                 if(fullScreenAction.fsOn() && isOffscreenInstance(WindowImpl.this, parentWindow)) { 
                     // enable fullscreen on offscreen instance
                     if(null != parentWindow) {
@@ -1821,13 +2015,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             return this.fullscreen;                
         }
     }
-
-    private class ScreenModeListenerImpl implements ScreenModeListener {
+    
+    private class MonitorModeListenerImpl implements MonitorModeListener {
         boolean animatorPaused = false;
 
-        public void screenModeChangeNotify(ScreenMode sm) {
+        public void monitorModeChangeNotify(MonitorEvent me) {
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window.screenModeChangeNotify: "+sm);
+                System.err.println("Window.monitorModeChangeNotify: "+me);
             }
 
             if(null!=lifecycleHook) {
@@ -1835,9 +2029,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             }
         }
 
-        public void screenModeChanged(ScreenMode sm, boolean success) {
+        public void monitorModeChanged(MonitorEvent me, boolean success) {
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window.screenModeChanged: "+sm+", success: "+success);
+                System.err.println("Window.monitorModeChanged: "+me+", success: "+success);
             }
 
             if(success) {
@@ -1845,10 +2039,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     // Didn't pass above notify method. probably detected screen change after it happened.
                     animatorPaused = lifecycleHook.pauseRenderingAction();
                 }
-                DimensionImmutable screenSize = sm.getMonitorMode().getSurfaceSize().getResolution();
-                if ( getHeight() > screenSize.getHeight()  ||
-                     getWidth() > screenSize.getWidth() ) {
-                    setSize(screenSize.getWidth(), screenSize.getHeight());
+                if( !fullscreen ) {
+                    // Simply move/resize window to fit in virtual screen if required
+                    final RectangleImmutable viewport = screen.getViewport();
+                    if( viewport.getWidth() > 0 && viewport.getHeight() > 0 ) { // failsafe
+                        final RectangleImmutable rect = new Rectangle(getX(), getY(), getWidth(), getHeight());
+                        final RectangleImmutable isect = viewport.intersection(rect);
+                        if ( getHeight() > isect.getHeight()  ||
+                             getWidth() > isect.getWidth() ) {
+                            if(DEBUG_IMPLEMENTATION) {
+                                System.err.println("Window.monitorModeChanged: fit window "+rect+" into screen viewport "+viewport+
+                                                   ", due to minimal intersection "+isect);
+                            }
+                            definePosition(viewport.getX(), viewport.getY()); // set pos for setVisible(..) or createNative(..) - reduce EDT roundtrip
+                            setSize(viewport.getWidth(), viewport.getHeight());
+                        }
+                    }
                 }
             }
 
@@ -1858,7 +2064,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
         }
     }
-    private final ScreenModeListenerImpl screenModeListenerImpl = new ScreenModeListenerImpl();
+    private final MonitorModeListenerImpl monitorModeListenerImpl = new MonitorModeListenerImpl();
 
 
 
@@ -1866,12 +2072,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     // Child Window Management
     // 
 
+    @Override
     public final boolean removeChild(NativeWindow win) {
         synchronized(childWindowsLock) {
             return childWindows.remove(win);
         }
     }
 
+    @Override
     public final boolean addChild(NativeWindow win) {
         if (win == null) {
             return false;
@@ -1897,12 +2105,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     }
 
+    @Override
     public void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
         if(isNativeValid()) {
-            ((DisplayImpl)getScreen().getDisplay()).enqueueEvent(wait, event);
+            ((DisplayImpl)screen.getDisplay()).enqueueEvent(wait, event);
         }
     }
 
+    @Override
     public boolean consumeEvent(NEWTEvent e) {
         switch(e.getEventType()) {
             // special repaint treatment
@@ -1914,7 +2124,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                         repaintQueued=true;
                         final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen();
                         if(DEBUG_IMPLEMENTATION) {
-                            System.err.println("Window.consumeEvent: "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
+                            System.err.println("Window.consumeEvent: REPAINT "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
                             // Thread.dumpStack();
                         }                                                
                         return discardTO; // discardTO:=true -> consumed
@@ -1930,7 +2140,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 if( null != windowLock.getOwner() ) {
                     final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen();
                     if(DEBUG_IMPLEMENTATION) {
-                        System.err.println("Window.consumeEvent: "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
+                        System.err.println("Window.consumeEvent: RESIZED "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
                         // Thread.dumpStack();
                     }
                     return discardTO; // discardTO:=true -> consumed
@@ -1954,18 +2164,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     //
     // SurfaceUpdatedListener Support
     //
+    @Override
     public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
         surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
     }
 
+    @Override
     public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
         surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
     }
 
+    @Override
     public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
         surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
     }
 
+    @Override
     public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
         surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
     }
@@ -1973,20 +2187,31 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     //
     // MouseListener/Event Support
     //
-    public void sendMouseEvent(int eventType, int modifiers,
-                               int x, int y, int button, int rotation) {
+    public final void sendMouseEvent(short eventType, int modifiers,
+                                     int x, int y, short button, float rotation) {
         doMouseEvent(false, false, eventType, modifiers, x, y, button, rotation);
     }
-    public void enqueueMouseEvent(boolean wait, int eventType, int modifiers,
-                                  int x, int y, int button, int rotation) {
+    public final void enqueueMouseEvent(boolean wait, short eventType, int modifiers,
+                                        int x, int y, short button, float rotation) {
         doMouseEvent(true, wait, eventType, modifiers, x, y, button, rotation);
     }
-    
-    protected void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers,
-                                int x, int y, int button, int rotation) {
-        if(eventType == MouseEvent.EVENT_MOUSE_ENTERED ||            
-           eventType == MouseEvent.EVENT_MOUSE_EXITED) {
-            if(eventType == MouseEvent.EVENT_MOUSE_EXITED && x==-1 && y==-1) {
+    protected final void doMouseEvent(boolean enqueue, boolean wait, short eventType, int modifiers,
+                                      int x, int y, short button, float rotation) {
+        this.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
+    }
+    /**
+    public final void sendMouseEvent(short eventType, int modifiers,
+                                     int x, int y, short button, float[] rotationXYZ, float rotationScale) {
+        doMouseEvent(false, false, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
+    }
+    public final void enqueueMouseEvent(boolean wait, short eventType, int modifiers,
+                                        int x, int y, short button, float[] rotationXYZ, float rotationScale) {
+        doMouseEvent(true, wait, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
+    } */
+    protected void doMouseEvent(boolean enqueue, boolean wait, short eventType, int modifiers,
+                                int x, int y, short button, float[] rotationXYZ, float rotationScale) {
+        if( eventType == MouseEvent.EVENT_MOUSE_ENTERED || eventType == MouseEvent.EVENT_MOUSE_EXITED ) {
+            if( eventType == MouseEvent.EVENT_MOUSE_EXITED && x==-1 && y==-1 ) {
                 x = lastMousePosition.getX();
                 y = lastMousePosition.getY();
             }
@@ -1994,26 +2219,32 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             x = Math.min(Math.max(x,  0), getWidth()-1);
             y = Math.min(Math.max(y,  0), getHeight()-1);
             mouseInWindow = eventType == MouseEvent.EVENT_MOUSE_ENTERED;
-            lastMousePressed=0;   // clear state
-            mouseButtonPressed=0; // clear state
+            // clear states
+            lastMousePressed = 0;
+            lastMouseClickCount = (short)0; 
+            mouseButtonPressed = 0;
+            mouseButtonModMask = 0;
         }
-        if(x<0||y<0||x>=getWidth()||y>=getHeight()) {
+        if( x < 0 || y < 0 || x >= getWidth() || y >= getHeight() ) {
             return; // .. invalid ..
         }
         if(DEBUG_MOUSE_EVENT) {
             System.err.println("doMouseEvent: enqueue "+enqueue+", wait "+wait+", "+MouseEvent.getEventTypeString(eventType)+
                                ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+lastMousePosition);
         }
-        long when = System.currentTimeMillis();
+        final long when = System.currentTimeMillis();
         MouseEvent eEntered = null;
         if(eventType == MouseEvent.EVENT_MOUSE_MOVED) {
             if(!mouseInWindow) {
                 mouseInWindow = true;
                 eEntered = new MouseEvent(MouseEvent.EVENT_MOUSE_ENTERED, this, when,
-                                          modifiers, x, y, lastMouseClickCount, button, 0);
-                lastMousePressed=0;   // clear state
-                mouseButtonPressed=0; // clear state
-            } else if(lastMousePosition.getX() == x && lastMousePosition.getY()==y) { 
+                                          modifiers, x, y, (short)0, (short)0, rotationXYZ, rotationScale);
+                // clear states
+                lastMousePressed = 0;
+                lastMouseClickCount = (short)0; 
+                mouseButtonPressed = 0;
+                mouseButtonModMask = 0;
+            } else if( lastMousePosition.getX() == x && lastMousePosition.getY()==y ) { 
                 if(DEBUG_MOUSE_EVENT) {
                     System.err.println("doMouseEvent: skip EVENT_MOUSE_MOVED w/ same position: "+lastMousePosition);
                 }
@@ -2025,61 +2256,63 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         if( 0 > button || button > MouseEvent.BUTTON_NUMBER ) {
             throw new NativeWindowException("Invalid mouse button number" + button);
         }
-        // Fixes Bug 571: X11 behavior, where the PRESSED button is not included in the native mask.
-        modifiers |= InputEvent.getButtonMask(button);
+        modifiers |= InputEvent.getButtonMask(button); // Always add current button to modifier mask (Bug 571)
+        modifiers |= mouseButtonModMask; // Always add currently pressed mouse buttons to modifier mask
 
         MouseEvent eClicked = null;
         MouseEvent e = null;
 
-        if(isPointerConfined()) {
+        if( isPointerConfined() ) {
             modifiers |= InputEvent.CONFINED_MASK;
         }
-        if(!isPointerVisible()) {
+        if( !isPointerVisible() ) {
             modifiers |= InputEvent.INVISIBLE_MASK;
         }
         
-        if(MouseEvent.EVENT_MOUSE_PRESSED==eventType) {
-            if(when-lastMousePressed<MouseEvent.getClickTimeout()) {
+        if( MouseEvent.EVENT_MOUSE_PRESSED == eventType ) {
+            if( when - lastMousePressed < MouseEvent.getClickTimeout() ) {
                 lastMouseClickCount++;
             } else {
-                lastMouseClickCount=1;
+                lastMouseClickCount=(short)1;
             }
-            lastMousePressed=when;
-            mouseButtonPressed=button;
+            lastMousePressed = when;
+            mouseButtonPressed = button;
+            mouseButtonModMask |= MouseEvent.getButtonMask(button);
             e = new MouseEvent(eventType, this, when,
-                               modifiers, x, y, lastMouseClickCount, button, 0);
-        } else if(MouseEvent.EVENT_MOUSE_RELEASED==eventType) {
+                               modifiers, x, y, lastMouseClickCount, button, rotationXYZ, rotationScale);
+        } else if( MouseEvent.EVENT_MOUSE_RELEASED == eventType ) {
             e = new MouseEvent(eventType, this, when,
-                               modifiers, x, y, lastMouseClickCount, button, 0);
-            if(when-lastMousePressed<MouseEvent.getClickTimeout()) {
+                               modifiers, x, y, lastMouseClickCount, button, rotationXYZ, rotationScale);
+            if( when - lastMousePressed < MouseEvent.getClickTimeout() ) {
                 eClicked = new MouseEvent(MouseEvent.EVENT_MOUSE_CLICKED, this, when,
-                                          modifiers, x, y, lastMouseClickCount, button, 0);
+                                          modifiers, x, y, lastMouseClickCount, button, rotationXYZ, rotationScale);
             } else {
-                lastMouseClickCount=0;
-                lastMousePressed=0;
+                lastMouseClickCount = (short)0;
+                lastMousePressed = 0;
             }
-            mouseButtonPressed=0;
-        } else if(MouseEvent.EVENT_MOUSE_MOVED==eventType) {
-            if (mouseButtonPressed>0) {
+            mouseButtonPressed = 0;
+            mouseButtonModMask &= ~MouseEvent.getButtonMask(button);
+        } else if( MouseEvent.EVENT_MOUSE_MOVED == eventType ) {
+            if ( mouseButtonPressed > 0 ) {
                 e = new MouseEvent(MouseEvent.EVENT_MOUSE_DRAGGED, this, when,
-                                   modifiers, x, y, 1, mouseButtonPressed, 0);
+                                   modifiers, x, y, (short)1, mouseButtonPressed, rotationXYZ, rotationScale);
             } else {
                 e = new MouseEvent(eventType, this, when,
-                                   modifiers, x, y, 0, button, 0);
+                                   modifiers, x, y, (short)0, button, rotationXYZ, rotationScale);
             }
-        } else if(MouseEvent.EVENT_MOUSE_WHEEL_MOVED==eventType) {
-            e = new MouseEvent(eventType, this, when, modifiers, x, y, 0, button, rotation);
+        } else if( MouseEvent.EVENT_MOUSE_WHEEL_MOVED == eventType ) {
+            e = new MouseEvent(eventType, this, when, modifiers, x, y, (short)0, button, rotationXYZ, rotationScale);
         } else {
-            e = new MouseEvent(eventType, this, when, modifiers, x, y, 0, button, 0);
+            e = new MouseEvent(eventType, this, when, modifiers, x, y, (short)0, button, rotationXYZ, rotationScale);
         }
-        if(null!=eEntered) {
+        if( null != eEntered ) {
             if(DEBUG_MOUSE_EVENT) {
                 System.err.println("doMouseEvent: synthesized MOUSE_ENTERED event: "+eEntered);
             }
             doEvent(enqueue, wait, eEntered);
         }
         doEvent(enqueue, wait, e); // actual mouse event
-        if(null!=eClicked) {
+        if( null != eClicked ) {
             if(DEBUG_MOUSE_EVENT) {
                 System.err.println("doMouseEvent: synthesized MOUSE_CLICKED event: "+eClicked);
             }
@@ -2087,11 +2320,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     }
 
-
+    @Override
     public void addMouseListener(MouseListener l) {
         addMouseListener(-1, l);
     }
 
+    @Override
     public void addMouseListener(int index, MouseListener l) {
         if(l == null) {
             return;
@@ -2105,6 +2339,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         mouseListeners = clonedListeners;
     }
 
+    @Override
     public void removeMouseListener(MouseListener l) {
         if (l == null) {
             return;
@@ -2115,6 +2350,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         mouseListeners = clonedListeners;
     }
 
+    @Override
     public MouseListener getMouseListener(int index) {
         @SuppressWarnings("unchecked")
         ArrayList<MouseListener> clonedListeners = (ArrayList<MouseListener>) mouseListeners.clone();
@@ -2124,6 +2360,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         return clonedListeners.get(index);
     }
 
+    @Override
     public MouseListener[] getMouseListeners() {
         return mouseListeners.toArray(new MouseListener[mouseListeners.size()]);
     }
@@ -2132,8 +2369,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         if(DEBUG_MOUSE_EVENT) {
             System.err.println("consumeMouseEvent: event:         "+e);
         }
-        boolean consumed = false;
-        for(int i = 0; !consumed && i < mouseListeners.size(); i++ ) {
+        for(int i = 0; !e.isConsumed() && i < mouseListeners.size(); i++ ) {
             MouseListener l = mouseListeners.get(i);
             switch(e.getEventType()) {
                 case MouseEvent.EVENT_MOUSE_CLICKED:
@@ -2163,68 +2399,78 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 default:
                     throw new NativeWindowException("Unexpected mouse event type " + e.getEventType());
             }
-            consumed = InputEvent.consumedTag == e.getAttachment();
         }
     }
 
     //
     // KeyListener/Event Support
     //
-    protected IntBitfield keyPressedState = new IntBitfield(KeyEvent.VK_CONTEXT_MENU+1);
-    protected IntBitfield keyRepeatState = new IntBitfield(KeyEvent.VK_CONTEXT_MENU+1);
+    private static final int keyTrackingRange = 255;
+    private final IntBitfield keyPressedState = new IntBitfield( keyTrackingRange + 1 );
+    
+    protected final boolean isKeyCodeTracked(final short keyCode) {
+        return ( 0xFFFF & (int)keyCode ) <= keyTrackingRange;
+    }
     
     /**
-     * @param keyCode
-     * @return 1 if pressed, 0 if not pressed, -1 if not handled. 
+     * @param keyCode the keyCode to set pressed state
+     * @param pressed true if pressed, otherwise false
+     * @return the previus pressed value 
      */
-    protected final int isKeyPressed(int keyCode) { 
-        if( 0 <= keyCode && keyCode < keyPressedState.capacity() ) {
-            return keyPressedState.get(keyCode) ? 1 : 0;
+    protected final boolean setKeyPressed(short keyCode, boolean pressed) {
+        final int v = 0xFFFF & (int)keyCode;
+        if( v <= keyTrackingRange ) {
+            return keyPressedState.put(v, pressed);
         }
-        return -1;
+        return false;
     }
     /**
-     * @param keyCode
-     * @return 1 if pressed, 0 if not pressed, -1 if not handled. 
+     * @param keyCode the keyCode to test pressed state
+     * @return true if pressed, otherwise false 
      */
-    protected final int isKeyInAutoRepeat(int keyCode) { 
-        if( 0 <= keyCode && keyCode < keyRepeatState.capacity() ) {
-            return keyRepeatState.get(keyCode) ? 1 : 0;
+    protected final boolean isKeyPressed(short keyCode) {
+        final int v = 0xFFFF & (int)keyCode;
+        if( v <= keyTrackingRange ) {
+            return keyPressedState.get(v);
         }
-        return -1;
-    }
-    protected final boolean isKeyCodeTracked(int keyCode) { 
-        return 0 <= keyCode && keyCode < keyRepeatState.capacity();
+        return false;
     }
         
-    public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
-        consumeKeyEvent(new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) );
+    public void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+        // Always add currently pressed mouse buttons to modifier mask
+        consumeKeyEvent( KeyEvent.create(eventType, this, System.currentTimeMillis(), modifiers | mouseButtonModMask, keyCode, keySym, keyChar) );
     }
 
-    public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
-        enqueueEvent(wait, new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) );
+    public void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+        // Always add currently pressed mouse buttons to modifier mask
+        enqueueEvent(wait, KeyEvent.create(eventType, this, System.currentTimeMillis(), modifiers | mouseButtonModMask, keyCode, keySym, keyChar) );
     }
-
-    public void addKeyListener(KeyListener l) {
-        addKeyListener(-1, l);
-    }
-
+    
+    @Override
     public final void setKeyboardVisible(boolean visible) {
         if(isNativeValid()) {
             // We don't skip the impl. if it seems that there is no state change,
             // since we cannot assume the impl. reliably gives us it's current state. 
-            final boolean n = setKeyboardVisibleImpl(visible);
+            final boolean ok = setKeyboardVisibleImpl(visible);
             if(DEBUG_IMPLEMENTATION || DEBUG_KEY_EVENT) {
-                System.err.println("setKeyboardVisible(native): visible "+keyboardVisible+" -> "+visible +" -> "+n);
+                System.err.println("setKeyboardVisible(native): visible "+keyboardVisible+" -- op[visible:"+visible +", ok "+ok+"] -> "+(visible && ok));
             }
-            keyboardVisible = n;
+            keyboardVisibilityChanged( visible && ok );
         } else {
-            keyboardVisible = visible; // earmark for creation
+            keyboardVisibilityChanged( visible ); // earmark for creation
         }
     }
+    @Override
     public final boolean isKeyboardVisible() {
         return keyboardVisible;
-    }    
+    }
+    /** 
+     * Returns <code>true</code> if operation was successful, otherwise <code>false</code>.
+     * <p>
+     * We assume that a failed invisible operation is due to an already invisible keyboard,
+     * hence even if an invisible operation failed, the keyboard is considered invisible!  
+     * </p> 
+     */ 
     protected boolean setKeyboardVisibleImpl(boolean visible) {
         return false; // nop
     }
@@ -2239,6 +2485,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
     protected boolean keyboardVisible = false;
     
+    @Override
+    public void addKeyListener(KeyListener l) {
+        addKeyListener(-1, l);
+    }
+
+    @Override
     public void addKeyListener(int index, KeyListener l) {
         if(l == null) {
             return;
@@ -2252,6 +2504,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         keyListeners = clonedListeners;
     }
 
+    @Override
     public void removeKeyListener(KeyListener l) {
         if (l == null) {
             return;
@@ -2262,6 +2515,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         keyListeners = clonedListeners;
     }
 
+    @Override
     public KeyListener getKeyListener(int index) {
         @SuppressWarnings("unchecked")
         ArrayList<KeyListener> clonedListeners = (ArrayList<KeyListener>) keyListeners.clone();
@@ -2271,6 +2525,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         return clonedListeners.get(index);
     }
 
+    @Override
     public KeyListener[] getKeyListeners() {
         return keyListeners.toArray(new KeyListener[keyListeners.size()]);
     }
@@ -2283,48 +2538,48 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             case KeyEvent.EVENT_KEY_RELEASED:
                 l.keyReleased(e);
                 break;
-            case KeyEvent.EVENT_KEY_TYPED:
-                l.keyTyped(e);
-                break;
             default:
                 throw new NativeWindowException("Unexpected key event type " + e.getEventType());
         }
-        return InputEvent.consumedTag == e.getAttachment();
+        return e.isConsumed();
     }
     
     protected void consumeKeyEvent(KeyEvent e) {
-        boolean consumed;
-        if(null != keyboardFocusHandler) {
-            consumed = propagateKeyEvent(e, keyboardFocusHandler);
+        boolean consumedE = false;
+        if( null != keyboardFocusHandler && !e.isAutoRepeat() ) {
+            consumedE = propagateKeyEvent(e, keyboardFocusHandler);
             if(DEBUG_KEY_EVENT) {
-                System.err.println("consumeKeyEvent: "+e+", keyboardFocusHandler consumed: "+consumed);
+                System.err.println("consumeKeyEvent(kfh): "+e+", keyboardFocusHandler consumed: "+consumedE);
             }
-        } else {
-            consumed = false;
-            if(DEBUG_KEY_EVENT) {
-                System.err.println("consumeKeyEvent: "+e);
+        }
+        if(DEBUG_KEY_EVENT) {
+            if( !consumedE ) {
+                System.err.println("consumeKeyEvent(usr): "+e);
             }
         }
-        for(int i = 0; !consumed && i < keyListeners.size(); i++ ) {
-            consumed = propagateKeyEvent(e, keyListeners.get(i));
+        for(int i = 0; !consumedE && i < keyListeners.size(); i++ ) {
+            consumedE = propagateKeyEvent(e, keyListeners.get(i));
         }
     }
 
     //
     // WindowListener/Event Support
     //
+    @Override
     public void sendWindowEvent(int eventType) {
-        consumeWindowEvent( new WindowEvent(eventType, this, System.currentTimeMillis()) );
+        consumeWindowEvent( new WindowEvent((short)eventType, this, System.currentTimeMillis()) ); // FIXME
     }
 
     public void enqueueWindowEvent(boolean wait, int eventType) {
-        enqueueEvent( wait, new WindowEvent(eventType, this, System.currentTimeMillis()) );
+        enqueueEvent( wait, new WindowEvent((short)eventType, this, System.currentTimeMillis()) ); // FIXME
     }
 
+    @Override
     public void addWindowListener(WindowListener l) {
         addWindowListener(-1, l);
     }
 
+    @Override
     public void addWindowListener(int index, WindowListener l) 
         throws IndexOutOfBoundsException
     {
@@ -2340,6 +2595,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         windowListeners = clonedListeners;
     }
 
+    @Override
     public final void removeWindowListener(WindowListener l) {
         if (l == null) {
             return;
@@ -2350,6 +2606,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         windowListeners = clonedListeners;
     }
 
+    @Override
     public WindowListener getWindowListener(int index) {
         @SuppressWarnings("unchecked")
         ArrayList<WindowListener> clonedListeners = (ArrayList<WindowListener>) windowListeners.clone();
@@ -2359,6 +2616,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         return clonedListeners.get(index);
     }
 
+    @Override
     public WindowListener[] getWindowListeners() {
         return windowListeners.toArray(new WindowListener[windowListeners.size()]);
     }
@@ -2367,7 +2625,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         if(DEBUG_IMPLEMENTATION) {
             System.err.println("consumeWindowEvent: "+e+", visible "+isVisible()+" "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
         }
-        for(int i = 0; i < windowListeners.size(); i++ ) {
+        for(int i = 0; !e.isConsumed() && i < windowListeners.size(); i++ ) {
             WindowListener l = windowListeners.get(i);
             switch(e.getEventType()) {
                 case WindowEvent.EVENT_WINDOW_RESIZED:
@@ -2425,15 +2683,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     }
 
-    private boolean waitForVisible(boolean visible, boolean failFast) {
+    /** Returns -1 if failed, otherwise remaining time until {@link #TIMEOUT_NATIVEWINDOW}, maybe zero. */
+    private long waitForVisible(boolean visible, boolean failFast) {
         return waitForVisible(visible, failFast, TIMEOUT_NATIVEWINDOW);
     }
 
-    private boolean waitForVisible(boolean visible, boolean failFast, long timeOut) {
-        DisplayImpl display = (DisplayImpl) screen.getDisplay();
-        for(long sleep = timeOut; 0<sleep && this.visible != visible; sleep-=10 ) {
-            display.dispatchMessagesNative(); // status up2date
+    /** Returns -1 if failed, otherwise remaining time until <code>timeOut</code>, maybe zero. */
+    private long waitForVisible(boolean visible, boolean failFast, long timeOut) {
+        final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+        display.dispatchMessagesNative(); // status up2date
+        long remaining;
+        for(remaining = timeOut; 0<remaining && this.visible != visible; remaining-=10 ) {
             try { Thread.sleep(10); } catch (InterruptedException ie) {}
+            display.dispatchMessagesNative(); // status up2date
         }
         if(this.visible != visible) {
             final String msg = "Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+this.visible; 
@@ -2441,9 +2703,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 throw new NativeWindowException(msg);
             } else if (DEBUG_IMPLEMENTATION) {
                 System.err.println(msg);
+                Thread.dumpStack();
             }
+            return -1;
+        } else if( 0 < remaining ){
+            return remaining;
+        } else {
+            return 0;
         }
-        return this.visible == visible;
     }
 
     /** Triggered by implementation's WM events to update the client-area size w/o insets/decorations. */ 
@@ -2467,18 +2734,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
     
     private boolean waitForSize(int w, int h, boolean failFast, long timeOut) {
-        DisplayImpl display = (DisplayImpl) screen.getDisplay();
-        boolean reached = false;
-        for(long sleep = timeOut; !reached && 0<sleep; sleep-=10 ) {
-            if( w==getWidth() && h==getHeight() ) {
-                // reached pos/size
-                reached = true;
-            } else {
-                display.dispatchMessagesNative(); // status up2date
-                try { Thread.sleep(10); } catch (InterruptedException ie) {}
-            }
+        final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+        display.dispatchMessagesNative(); // status up2date
+        long sleep;
+        for(sleep = timeOut; 0<sleep && w!=getWidth() && h!=getHeight(); sleep-=10 ) {
+            try { Thread.sleep(10); } catch (InterruptedException ie) {}
+            display.dispatchMessagesNative(); // status up2date
         }
-        if(!reached) {
+        if(0 >= sleep) {
             final String msg = "Size/Pos not reached as requested within "+timeOut+"ms : requested "+w+"x"+h+", is "+getWidth()+"x"+getHeight();
             if(failFast) {
                 throw new NativeWindowException(msg);
@@ -2486,8 +2749,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 System.err.println(msg);
                 Thread.dumpStack();
             }
+            return false;
+        } else {
+            return true;
         }
-        return reached;
     }
     
     /** Triggered by implementation's WM events to update the position. */ 
@@ -2508,6 +2773,47 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
 
     /**
+     * Wait until position is reached within tolerances, either auto-position or custom position.
+     * <p>
+     * Since WM may not obey our positional request exactly, we allow a tolerance of 2 times insets[left/top], or 64 pixels, whatever is greater.
+     * </p>
+     */
+    private boolean waitForPosition(boolean useCustomPosition, int x, int y, long timeOut) {
+        final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+        final int maxDX, maxDY;
+        {
+            final InsetsImmutable insets = getInsets();
+            maxDX = Math.max(64, insets.getLeftWidth() * 2);
+            maxDY = Math.max(64, insets.getTopHeight() * 2);
+        }
+        long remaining = timeOut;
+        boolean ok;
+        do {
+            if( useCustomPosition ) {
+                ok = Math.abs(x - getX()) <= maxDX && Math.abs(y - getY()) <= maxDY ;
+            } else {
+                ok = !autoPosition;
+            }
+            if( !ok ) {
+                try { Thread.sleep(10); } catch (InterruptedException ie) {}
+                display.dispatchMessagesNative(); // status up2date
+                remaining-=10;
+            }
+        } while ( 0<remaining && !ok );
+        if (DEBUG_IMPLEMENTATION) {
+            if( !ok ) {
+                if( useCustomPosition ) {
+                    System.err.println("Custom position "+x+"/"+y+" not reached within timeout, has "+getX()+"/"+getY()+", remaining "+remaining);
+                } else {
+                    System.err.println("Auto position not reached within timeout, has "+getX()+"/"+getY()+", autoPosition "+autoPosition+", remaining "+remaining);
+                }
+                Thread.dumpStack();
+            }
+        }
+        return ok;
+    }
+    
+    /**
      * Triggered by implementation's WM events to update the insets. 
      * 
      * @see #getInsets()
@@ -2534,35 +2840,56 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
     
     /**
-     * Triggered by implementation's WM events or programmatically
+     * Triggered by implementation's WM events or programmatic while respecting {@link #getDefaultCloseOperation()}.
      * 
      * @param force if true, overrides {@link #setDefaultCloseOperation(WindowClosingMode)} with {@link WindowClosingProtocol#DISPOSE_ON_CLOSE}
      *              and hence force destruction. Otherwise is follows the user settings.
      * @return true if this window is no more valid and hence has been destroyed, otherwise false.
      */
-    protected boolean windowDestroyNotify(boolean force) {
+    public boolean windowDestroyNotify(boolean force) {
+        final WindowClosingMode defMode = getDefaultCloseOperation();
+        final WindowClosingMode mode = force ? WindowClosingMode.DISPOSE_ON_CLOSE : defMode;
         if(DEBUG_IMPLEMENTATION) {
-            System.err.println("Window.windowDestroyNotify(force: "+force+") START "+getThreadName()+": "+this);
-        }
-        if(force) {
-            setDefaultCloseOperation(WindowClosingMode.DISPOSE_ON_CLOSE);
-        }
-
-        // send synced destroy notifications
-        enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
-
-        if(handleDestroyNotify && WindowClosingMode.DISPOSE_ON_CLOSE == getDefaultCloseOperation()) {
-            destroy();
+            System.err.println("Window.windowDestroyNotify(isNativeValid: "+isNativeValid()+", force: "+force+", mode "+defMode+" -> "+mode+") "+getThreadName()+": "+this);
+            // Thread.dumpStack();
         }
         
-        final boolean destroyed = !isNativeValid();
+        final boolean destroyed;
+        
+        if( isNativeValid() ) {
+            if( WindowClosingMode.DISPOSE_ON_CLOSE == mode ) {
+                if(force) {
+                    setDefaultCloseOperation(mode);
+                }
+                try {
+                    if( null == windowDestroyNotifyAction ) {
+                        destroy();
+                    } else {
+                        windowDestroyNotifyAction.run();
+                    }
+                } finally {
+                    if(force) {
+                        setDefaultCloseOperation(defMode);
+                    }
+                }
+            } else {
+                // send synced destroy notifications
+                sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+            }
+            
+            destroyed = !isNativeValid();
+        } else {
+            destroyed = true;
+        }
 
         if(DEBUG_IMPLEMENTATION) {
-            System.err.println("Window.windowDestroyNotify(force: "+force+") END "+getThreadName()+": destroyed "+destroyed+", "+this);
-        }
+            System.err.println("Window.windowDestroyNotify(isNativeValid: "+isNativeValid()+", force: "+force+", mode "+mode+") END "+getThreadName()+": destroyed "+destroyed+", "+this);
+        }        
+        
         return destroyed;
     }
 
+    @Override
     public void windowRepaint(int x, int y, int width, int height) {
         windowRepaint(false, x, y, width, height); 
     }
diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java b/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java
index cb70da1..1e15070 100644
--- a/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java
+++ b/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java
@@ -28,130 +28,633 @@
  
 package jogamp.newt.awt.event;
 
-import com.jogamp.common.util.IntIntHashMap;
-import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.MouseEvent;
 
+/**
+ *
+ * <a name="AWTEventModifierMapping"><h5>AWT Event Modifier Mapping</h5></a> 
+ * <pre>
+    Modifier       AWT Constant                     AWT Bit  AWT Ex  NEWT Constant              NEWT Bit
+    -------------  -------------------------------  -------  ------  -------------------------  --------
+    Shift          Event.SHIFT_MASK                 0                
+    Ctrl           Event.CTRL_MASK                  1                
+    Meta           Event.META_MASK                  2                
+    Alt            Event.ALT_MASK                   3               
+    Button1        InputEvent.BUTTON1_MASK          4
+    Button2        InputEvent.BUTTON2_MASK          3
+    Button3        InputEvent.BUTTON3_MASK          2
+    Shift Down     InputEvent.SHIFT_DOWN_MASK       6        *       InputEvent.SHIFT_MASK      0
+    Ctrl Down      InputEvent.CTRL_DOWN_MASK        7        *       InputEvent.CTRL_MASK       1
+    Meta Down      InputEvent.META_DOWN_MASK        8        *       InputEvent.META_MASK       2
+    Alt Down       InputEvent.ALT_DOWN_MASK         9        *       InputEvent.ALT_MASK        3
+    Button1 Down   InputEvent.BUTTON1_DOWN_MASK     10       *       InputEvent.BUTTON1_MASK    5
+    Button2 Down   InputEvent.BUTTON2_DOWN_MASK     11       *       InputEvent.BUTTON2_MASK    6
+    Button3 Down   InputEvent.BUTTON3_DOWN_MASK     12       *       InputEvent.BUTTON3_MASK    7
+    AltGraph Down  InputEvent.ALT_GRAPH_DOWN_MASK   13       *       InputEvent.ALT_GRAPH_MASK  4
+    Button4 Down   --                               14       *       InputEvent.BUTTON4_MASK    8
+    Button5 Down   --                               15       *       InputEvent.BUTTON5_MASK    9
+    Button6 Down   --                               16       *       InputEvent.BUTTON6_MASK    10
+    Button7 Down   --                               17       *       InputEvent.BUTTON7_MASK    11
+    Button8 Down   --                               18       *       InputEvent.BUTTON8_MASK    12
+    Button9 Down   --                               19       *       InputEvent.BUTTON9_MASK    13
+    Button10 Down  --                               20       *                                  14
+    Button11 Down  --                               21       *                                  15
+    Button12 Down  --                               22       *                                  16
+    Button13 Down  --                               23       *                                  17
+    Button14 Down  --                               24       *                                  18
+    Button15 Down  --                               25       *                                  19
+    Button16 Down  --                               26       *       InputEvent.BUTTONLAST_MASK 20
+    Button17 Down  --                               27       *
+    Button18 Down  --                               28       *
+    Button19 Down  --                               29       *
+    Button20 Down  --                               30       *
+    Autorepeat     --                               -                InputEvent.AUTOREPEAT_MASK 29
+    Confined       --                               -                InputEvent.CONFINED_MASK   30
+    Invisible      --                               -                InputEvent.INVISIBLE_MASK  31
+ * </pre>
+ *
+ */
 public class AWTNewtEventFactory {
 
-    protected static final IntIntHashMap eventTypeAWT2NEWT;
+    /** zero-based AWT button mask array filled by {@link #getAWTButtonDownMask(int)}, allowing fast lookup. */
+    private static int awtButtonDownMasks[] ;
 
     static {
-        IntIntHashMap map = new IntIntHashMap();
-        map.setKeyNotFoundValue(0xFFFFFFFF);
-        // n/a map.put(java.awt.event.WindowEvent.WINDOW_OPENED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_OPENED);
-        map.put(java.awt.event.WindowEvent.WINDOW_CLOSING, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
-        map.put(java.awt.event.WindowEvent.WINDOW_CLOSED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROYED);
-        // n/a map.put(java.awt.event.WindowEvent.WINDOW_ICONIFIED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_ICONIFIED);
-        // n/a map.put(java.awt.event.WindowEvent.WINDOW_DEICONIFIED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DEICONIFIED);
-        map.put(java.awt.event.WindowEvent.WINDOW_ACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
-        map.put(java.awt.event.WindowEvent.WINDOW_GAINED_FOCUS, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
-        map.put(java.awt.event.FocusEvent.FOCUS_GAINED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
-        map.put(java.awt.event.WindowEvent.WINDOW_DEACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
-        map.put(java.awt.event.WindowEvent.WINDOW_LOST_FOCUS, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
-        map.put(java.awt.event.FocusEvent.FOCUS_LOST, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
-        // n/a map.put(java.awt.event.WindowEvent.WINDOW_STATE_CHANGED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_STATE_CHANGED);
-
-        map.put(java.awt.event.ComponentEvent.COMPONENT_MOVED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_MOVED);
-        map.put(java.awt.event.ComponentEvent.COMPONENT_RESIZED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_RESIZED);
-        // n/a map.put(java.awt.event.ComponentEvent.COMPONENT_SHOWN, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_SHOWN);
-        // n/a map.put(java.awt.event.ComponentEvent.COMPONENT_HIDDEN, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_HIDDEN);
-
-        map.put(java.awt.event.MouseEvent.MOUSE_CLICKED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED);
-        map.put(java.awt.event.MouseEvent.MOUSE_PRESSED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED);
-        map.put(java.awt.event.MouseEvent.MOUSE_RELEASED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
-        map.put(java.awt.event.MouseEvent.MOUSE_MOVED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED);
-        map.put(java.awt.event.MouseEvent.MOUSE_ENTERED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED);
-        map.put(java.awt.event.MouseEvent.MOUSE_EXITED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED);
-        map.put(java.awt.event.MouseEvent.MOUSE_DRAGGED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED);
-        map.put(java.awt.event.MouseEvent.MOUSE_WHEEL, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED);
-
-        map.put(java.awt.event.KeyEvent.KEY_PRESSED, com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED);
-        map.put(java.awt.event.KeyEvent.KEY_RELEASED, com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED);
-        map.put(java.awt.event.KeyEvent.KEY_TYPED, com.jogamp.newt.event.KeyEvent.EVENT_KEY_TYPED);
-
-        eventTypeAWT2NEWT = map;
+        // There is an assumption in awtModifiers2Newt(int,int,boolean)
+        // that the awtButtonMasks and newtButtonMasks are peers, i.e.
+        // a given index refers to the same button in each array.
+
+        /* {
+            Method _getMaskForButtonMethod = null;
+            try {
+                _getMaskForButtonMethod = ReflectionUtil.getMethod(java.awt.event.InputEvent.class, "getMaskForButton", int.class);
+            } catch(Throwable t) {}        
+            getMaskForButtonMethod = _getMaskForButtonMethod;
+        } */
+        
+        awtButtonDownMasks = new int[com.jogamp.newt.event.MouseEvent.BUTTON_NUMBER] ; // java.awt.MouseInfo.getNumberOfButtons() ;
+        for (int n = 0 ; n < awtButtonDownMasks.length ; ++n) {
+            awtButtonDownMasks[n] = getAWTButtonDownMaskImpl(n+1);
+        }
     }
 
-    public static final int awtModifiers2Newt(int awtMods, boolean mouseHint) {
+    public static final short eventTypeAWT2NEWT(int awtType) {
+        switch( awtType ) {
+            // n/a case java.awt.event.WindowEvent.WINDOW_OPENED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_OPENED;
+            case java.awt.event.WindowEvent.WINDOW_CLOSING: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY;
+            case java.awt.event.WindowEvent.WINDOW_CLOSED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROYED;
+            // n/a case java.awt.event.WindowEvent.WINDOW_ICONIFIED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_ICONIFIED;
+            // n/a case java.awt.event.WindowEvent.WINDOW_DEICONIFIED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DEICONIFIED;
+            case java.awt.event.WindowEvent.WINDOW_ACTIVATED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+            case java.awt.event.WindowEvent.WINDOW_GAINED_FOCUS: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+            case java.awt.event.FocusEvent.FOCUS_GAINED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+            case java.awt.event.WindowEvent.WINDOW_DEACTIVATED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS;
+            case java.awt.event.WindowEvent.WINDOW_LOST_FOCUS: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS;
+            case java.awt.event.FocusEvent.FOCUS_LOST: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS;
+            // n/a case java.awt.event.WindowEvent.WINDOW_STATE_CHANGED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_STATE_CHANGED;
+    
+            case java.awt.event.ComponentEvent.COMPONENT_MOVED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_MOVED;
+            case java.awt.event.ComponentEvent.COMPONENT_RESIZED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_RESIZED;
+            // n/a case java.awt.event.ComponentEvent.COMPONENT_SHOWN: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_SHOWN;
+            // n/a case java.awt.event.ComponentEvent.COMPONENT_HIDDEN: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_HIDDEN;
+    
+            case java.awt.event.MouseEvent.MOUSE_CLICKED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED;
+            case java.awt.event.MouseEvent.MOUSE_PRESSED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED;
+            case java.awt.event.MouseEvent.MOUSE_RELEASED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED;
+            case java.awt.event.MouseEvent.MOUSE_MOVED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED;
+            case java.awt.event.MouseEvent.MOUSE_ENTERED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED;
+            case java.awt.event.MouseEvent.MOUSE_EXITED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED;
+            case java.awt.event.MouseEvent.MOUSE_DRAGGED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED;
+            case java.awt.event.MouseEvent.MOUSE_WHEEL: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+    
+            case java.awt.event.KeyEvent.KEY_PRESSED: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
+            case java.awt.event.KeyEvent.KEY_RELEASED: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
+        }
+        return (short)0;
+    }
+    
+    private static int getAWTButtonDownMaskImpl(int button) {
+        /**
+         * java.awt.event.InputEvent.getMaskForButton(button);
+         * 
+        if(null != getMaskForButtonMethod) {
+            Object r=null;
+            try {
+                r = getMaskForButtonMethod.invoke(null, new Integer(button));
+            } catch (Throwable t) { }
+            if(null != r) {
+                return ((Integer)r).intValue();
+            }
+        } */
+        final int m;
+        switch(button) {
+            case 0 : m = 0; break;
+            case 1 : m = java.awt.event.InputEvent.BUTTON1_DOWN_MASK; break; // 1<<10
+            case 2 : m = java.awt.event.InputEvent.BUTTON2_DOWN_MASK; break; // 1<<11
+            case 3 : m = java.awt.event.InputEvent.BUTTON3_DOWN_MASK; break; // 1<<12
+            default:
+                if( button <= com.jogamp.newt.event.MouseEvent.BUTTON_NUMBER ) {
+                    m = 1 << ( 10 + button ) ; // b4 = 1<<14, b5 = 1<<15, etc
+                } else {
+                    m = 0;
+                }                
+        }
+        return m;
+    }
+    
+    /**
+     * <p>
+     * See <a href="#AWTEventModifierMapping"> AWT event modifier mapping details</a>.
+     * </p>
+     * 
+     * @param button
+     * @return
+     */
+    public static int getAWTButtonDownMask(int button) {
+        if( 0 < button && button <= awtButtonDownMasks.length ) {
+            return awtButtonDownMasks[button-1];
+        } else {
+            return 0;
+        }        
+    }
+    
+    public static final short awtButton2Newt(int awtButton) {
+        if( 0 < awtButton && awtButton <= com.jogamp.newt.event.MouseEvent.BUTTON_NUMBER ) {
+            return (short)awtButton;
+        } else {
+            return (short)0;
+        }
+    }
+    
+    /**
+     * Converts the specified set of AWT event modifiers and extended event
+     * modifiers to the equivalent NEWT event modifiers.
+     * 
+     * <p>
+     * See <a href="#AWTEventModifierMapping"> AWT event modifier mapping details</a>.
+     * </p>
+     * 
+     * @param awtMods
+     * The AWT event modifiers.
+     * 
+     * @param awtModsEx
+     * The AWT extended event modifiers.
+     * AWT passes mouse button specific bits here and are the preferred way check the mouse button state.
+     */
+    public static final int awtModifiers2Newt(final int awtMods, final int awtModsEx) {
         int newtMods = 0;
+        
+        /** Redundant old modifiers ..
         if ((awtMods & java.awt.event.InputEvent.SHIFT_MASK) != 0)     newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
         if ((awtMods & java.awt.event.InputEvent.CTRL_MASK) != 0)      newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK;
         if ((awtMods & java.awt.event.InputEvent.META_MASK) != 0)      newtMods |= com.jogamp.newt.event.InputEvent.META_MASK;
         if ((awtMods & java.awt.event.InputEvent.ALT_MASK) != 0)       newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
-        if ((awtMods & java.awt.event.InputEvent.ALT_GRAPH_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK;
+        if ((awtMods & java.awt.event.InputEvent.ALT_GRAPH_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK; */
+        
+        if ((awtModsEx & java.awt.event.InputEvent.SHIFT_DOWN_MASK) != 0)     newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+        if ((awtModsEx & java.awt.event.InputEvent.CTRL_DOWN_MASK) != 0)      newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK;
+        if ((awtModsEx & java.awt.event.InputEvent.META_DOWN_MASK) != 0)      newtMods |= com.jogamp.newt.event.InputEvent.META_MASK;
+        if ((awtModsEx & java.awt.event.InputEvent.ALT_DOWN_MASK) != 0)       newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
+        if ((awtModsEx & java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK;
+
+        // The BUTTON1_MASK, BUTTON2_MASK, and BUTTON3_MASK bits are
+        // being ignored intentionally.  The AWT docs say that the
+        // BUTTON1_DOWN_MASK etc bits in the extended modifiers are
+        // the preferred place to check current button state.
+        
+        if( 0 != awtModsEx ) {
+            for (int n = 0 ; n < awtButtonDownMasks.length ; ++n) {
+                if ( (awtModsEx & awtButtonDownMasks[n]) != 0 ) {
+                    newtMods |= com.jogamp.newt.event.InputEvent.getButtonMask(n+1);
+                }
+            }
+        }
+
         return newtMods;
     }
+    
+    public static short awtKeyCode2NewtKeyCode(final int awtKeyCode) {
+        final short defNEWTKeyCode = (short)awtKeyCode;
+        switch (awtKeyCode) {
+            case java.awt.event.KeyEvent.VK_HOME          : return com.jogamp.newt.event.KeyEvent.VK_HOME;
+            case java.awt.event.KeyEvent.VK_END           : return com.jogamp.newt.event.KeyEvent.VK_END;
+            case java.awt.event.KeyEvent.VK_FINAL         : return com.jogamp.newt.event.KeyEvent.VK_FINAL;
+            case java.awt.event.KeyEvent.VK_PRINTSCREEN   : return com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN;
+            case java.awt.event.KeyEvent.VK_BACK_SPACE    : return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
+            case java.awt.event.KeyEvent.VK_TAB           : return com.jogamp.newt.event.KeyEvent.VK_TAB;
+            case java.awt.event.KeyEvent.VK_ENTER         : return com.jogamp.newt.event.KeyEvent.VK_ENTER;
+            case java.awt.event.KeyEvent.VK_PAGE_DOWN     : return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN;
+            case java.awt.event.KeyEvent.VK_CLEAR         : return com.jogamp.newt.event.KeyEvent.VK_CLEAR;
+            case java.awt.event.KeyEvent.VK_SHIFT         : return com.jogamp.newt.event.KeyEvent.VK_SHIFT;
+            case java.awt.event.KeyEvent.VK_PAGE_UP       : return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP;
+            case java.awt.event.KeyEvent.VK_CONTROL       : return com.jogamp.newt.event.KeyEvent.VK_CONTROL;
+            case java.awt.event.KeyEvent.VK_ALT           : return com.jogamp.newt.event.KeyEvent.VK_ALT;
+            case java.awt.event.KeyEvent.VK_ALT_GRAPH     : return com.jogamp.newt.event.KeyEvent.VK_ALT_GRAPH;
+            case java.awt.event.KeyEvent.VK_CAPS_LOCK     : return com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK;
+            case java.awt.event.KeyEvent.VK_PAUSE         : return com.jogamp.newt.event.KeyEvent.VK_PAUSE;
+            case java.awt.event.KeyEvent.VK_SCROLL_LOCK   : return com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK;
+            case java.awt.event.KeyEvent.VK_CANCEL        : return com.jogamp.newt.event.KeyEvent.VK_CANCEL;
+            case java.awt.event.KeyEvent.VK_INSERT        : return com.jogamp.newt.event.KeyEvent.VK_INSERT;
+            case java.awt.event.KeyEvent.VK_ESCAPE        : return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
+            case java.awt.event.KeyEvent.VK_CONVERT       : return com.jogamp.newt.event.KeyEvent.VK_CONVERT;
+            case java.awt.event.KeyEvent.VK_NONCONVERT    : return com.jogamp.newt.event.KeyEvent.VK_NONCONVERT;
+            case java.awt.event.KeyEvent.VK_ACCEPT        : return com.jogamp.newt.event.KeyEvent.VK_ACCEPT;
+            case java.awt.event.KeyEvent.VK_MODECHANGE    : return com.jogamp.newt.event.KeyEvent.VK_MODECHANGE;
+            case java.awt.event.KeyEvent.VK_SPACE         : return com.jogamp.newt.event.KeyEvent.VK_SPACE;
+            case java.awt.event.KeyEvent.VK_EXCLAMATION_MARK: return com.jogamp.newt.event.KeyEvent.VK_EXCLAMATION_MARK;
+            case java.awt.event.KeyEvent.VK_QUOTEDBL      : return com.jogamp.newt.event.KeyEvent.VK_QUOTEDBL;
+            case java.awt.event.KeyEvent.VK_NUMBER_SIGN   : return com.jogamp.newt.event.KeyEvent.VK_NUMBER_SIGN;
+            case java.awt.event.KeyEvent.VK_DOLLAR        : return com.jogamp.newt.event.KeyEvent.VK_DOLLAR;
+            // case                         0x25             : return com.jogamp.newt.event.KeyEvent.VK_PERCENT;
+            case java.awt.event.KeyEvent.VK_AMPERSAND     : return com.jogamp.newt.event.KeyEvent.VK_AMPERSAND;
+            case java.awt.event.KeyEvent.VK_QUOTE         : return com.jogamp.newt.event.KeyEvent.VK_QUOTE;
+            case java.awt.event.KeyEvent.VK_LEFT_PARENTHESIS : return com.jogamp.newt.event.KeyEvent.VK_LEFT_PARENTHESIS;
+            case java.awt.event.KeyEvent.VK_RIGHT_PARENTHESIS: return com.jogamp.newt.event.KeyEvent.VK_RIGHT_PARENTHESIS;
+            case java.awt.event.KeyEvent.VK_ASTERISK      : return com.jogamp.newt.event.KeyEvent.VK_ASTERISK;
+            case java.awt.event.KeyEvent.VK_PLUS          : return com.jogamp.newt.event.KeyEvent.VK_PLUS;
+            case java.awt.event.KeyEvent.VK_COMMA         : return com.jogamp.newt.event.KeyEvent.VK_COMMA;
+            case java.awt.event.KeyEvent.VK_MINUS         : return com.jogamp.newt.event.KeyEvent.VK_MINUS;
+            case java.awt.event.KeyEvent.VK_PERIOD        : return com.jogamp.newt.event.KeyEvent.VK_PERIOD;
+            case java.awt.event.KeyEvent.VK_SLASH         : return com.jogamp.newt.event.KeyEvent.VK_SLASH;
+            case java.awt.event.KeyEvent.VK_0             : return com.jogamp.newt.event.KeyEvent.VK_0;
+            case java.awt.event.KeyEvent.VK_1             : return com.jogamp.newt.event.KeyEvent.VK_1;
+            case java.awt.event.KeyEvent.VK_2             : return com.jogamp.newt.event.KeyEvent.VK_2;
+            case java.awt.event.KeyEvent.VK_3             : return com.jogamp.newt.event.KeyEvent.VK_3;
+            case java.awt.event.KeyEvent.VK_4             : return com.jogamp.newt.event.KeyEvent.VK_4;
+            case java.awt.event.KeyEvent.VK_5             : return com.jogamp.newt.event.KeyEvent.VK_5;
+            case java.awt.event.KeyEvent.VK_6             : return com.jogamp.newt.event.KeyEvent.VK_6;
+            case java.awt.event.KeyEvent.VK_7             : return com.jogamp.newt.event.KeyEvent.VK_7;
+            case java.awt.event.KeyEvent.VK_8             : return com.jogamp.newt.event.KeyEvent.VK_8;
+            case java.awt.event.KeyEvent.VK_9             : return com.jogamp.newt.event.KeyEvent.VK_9;
+            case java.awt.event.KeyEvent.VK_COLON         : return com.jogamp.newt.event.KeyEvent.VK_COLON;
+            case java.awt.event.KeyEvent.VK_SEMICOLON     : return com.jogamp.newt.event.KeyEvent.VK_SEMICOLON;
+            case java.awt.event.KeyEvent.VK_LESS          : return com.jogamp.newt.event.KeyEvent.VK_LESS;
+            case java.awt.event.KeyEvent.VK_EQUALS        : return com.jogamp.newt.event.KeyEvent.VK_EQUALS;
+            case java.awt.event.KeyEvent.VK_GREATER       : return com.jogamp.newt.event.KeyEvent.VK_GREATER;
+            case                         0x3f             : return com.jogamp.newt.event.KeyEvent.VK_QUESTIONMARK;
+            case java.awt.event.KeyEvent.VK_AT            : return com.jogamp.newt.event.KeyEvent.VK_AT;
+            case java.awt.event.KeyEvent.VK_A             : return com.jogamp.newt.event.KeyEvent.VK_A;
+            case java.awt.event.KeyEvent.VK_B             : return com.jogamp.newt.event.KeyEvent.VK_B;
+            case java.awt.event.KeyEvent.VK_C             : return com.jogamp.newt.event.KeyEvent.VK_C;
+            case java.awt.event.KeyEvent.VK_D             : return com.jogamp.newt.event.KeyEvent.VK_D;
+            case java.awt.event.KeyEvent.VK_E             : return com.jogamp.newt.event.KeyEvent.VK_E;
+            case java.awt.event.KeyEvent.VK_F             : return com.jogamp.newt.event.KeyEvent.VK_F;
+            case java.awt.event.KeyEvent.VK_G             : return com.jogamp.newt.event.KeyEvent.VK_G;
+            case java.awt.event.KeyEvent.VK_H             : return com.jogamp.newt.event.KeyEvent.VK_H;
+            case java.awt.event.KeyEvent.VK_I             : return com.jogamp.newt.event.KeyEvent.VK_I;
+            case java.awt.event.KeyEvent.VK_J             : return com.jogamp.newt.event.KeyEvent.VK_J;
+            case java.awt.event.KeyEvent.VK_K             : return com.jogamp.newt.event.KeyEvent.VK_K;
+            case java.awt.event.KeyEvent.VK_L             : return com.jogamp.newt.event.KeyEvent.VK_L;
+            case java.awt.event.KeyEvent.VK_M             : return com.jogamp.newt.event.KeyEvent.VK_M;
+            case java.awt.event.KeyEvent.VK_N             : return com.jogamp.newt.event.KeyEvent.VK_N;
+            case java.awt.event.KeyEvent.VK_O             : return com.jogamp.newt.event.KeyEvent.VK_O;
+            case java.awt.event.KeyEvent.VK_P             : return com.jogamp.newt.event.KeyEvent.VK_P;
+            case java.awt.event.KeyEvent.VK_Q             : return com.jogamp.newt.event.KeyEvent.VK_Q;
+            case java.awt.event.KeyEvent.VK_R             : return com.jogamp.newt.event.KeyEvent.VK_R;
+            case java.awt.event.KeyEvent.VK_S             : return com.jogamp.newt.event.KeyEvent.VK_S;
+            case java.awt.event.KeyEvent.VK_T             : return com.jogamp.newt.event.KeyEvent.VK_T;
+            case java.awt.event.KeyEvent.VK_U             : return com.jogamp.newt.event.KeyEvent.VK_U;
+            case java.awt.event.KeyEvent.VK_V             : return com.jogamp.newt.event.KeyEvent.VK_V;
+            case java.awt.event.KeyEvent.VK_W             : return com.jogamp.newt.event.KeyEvent.VK_W;
+            case java.awt.event.KeyEvent.VK_X             : return com.jogamp.newt.event.KeyEvent.VK_X;
+            case java.awt.event.KeyEvent.VK_Y             : return com.jogamp.newt.event.KeyEvent.VK_Y;
+            case java.awt.event.KeyEvent.VK_Z             : return com.jogamp.newt.event.KeyEvent.VK_Z;
+            case java.awt.event.KeyEvent.VK_OPEN_BRACKET  : return com.jogamp.newt.event.KeyEvent.VK_OPEN_BRACKET;
+            case java.awt.event.KeyEvent.VK_BACK_SLASH    : return com.jogamp.newt.event.KeyEvent.VK_BACK_SLASH;
+            case java.awt.event.KeyEvent.VK_CLOSE_BRACKET : return com.jogamp.newt.event.KeyEvent.VK_CLOSE_BRACKET;
+            case java.awt.event.KeyEvent.VK_CIRCUMFLEX    : return com.jogamp.newt.event.KeyEvent.VK_CIRCUMFLEX;
+            case java.awt.event.KeyEvent.VK_UNDERSCORE    : return com.jogamp.newt.event.KeyEvent.VK_UNDERSCORE;
+            case java.awt.event.KeyEvent.VK_BACK_QUOTE    : return com.jogamp.newt.event.KeyEvent.VK_BACK_QUOTE;
+            case java.awt.event.KeyEvent.VK_F1            : return com.jogamp.newt.event.KeyEvent.VK_F1;
+            case java.awt.event.KeyEvent.VK_F2            : return com.jogamp.newt.event.KeyEvent.VK_F2;
+            case java.awt.event.KeyEvent.VK_F3            : return com.jogamp.newt.event.KeyEvent.VK_F3;
+            case java.awt.event.KeyEvent.VK_F4            : return com.jogamp.newt.event.KeyEvent.VK_F4;
+            case java.awt.event.KeyEvent.VK_F5            : return com.jogamp.newt.event.KeyEvent.VK_F5;
+            case java.awt.event.KeyEvent.VK_F6            : return com.jogamp.newt.event.KeyEvent.VK_F6;
+            case java.awt.event.KeyEvent.VK_F7            : return com.jogamp.newt.event.KeyEvent.VK_F7;
+            case java.awt.event.KeyEvent.VK_F8            : return com.jogamp.newt.event.KeyEvent.VK_F8;
+            case java.awt.event.KeyEvent.VK_F9            : return com.jogamp.newt.event.KeyEvent.VK_F9;
+            case java.awt.event.KeyEvent.VK_F10           : return com.jogamp.newt.event.KeyEvent.VK_F10;
+            case java.awt.event.KeyEvent.VK_F11           : return com.jogamp.newt.event.KeyEvent.VK_F11;
+            case java.awt.event.KeyEvent.VK_F12           : return com.jogamp.newt.event.KeyEvent.VK_F12;
+            case java.awt.event.KeyEvent.VK_F13           : return com.jogamp.newt.event.KeyEvent.VK_F13;
+            case java.awt.event.KeyEvent.VK_F14           : return com.jogamp.newt.event.KeyEvent.VK_F14;
+            case java.awt.event.KeyEvent.VK_F15           : return com.jogamp.newt.event.KeyEvent.VK_F15;
+            case java.awt.event.KeyEvent.VK_F16           : return com.jogamp.newt.event.KeyEvent.VK_F16;
+            case java.awt.event.KeyEvent.VK_F17           : return com.jogamp.newt.event.KeyEvent.VK_F17;
+            case java.awt.event.KeyEvent.VK_F18           : return com.jogamp.newt.event.KeyEvent.VK_F18;
+            case java.awt.event.KeyEvent.VK_F19           : return com.jogamp.newt.event.KeyEvent.VK_F19;
+            case java.awt.event.KeyEvent.VK_F20           : return com.jogamp.newt.event.KeyEvent.VK_F20;
+            case java.awt.event.KeyEvent.VK_F21           : return com.jogamp.newt.event.KeyEvent.VK_F21;
+            case java.awt.event.KeyEvent.VK_F22           : return com.jogamp.newt.event.KeyEvent.VK_F22;
+            case java.awt.event.KeyEvent.VK_F23           : return com.jogamp.newt.event.KeyEvent.VK_F23;
+            case java.awt.event.KeyEvent.VK_F24           : return com.jogamp.newt.event.KeyEvent.VK_F24;
+            case java.awt.event.KeyEvent.VK_BRACELEFT     : return com.jogamp.newt.event.KeyEvent.VK_LEFT_BRACE;
+            case                         0x7c             : return com.jogamp.newt.event.KeyEvent.VK_PIPE;
+            case java.awt.event.KeyEvent.VK_BRACERIGHT    : return com.jogamp.newt.event.KeyEvent.VK_RIGHT_BRACE;
+            case java.awt.event.KeyEvent.VK_DEAD_TILDE    : return com.jogamp.newt.event.KeyEvent.VK_TILDE;
+            case java.awt.event.KeyEvent.VK_DELETE        : return com.jogamp.newt.event.KeyEvent.VK_DELETE;
+            case java.awt.event.KeyEvent.VK_NUMPAD0       : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD0;
+            case java.awt.event.KeyEvent.VK_NUMPAD1       : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD1;
+            case java.awt.event.KeyEvent.VK_NUMPAD2       : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD2;
+            case java.awt.event.KeyEvent.VK_NUMPAD3       : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD3;
+            case java.awt.event.KeyEvent.VK_NUMPAD4       : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD4;
+            case java.awt.event.KeyEvent.VK_NUMPAD5       : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD5;
+            case java.awt.event.KeyEvent.VK_NUMPAD6       : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD6;
+            case java.awt.event.KeyEvent.VK_NUMPAD7       : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD7;
+            case java.awt.event.KeyEvent.VK_NUMPAD8       : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD8;
+            case java.awt.event.KeyEvent.VK_NUMPAD9       : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD9;
+            case java.awt.event.KeyEvent.VK_DECIMAL       : return com.jogamp.newt.event.KeyEvent.VK_DECIMAL;
+            case java.awt.event.KeyEvent.VK_SEPARATOR     : return com.jogamp.newt.event.KeyEvent.VK_SEPARATOR;
+            case java.awt.event.KeyEvent.VK_ADD           : return com.jogamp.newt.event.KeyEvent.VK_ADD;
+            case java.awt.event.KeyEvent.VK_SUBTRACT      : return com.jogamp.newt.event.KeyEvent.VK_SUBTRACT;
+            case java.awt.event.KeyEvent.VK_MULTIPLY      : return com.jogamp.newt.event.KeyEvent.VK_MULTIPLY;
+            case java.awt.event.KeyEvent.VK_DIVIDE        : return com.jogamp.newt.event.KeyEvent.VK_DIVIDE;
+            case java.awt.event.KeyEvent.VK_NUM_LOCK      : return com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK;
+            case java.awt.event.KeyEvent.VK_KP_LEFT       : /** Fall through intended .. */ 
+            case java.awt.event.KeyEvent.VK_LEFT          : return com.jogamp.newt.event.KeyEvent.VK_LEFT;
+            case java.awt.event.KeyEvent.VK_KP_UP         : /** Fall through intended .. */
+            case java.awt.event.KeyEvent.VK_UP            : return com.jogamp.newt.event.KeyEvent.VK_UP;
+            case java.awt.event.KeyEvent.VK_KP_RIGHT      : /** Fall through intended .. */
+            case java.awt.event.KeyEvent.VK_RIGHT         : return com.jogamp.newt.event.KeyEvent.VK_RIGHT;
+            case java.awt.event.KeyEvent.VK_KP_DOWN       : /** Fall through intended .. */
+            case java.awt.event.KeyEvent.VK_DOWN          : return com.jogamp.newt.event.KeyEvent.VK_DOWN;
+            case java.awt.event.KeyEvent.VK_CONTEXT_MENU  : return com.jogamp.newt.event.KeyEvent.VK_CONTEXT_MENU;
+            case java.awt.event.KeyEvent.VK_WINDOWS       : return com.jogamp.newt.event.KeyEvent.VK_WINDOWS;
+            case java.awt.event.KeyEvent.VK_META          : return com.jogamp.newt.event.KeyEvent.VK_META;            
+            case java.awt.event.KeyEvent.VK_HELP          : return com.jogamp.newt.event.KeyEvent.VK_HELP;
+            case java.awt.event.KeyEvent.VK_COMPOSE       : return com.jogamp.newt.event.KeyEvent.VK_COMPOSE;
+            case java.awt.event.KeyEvent.VK_BEGIN         : return com.jogamp.newt.event.KeyEvent.VK_BEGIN;
+            case java.awt.event.KeyEvent.VK_STOP          : return com.jogamp.newt.event.KeyEvent.VK_STOP;
+            case java.awt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK: return com.jogamp.newt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK;
+            case java.awt.event.KeyEvent.VK_EURO_SIGN     : return com.jogamp.newt.event.KeyEvent.VK_EURO_SIGN;
+            case java.awt.event.KeyEvent.VK_CUT           : return com.jogamp.newt.event.KeyEvent.VK_CUT;
+            case java.awt.event.KeyEvent.VK_COPY          : return com.jogamp.newt.event.KeyEvent.VK_COPY;
+            case java.awt.event.KeyEvent.VK_PASTE         : return com.jogamp.newt.event.KeyEvent.VK_PASTE;
+            case java.awt.event.KeyEvent.VK_UNDO          : return com.jogamp.newt.event.KeyEvent.VK_UNDO;
+            case java.awt.event.KeyEvent.VK_AGAIN         : return com.jogamp.newt.event.KeyEvent.VK_AGAIN;
+            case java.awt.event.KeyEvent.VK_FIND          : return com.jogamp.newt.event.KeyEvent.VK_FIND;
+            case java.awt.event.KeyEvent.VK_PROPS         : return com.jogamp.newt.event.KeyEvent.VK_PROPS;
+            case java.awt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF: return com.jogamp.newt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF;
+            case java.awt.event.KeyEvent.VK_CODE_INPUT    : return com.jogamp.newt.event.KeyEvent.VK_CODE_INPUT;
+            case java.awt.event.KeyEvent.VK_ROMAN_CHARACTERS: return com.jogamp.newt.event.KeyEvent.VK_ROMAN_CHARACTERS;
+            case java.awt.event.KeyEvent.VK_ALL_CANDIDATES: return com.jogamp.newt.event.KeyEvent.VK_ALL_CANDIDATES;
+            case java.awt.event.KeyEvent.VK_PREVIOUS_CANDIDATE: return com.jogamp.newt.event.KeyEvent.VK_PREVIOUS_CANDIDATE;
+            case java.awt.event.KeyEvent.VK_ALPHANUMERIC  : return com.jogamp.newt.event.KeyEvent.VK_ALPHANUMERIC;
+            case java.awt.event.KeyEvent.VK_KATAKANA      : return com.jogamp.newt.event.KeyEvent.VK_KATAKANA;
+            case java.awt.event.KeyEvent.VK_HIRAGANA      : return com.jogamp.newt.event.KeyEvent.VK_HIRAGANA;
+            case java.awt.event.KeyEvent.VK_FULL_WIDTH    : return com.jogamp.newt.event.KeyEvent.VK_FULL_WIDTH;
+            case java.awt.event.KeyEvent.VK_HALF_WIDTH    : return com.jogamp.newt.event.KeyEvent.VK_HALF_WIDTH;
+            case java.awt.event.KeyEvent.VK_JAPANESE_KATAKANA: return com.jogamp.newt.event.KeyEvent.VK_JAPANESE_KATAKANA;
+            case java.awt.event.KeyEvent.VK_JAPANESE_HIRAGANA: return com.jogamp.newt.event.KeyEvent.VK_JAPANESE_HIRAGANA;
+            case java.awt.event.KeyEvent.VK_JAPANESE_ROMAN: return com.jogamp.newt.event.KeyEvent.VK_JAPANESE_ROMAN;
+            case java.awt.event.KeyEvent.VK_KANA_LOCK     : return com.jogamp.newt.event.KeyEvent.VK_KANA_LOCK;
+        }
+        return defNEWTKeyCode;
+    }
 
-    public static final int awtButton2Newt(int awtButton) {
-        switch (awtButton) {
-            case java.awt.event.MouseEvent.BUTTON1: return com.jogamp.newt.event.MouseEvent.BUTTON1;
-            case java.awt.event.MouseEvent.BUTTON2: return com.jogamp.newt.event.MouseEvent.BUTTON2;
-            case java.awt.event.MouseEvent.BUTTON3: return com.jogamp.newt.event.MouseEvent.BUTTON3;
+    public static int newtKeyCode2AWTKeyCode(final short newtKeyCode) {
+        final int defAwtKeyCode = 0xFFFF & (int)newtKeyCode;
+        switch (newtKeyCode) {
+            case com.jogamp.newt.event.KeyEvent.VK_HOME          : return java.awt.event.KeyEvent.VK_HOME;
+            case com.jogamp.newt.event.KeyEvent.VK_END           : return java.awt.event.KeyEvent.VK_END;
+            case com.jogamp.newt.event.KeyEvent.VK_FINAL         : return java.awt.event.KeyEvent.VK_FINAL;
+            case com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN   : return java.awt.event.KeyEvent.VK_PRINTSCREEN;
+            case com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE    : return java.awt.event.KeyEvent.VK_BACK_SPACE;
+            case com.jogamp.newt.event.KeyEvent.VK_TAB           : return java.awt.event.KeyEvent.VK_TAB;
+            case com.jogamp.newt.event.KeyEvent.VK_ENTER         : return java.awt.event.KeyEvent.VK_ENTER;
+            case com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN     : return java.awt.event.KeyEvent.VK_PAGE_DOWN;
+            case com.jogamp.newt.event.KeyEvent.VK_CLEAR         : return java.awt.event.KeyEvent.VK_CLEAR;
+            case com.jogamp.newt.event.KeyEvent.VK_SHIFT         : return java.awt.event.KeyEvent.VK_SHIFT;
+            case com.jogamp.newt.event.KeyEvent.VK_PAGE_UP       : return java.awt.event.KeyEvent.VK_PAGE_UP;
+            case com.jogamp.newt.event.KeyEvent.VK_CONTROL       : return java.awt.event.KeyEvent.VK_CONTROL;
+            case com.jogamp.newt.event.KeyEvent.VK_ALT           : return java.awt.event.KeyEvent.VK_ALT;
+            // FIXME: On X11 it results to 0xff7e w/ AWTRobot, which is wrong. 0xffea Alt_R is expected AFAIK.
+            case com.jogamp.newt.event.KeyEvent.VK_ALT_GRAPH     : return java.awt.event.KeyEvent.VK_ALT_GRAPH;
+            case com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK     : return java.awt.event.KeyEvent.VK_CAPS_LOCK;
+            case com.jogamp.newt.event.KeyEvent.VK_PAUSE         : return java.awt.event.KeyEvent.VK_PAUSE;
+            case com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK   : return java.awt.event.KeyEvent.VK_SCROLL_LOCK;
+            case com.jogamp.newt.event.KeyEvent.VK_CANCEL        : return java.awt.event.KeyEvent.VK_CANCEL;
+            case com.jogamp.newt.event.KeyEvent.VK_INSERT        : return java.awt.event.KeyEvent.VK_INSERT;
+            case com.jogamp.newt.event.KeyEvent.VK_ESCAPE        : return java.awt.event.KeyEvent.VK_ESCAPE;
+            case com.jogamp.newt.event.KeyEvent.VK_CONVERT       : return java.awt.event.KeyEvent.VK_CONVERT;
+            case com.jogamp.newt.event.KeyEvent.VK_NONCONVERT    : return java.awt.event.KeyEvent.VK_NONCONVERT;
+            case com.jogamp.newt.event.KeyEvent.VK_ACCEPT        : return java.awt.event.KeyEvent.VK_ACCEPT;
+            case com.jogamp.newt.event.KeyEvent.VK_MODECHANGE    : return java.awt.event.KeyEvent.VK_MODECHANGE;
+            case com.jogamp.newt.event.KeyEvent.VK_SPACE         : return java.awt.event.KeyEvent.VK_SPACE;
+            case com.jogamp.newt.event.KeyEvent.VK_EXCLAMATION_MARK: return java.awt.event.KeyEvent.VK_EXCLAMATION_MARK;
+            case com.jogamp.newt.event.KeyEvent.VK_QUOTEDBL      : return java.awt.event.KeyEvent.VK_QUOTEDBL;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMBER_SIGN   : return java.awt.event.KeyEvent.VK_NUMBER_SIGN;
+            case com.jogamp.newt.event.KeyEvent.VK_DOLLAR        : return java.awt.event.KeyEvent.VK_DOLLAR;
+            case com.jogamp.newt.event.KeyEvent.VK_PERCENT       : return defAwtKeyCode;
+            case com.jogamp.newt.event.KeyEvent.VK_AMPERSAND     : return java.awt.event.KeyEvent.VK_AMPERSAND;
+            case com.jogamp.newt.event.KeyEvent.VK_QUOTE         : return java.awt.event.KeyEvent.VK_QUOTE;
+            case com.jogamp.newt.event.KeyEvent.VK_LEFT_PARENTHESIS : return java.awt.event.KeyEvent.VK_LEFT_PARENTHESIS;
+            case com.jogamp.newt.event.KeyEvent.VK_RIGHT_PARENTHESIS: return java.awt.event.KeyEvent.VK_RIGHT_PARENTHESIS;
+            case com.jogamp.newt.event.KeyEvent.VK_ASTERISK      : return java.awt.event.KeyEvent.VK_ASTERISK;
+            case com.jogamp.newt.event.KeyEvent.VK_PLUS          : return java.awt.event.KeyEvent.VK_PLUS;
+            case com.jogamp.newt.event.KeyEvent.VK_COMMA         : return java.awt.event.KeyEvent.VK_COMMA;
+            case com.jogamp.newt.event.KeyEvent.VK_MINUS         : return java.awt.event.KeyEvent.VK_MINUS;
+            case com.jogamp.newt.event.KeyEvent.VK_PERIOD        : return java.awt.event.KeyEvent.VK_PERIOD;
+            case com.jogamp.newt.event.KeyEvent.VK_SLASH         : return java.awt.event.KeyEvent.VK_SLASH;
+            case com.jogamp.newt.event.KeyEvent.VK_0             : return java.awt.event.KeyEvent.VK_0;
+            case com.jogamp.newt.event.KeyEvent.VK_1             : return java.awt.event.KeyEvent.VK_1;
+            case com.jogamp.newt.event.KeyEvent.VK_2             : return java.awt.event.KeyEvent.VK_2;
+            case com.jogamp.newt.event.KeyEvent.VK_3             : return java.awt.event.KeyEvent.VK_3;
+            case com.jogamp.newt.event.KeyEvent.VK_4             : return java.awt.event.KeyEvent.VK_4;
+            case com.jogamp.newt.event.KeyEvent.VK_5             : return java.awt.event.KeyEvent.VK_5;
+            case com.jogamp.newt.event.KeyEvent.VK_6             : return java.awt.event.KeyEvent.VK_6;
+            case com.jogamp.newt.event.KeyEvent.VK_7             : return java.awt.event.KeyEvent.VK_7;
+            case com.jogamp.newt.event.KeyEvent.VK_8             : return java.awt.event.KeyEvent.VK_8;
+            case com.jogamp.newt.event.KeyEvent.VK_9             : return java.awt.event.KeyEvent.VK_9;
+            case com.jogamp.newt.event.KeyEvent.VK_COLON         : return java.awt.event.KeyEvent.VK_COLON;
+            case com.jogamp.newt.event.KeyEvent.VK_SEMICOLON     : return java.awt.event.KeyEvent.VK_SEMICOLON;
+            case com.jogamp.newt.event.KeyEvent.VK_LESS          : return java.awt.event.KeyEvent.VK_LESS;
+            case com.jogamp.newt.event.KeyEvent.VK_EQUALS        : return java.awt.event.KeyEvent.VK_EQUALS;
+            case com.jogamp.newt.event.KeyEvent.VK_GREATER       : return java.awt.event.KeyEvent.VK_GREATER;
+            case com.jogamp.newt.event.KeyEvent.VK_QUESTIONMARK  : return defAwtKeyCode;
+            case com.jogamp.newt.event.KeyEvent.VK_AT            : return java.awt.event.KeyEvent.VK_AT;
+            case com.jogamp.newt.event.KeyEvent.VK_A             : return java.awt.event.KeyEvent.VK_A;
+            case com.jogamp.newt.event.KeyEvent.VK_B             : return java.awt.event.KeyEvent.VK_B;
+            case com.jogamp.newt.event.KeyEvent.VK_C             : return java.awt.event.KeyEvent.VK_C;
+            case com.jogamp.newt.event.KeyEvent.VK_D             : return java.awt.event.KeyEvent.VK_D;
+            case com.jogamp.newt.event.KeyEvent.VK_E             : return java.awt.event.KeyEvent.VK_E;
+            case com.jogamp.newt.event.KeyEvent.VK_F             : return java.awt.event.KeyEvent.VK_F;
+            case com.jogamp.newt.event.KeyEvent.VK_G             : return java.awt.event.KeyEvent.VK_G;
+            case com.jogamp.newt.event.KeyEvent.VK_H             : return java.awt.event.KeyEvent.VK_H;
+            case com.jogamp.newt.event.KeyEvent.VK_I             : return java.awt.event.KeyEvent.VK_I;
+            case com.jogamp.newt.event.KeyEvent.VK_J             : return java.awt.event.KeyEvent.VK_J;
+            case com.jogamp.newt.event.KeyEvent.VK_K             : return java.awt.event.KeyEvent.VK_K;
+            case com.jogamp.newt.event.KeyEvent.VK_L             : return java.awt.event.KeyEvent.VK_L;
+            case com.jogamp.newt.event.KeyEvent.VK_M             : return java.awt.event.KeyEvent.VK_M;
+            case com.jogamp.newt.event.KeyEvent.VK_N             : return java.awt.event.KeyEvent.VK_N;
+            case com.jogamp.newt.event.KeyEvent.VK_O             : return java.awt.event.KeyEvent.VK_O;
+            case com.jogamp.newt.event.KeyEvent.VK_P             : return java.awt.event.KeyEvent.VK_P;
+            case com.jogamp.newt.event.KeyEvent.VK_Q             : return java.awt.event.KeyEvent.VK_Q;
+            case com.jogamp.newt.event.KeyEvent.VK_R             : return java.awt.event.KeyEvent.VK_R;
+            case com.jogamp.newt.event.KeyEvent.VK_S             : return java.awt.event.KeyEvent.VK_S;
+            case com.jogamp.newt.event.KeyEvent.VK_T             : return java.awt.event.KeyEvent.VK_T;
+            case com.jogamp.newt.event.KeyEvent.VK_U             : return java.awt.event.KeyEvent.VK_U;
+            case com.jogamp.newt.event.KeyEvent.VK_V             : return java.awt.event.KeyEvent.VK_V;
+            case com.jogamp.newt.event.KeyEvent.VK_W             : return java.awt.event.KeyEvent.VK_W;
+            case com.jogamp.newt.event.KeyEvent.VK_X             : return java.awt.event.KeyEvent.VK_X;
+            case com.jogamp.newt.event.KeyEvent.VK_Y             : return java.awt.event.KeyEvent.VK_Y;
+            case com.jogamp.newt.event.KeyEvent.VK_Z             : return java.awt.event.KeyEvent.VK_Z;
+            case com.jogamp.newt.event.KeyEvent.VK_OPEN_BRACKET  : return java.awt.event.KeyEvent.VK_OPEN_BRACKET;
+            case com.jogamp.newt.event.KeyEvent.VK_BACK_SLASH    : return java.awt.event.KeyEvent.VK_BACK_SLASH;
+            case com.jogamp.newt.event.KeyEvent.VK_CLOSE_BRACKET : return java.awt.event.KeyEvent.VK_CLOSE_BRACKET;
+            case com.jogamp.newt.event.KeyEvent.VK_CIRCUMFLEX    : return java.awt.event.KeyEvent.VK_CIRCUMFLEX;
+            case com.jogamp.newt.event.KeyEvent.VK_UNDERSCORE    : return java.awt.event.KeyEvent.VK_UNDERSCORE;
+            case com.jogamp.newt.event.KeyEvent.VK_BACK_QUOTE    : return java.awt.event.KeyEvent.VK_BACK_QUOTE;
+            case com.jogamp.newt.event.KeyEvent.VK_F1            : return java.awt.event.KeyEvent.VK_F1;
+            case com.jogamp.newt.event.KeyEvent.VK_F2            : return java.awt.event.KeyEvent.VK_F2;
+            case com.jogamp.newt.event.KeyEvent.VK_F3            : return java.awt.event.KeyEvent.VK_F3;
+            case com.jogamp.newt.event.KeyEvent.VK_F4            : return java.awt.event.KeyEvent.VK_F4;
+            case com.jogamp.newt.event.KeyEvent.VK_F5            : return java.awt.event.KeyEvent.VK_F5;
+            case com.jogamp.newt.event.KeyEvent.VK_F6            : return java.awt.event.KeyEvent.VK_F6;
+            case com.jogamp.newt.event.KeyEvent.VK_F7            : return java.awt.event.KeyEvent.VK_F7;
+            case com.jogamp.newt.event.KeyEvent.VK_F8            : return java.awt.event.KeyEvent.VK_F8;
+            case com.jogamp.newt.event.KeyEvent.VK_F9            : return java.awt.event.KeyEvent.VK_F9;
+            case com.jogamp.newt.event.KeyEvent.VK_F10           : return java.awt.event.KeyEvent.VK_F10;
+            case com.jogamp.newt.event.KeyEvent.VK_F11           : return java.awt.event.KeyEvent.VK_F11;
+            case com.jogamp.newt.event.KeyEvent.VK_F12           : return java.awt.event.KeyEvent.VK_F12;
+            case com.jogamp.newt.event.KeyEvent.VK_F13           : return java.awt.event.KeyEvent.VK_F13;
+            case com.jogamp.newt.event.KeyEvent.VK_F14           : return java.awt.event.KeyEvent.VK_F14;
+            case com.jogamp.newt.event.KeyEvent.VK_F15           : return java.awt.event.KeyEvent.VK_F15;
+            case com.jogamp.newt.event.KeyEvent.VK_F16           : return java.awt.event.KeyEvent.VK_F16;
+            case com.jogamp.newt.event.KeyEvent.VK_F17           : return java.awt.event.KeyEvent.VK_F17;
+            case com.jogamp.newt.event.KeyEvent.VK_F18           : return java.awt.event.KeyEvent.VK_F18;
+            case com.jogamp.newt.event.KeyEvent.VK_F19           : return java.awt.event.KeyEvent.VK_F19;
+            case com.jogamp.newt.event.KeyEvent.VK_F20           : return java.awt.event.KeyEvent.VK_F20;
+            case com.jogamp.newt.event.KeyEvent.VK_F21           : return java.awt.event.KeyEvent.VK_F21;
+            case com.jogamp.newt.event.KeyEvent.VK_F22           : return java.awt.event.KeyEvent.VK_F22;
+            case com.jogamp.newt.event.KeyEvent.VK_F23           : return java.awt.event.KeyEvent.VK_F23;
+            case com.jogamp.newt.event.KeyEvent.VK_F24           : return java.awt.event.KeyEvent.VK_F24;
+            case com.jogamp.newt.event.KeyEvent.VK_LEFT_BRACE    : return java.awt.event.KeyEvent.VK_BRACELEFT;
+            case com.jogamp.newt.event.KeyEvent.VK_PIPE          : return defAwtKeyCode;
+            case com.jogamp.newt.event.KeyEvent.VK_RIGHT_BRACE   : return java.awt.event.KeyEvent.VK_BRACERIGHT;
+            case com.jogamp.newt.event.KeyEvent.VK_TILDE         : return java.awt.event.KeyEvent.VK_DEAD_TILDE;
+            case com.jogamp.newt.event.KeyEvent.VK_DELETE        : return java.awt.event.KeyEvent.VK_DELETE;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD0       : return java.awt.event.KeyEvent.VK_NUMPAD0;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD1       : return java.awt.event.KeyEvent.VK_NUMPAD1;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD2       : return java.awt.event.KeyEvent.VK_NUMPAD2;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD3       : return java.awt.event.KeyEvent.VK_NUMPAD3;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD4       : return java.awt.event.KeyEvent.VK_NUMPAD4;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD5       : return java.awt.event.KeyEvent.VK_NUMPAD5;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD6       : return java.awt.event.KeyEvent.VK_NUMPAD6;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD7       : return java.awt.event.KeyEvent.VK_NUMPAD7;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD8       : return java.awt.event.KeyEvent.VK_NUMPAD8;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD9       : return java.awt.event.KeyEvent.VK_NUMPAD9;
+            case com.jogamp.newt.event.KeyEvent.VK_DECIMAL       : return java.awt.event.KeyEvent.VK_DECIMAL;
+            case com.jogamp.newt.event.KeyEvent.VK_SEPARATOR     : return java.awt.event.KeyEvent.VK_SEPARATOR;
+            case com.jogamp.newt.event.KeyEvent.VK_ADD           : return java.awt.event.KeyEvent.VK_ADD;
+            case com.jogamp.newt.event.KeyEvent.VK_SUBTRACT      : return java.awt.event.KeyEvent.VK_SUBTRACT;
+            case com.jogamp.newt.event.KeyEvent.VK_MULTIPLY      : return java.awt.event.KeyEvent.VK_MULTIPLY;
+            case com.jogamp.newt.event.KeyEvent.VK_DIVIDE        : return java.awt.event.KeyEvent.VK_DIVIDE;
+            case com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK      : return java.awt.event.KeyEvent.VK_NUM_LOCK;
+            case com.jogamp.newt.event.KeyEvent.VK_LEFT          : return java.awt.event.KeyEvent.VK_LEFT;
+            case com.jogamp.newt.event.KeyEvent.VK_UP            : return java.awt.event.KeyEvent.VK_UP;
+            case com.jogamp.newt.event.KeyEvent.VK_RIGHT         : return java.awt.event.KeyEvent.VK_RIGHT;
+            case com.jogamp.newt.event.KeyEvent.VK_DOWN          : return java.awt.event.KeyEvent.VK_DOWN;
+            case com.jogamp.newt.event.KeyEvent.VK_CONTEXT_MENU  : return java.awt.event.KeyEvent.VK_CONTEXT_MENU;
+            case com.jogamp.newt.event.KeyEvent.VK_WINDOWS       : return java.awt.event.KeyEvent.VK_WINDOWS;
+            case com.jogamp.newt.event.KeyEvent.VK_META          : return java.awt.event.KeyEvent.VK_META;            
+            case com.jogamp.newt.event.KeyEvent.VK_HELP          : return java.awt.event.KeyEvent.VK_HELP;
+            case com.jogamp.newt.event.KeyEvent.VK_COMPOSE       : return java.awt.event.KeyEvent.VK_COMPOSE;
+            case com.jogamp.newt.event.KeyEvent.VK_BEGIN         : return java.awt.event.KeyEvent.VK_BEGIN;
+            case com.jogamp.newt.event.KeyEvent.VK_STOP          : return java.awt.event.KeyEvent.VK_STOP;
+            case com.jogamp.newt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK: return java.awt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK;
+            case com.jogamp.newt.event.KeyEvent.VK_EURO_SIGN     : return java.awt.event.KeyEvent.VK_EURO_SIGN;
+            case com.jogamp.newt.event.KeyEvent.VK_CUT           : return java.awt.event.KeyEvent.VK_CUT;
+            case com.jogamp.newt.event.KeyEvent.VK_COPY          : return java.awt.event.KeyEvent.VK_COPY;
+            case com.jogamp.newt.event.KeyEvent.VK_PASTE         : return java.awt.event.KeyEvent.VK_PASTE;
+            case com.jogamp.newt.event.KeyEvent.VK_UNDO          : return java.awt.event.KeyEvent.VK_UNDO;
+            case com.jogamp.newt.event.KeyEvent.VK_AGAIN         : return java.awt.event.KeyEvent.VK_AGAIN;
+            case com.jogamp.newt.event.KeyEvent.VK_FIND          : return java.awt.event.KeyEvent.VK_FIND;
+            case com.jogamp.newt.event.KeyEvent.VK_PROPS         : return java.awt.event.KeyEvent.VK_PROPS;
+            case com.jogamp.newt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF: return java.awt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF;
+            case com.jogamp.newt.event.KeyEvent.VK_CODE_INPUT    : return java.awt.event.KeyEvent.VK_CODE_INPUT;
+            case com.jogamp.newt.event.KeyEvent.VK_ROMAN_CHARACTERS: return java.awt.event.KeyEvent.VK_ROMAN_CHARACTERS;
+            case com.jogamp.newt.event.KeyEvent.VK_ALL_CANDIDATES: return java.awt.event.KeyEvent.VK_ALL_CANDIDATES;
+            case com.jogamp.newt.event.KeyEvent.VK_PREVIOUS_CANDIDATE: return java.awt.event.KeyEvent.VK_PREVIOUS_CANDIDATE;
+            case com.jogamp.newt.event.KeyEvent.VK_ALPHANUMERIC  : return java.awt.event.KeyEvent.VK_ALPHANUMERIC;
+            case com.jogamp.newt.event.KeyEvent.VK_KATAKANA      : return java.awt.event.KeyEvent.VK_KATAKANA;
+            case com.jogamp.newt.event.KeyEvent.VK_HIRAGANA      : return java.awt.event.KeyEvent.VK_HIRAGANA;
+            case com.jogamp.newt.event.KeyEvent.VK_FULL_WIDTH    : return java.awt.event.KeyEvent.VK_FULL_WIDTH;
+            case com.jogamp.newt.event.KeyEvent.VK_HALF_WIDTH    : return java.awt.event.KeyEvent.VK_HALF_WIDTH;
+            case com.jogamp.newt.event.KeyEvent.VK_JAPANESE_KATAKANA: return java.awt.event.KeyEvent.VK_JAPANESE_KATAKANA;
+            case com.jogamp.newt.event.KeyEvent.VK_JAPANESE_HIRAGANA: return java.awt.event.KeyEvent.VK_JAPANESE_HIRAGANA;
+            case com.jogamp.newt.event.KeyEvent.VK_JAPANESE_ROMAN: return java.awt.event.KeyEvent.VK_JAPANESE_ROMAN;
+            case com.jogamp.newt.event.KeyEvent.VK_KANA_LOCK     : return java.awt.event.KeyEvent.VK_KANA_LOCK;
         }
-        return 0;
+        return defAwtKeyCode;
     }
 
     public static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.WindowEvent event, com.jogamp.newt.Window newtSource) {
-        int type = eventTypeAWT2NEWT.get(event.getID());
-        if(0xFFFFFFFF != type) {
-            return new com.jogamp.newt.event.WindowEvent(type, ((null==newtSource)?(Object)event.getComponent():(Object)newtSource), System.currentTimeMillis());
+        final short newtType = eventTypeAWT2NEWT(event.getID());
+        if( (short)0 != newtType ) {
+            return new com.jogamp.newt.event.WindowEvent(newtType, ((null==newtSource)?(Object)event.getComponent():(Object)newtSource), System.currentTimeMillis());
         }
         return null; // no mapping ..
     }
 
     public static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.ComponentEvent event, com.jogamp.newt.Window newtSource) {
-        int type = eventTypeAWT2NEWT.get(event.getID());
-        if(0xFFFFFFFF != type) {
-            return new com.jogamp.newt.event.WindowEvent(type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
+        final short newtType = eventTypeAWT2NEWT(event.getID());
+        if( (short)0 != newtType ) {
+            return new com.jogamp.newt.event.WindowEvent(newtType, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
         }
         return null; // no mapping ..
     }
 
     public static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.FocusEvent event, com.jogamp.newt.Window newtSource) {
-        int type = eventTypeAWT2NEWT.get(event.getID());
-        if(0xFFFFFFFF != type) {
-            return new com.jogamp.newt.event.WindowEvent(type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
+        final short newtType = eventTypeAWT2NEWT(event.getID());
+        if( (short)0 != newtType ) {
+            return new com.jogamp.newt.event.WindowEvent(newtType, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
         }
         return null; // no mapping ..
     }
 
     public static final com.jogamp.newt.event.MouseEvent createMouseEvent(java.awt.event.MouseEvent event, com.jogamp.newt.Window newtSource) {
-        int type = eventTypeAWT2NEWT.get(event.getID());
-        if(0xFFFFFFFF != type) {
-            int rotation = 0;
+        final short newtType = eventTypeAWT2NEWT(event.getID());
+        if( (short)0 != newtType ) {
+            float rotation = 0;
             if (event instanceof java.awt.event.MouseWheelEvent) {
                 // AWT/NEWT rotation is reversed - AWT +1 is down, NEWT +1 is up.
-                rotation = -1 * ((java.awt.event.MouseWheelEvent)event).getWheelRotation();
+                rotation = -1f * ((java.awt.event.MouseWheelEvent)event).getWheelRotation();
             }
 
-            int mods = awtModifiers2Newt(event.getModifiers(), true);
+            final short newtButton = awtButton2Newt(event.getButton());
+            int mods = awtModifiers2Newt(event.getModifiers(), event.getModifiersEx());
+            mods |= com.jogamp.newt.event.InputEvent.getButtonMask(newtButton); // always include NEWT BUTTON_MASK
             if(null!=newtSource) {
                 if(newtSource.isPointerConfined()) {
-                    mods |= InputEvent.CONFINED_MASK;
+                    mods |= com.jogamp.newt.event.InputEvent.CONFINED_MASK;
                 }
                 if(!newtSource.isPointerVisible()) {
-                    mods |= InputEvent.INVISIBLE_MASK;
+                    mods |= com.jogamp.newt.event.InputEvent.INVISIBLE_MASK;
                 }
             }
-                    
             return new com.jogamp.newt.event.MouseEvent(
-                           type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, event.getWhen(),
-                           mods, event.getX(), event.getY(), event.getClickCount(), 
-                           awtButton2Newt(event.getButton()), rotation);
+                           newtType, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, event.getWhen(),
+                           mods, event.getX(), event.getY(), (short)event.getClickCount(), 
+                           newtButton, MouseEvent.getRotationXYZ(rotation, mods), 1f);
         }
         return null; // no mapping ..
     }
 
     public static final com.jogamp.newt.event.KeyEvent createKeyEvent(java.awt.event.KeyEvent event, com.jogamp.newt.Window newtSource) {
-        int type = eventTypeAWT2NEWT.get(event.getID());
-        if(0xFFFFFFFF != type) {
-            return new com.jogamp.newt.event.KeyEvent(
-                           type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, event.getWhen(), 
-                           awtModifiers2Newt(event.getModifiers(), false), 
-                           event.getKeyCode(), event.getKeyChar());
+        return createKeyEvent(eventTypeAWT2NEWT(event.getID()), event, newtSource);
+    }
+
+    public static final com.jogamp.newt.event.KeyEvent createKeyEvent(short newtType, java.awt.event.KeyEvent event, com.jogamp.newt.Window newtSource) {
+        if( (short)0 != newtType ) {
+            final short newtKeyCode = awtKeyCode2NewtKeyCode( event.getKeyCode() );
+            return com.jogamp.newt.event.KeyEvent.create(
+                           newtType, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, event.getWhen(), 
+                           awtModifiers2Newt(event.getModifiers(), event.getModifiersEx()), 
+                           newtKeyCode, newtKeyCode, event.getKeyChar());
         }
         return null; // no mapping ..
     }
-
+    
 }
-
diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
index 747e236..fa494ad 100644
--- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
+++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
@@ -42,9 +42,7 @@ import com.jogamp.newt.event.awt.AWTWindowAdapter;
  * Specialized parent/client adapter,
  * where the NEWT child window really gets resized,
  * and the parent move window event gets discarded. */
-public class AWTParentWindowAdapter 
-    extends AWTWindowAdapter 
-    implements java.awt.event.HierarchyListener
+public class AWTParentWindowAdapter extends AWTWindowAdapter implements java.awt.event.HierarchyListener
 {
     NativeWindow downstreamParent;
     
@@ -98,7 +96,7 @@ public class AWTParentWindowAdapter
             public void run() {
                 int cw = comp.getWidth();
                 int ch = comp.getHeight();
-                if( 0 < cw * ch ) {
+                if( 0 < cw && 0 < ch ) {
                     if( newtWindow.getWidth() != cw || newtWindow.getHeight() != ch ) {
                         newtWindow.setSize(cw, ch);
                         if(comp.isVisible() != newtWindow.isVisible()) {
@@ -117,7 +115,7 @@ public class AWTParentWindowAdapter
         }
         final Window newtWindow = getNewtWindow();
         if(newtWindow.getDelegatedWindow() instanceof DriverUpdatePosition) {
-            ((DriverUpdatePosition)newtWindow.getDelegatedWindow()).updatePosition();
+            ((DriverUpdatePosition)newtWindow.getDelegatedWindow()).updatePosition(0, 0);
         }            
     }
 
diff --git a/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java b/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java
index bb846c0..2ec3271 100644
--- a/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java
+++ b/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java
@@ -4,6 +4,12 @@ package jogamp.newt.driver;
  * Interface tagging driver requirement of absolute positioning, ie. depend on parent position.
  */
 public interface DriverUpdatePosition {
-    /** Programmatic update the position */
-    void updatePosition();
+    /** 
+     * Programmatic update the top-left corner
+     * of the client area relative to it's parent.
+     * 
+     * @param x x-component 
+     * @param y y-component
+     **/
+    void updatePosition(int x, int y);
 }
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java
index 28c4da7..76eb890 100644
--- a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java
+++ b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java
@@ -32,9 +32,12 @@ import java.util.List;
 
 import javax.media.nativewindow.CapabilitiesImmutable;
 import javax.media.opengl.FPSCounter;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
 
 import com.jogamp.newt.Window;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.GLStateKeeper;
 
 import jogamp.newt.driver.android.WindowDriver;
 
@@ -46,12 +49,46 @@ import android.view.WindowManager;
 
 public class NewtBaseActivity extends Activity {
    List<Window> newtWindows = new ArrayList<Window>();
-   Animator animator = null;
+   List<GLAutoDrawable> glAutoDrawables = new ArrayList<GLAutoDrawable>();
+   
+   GLAnimatorControl animator = null;
     
    boolean isDelegatedActivity;
    Activity rootActivity;
    boolean setThemeCalled = false;
       
+   protected void startAnimation(boolean start) {
+     if(null != animator) {
+         final boolean res;
+         if( start ) {
+             if( animator.isPaused() ) { 
+                 res = animator.resume(); 
+             } else { 
+                 res = animator.start(); 
+             }
+         } else {
+             res = animator.stop();
+         }
+         Log.d(MD.TAG, "Animator global: start "+start+", result "+res);
+     }
+     for(int i=0; i<glAutoDrawables.size(); i++) {
+         final GLAnimatorControl anim = glAutoDrawables.get(i).getAnimator();
+         if(null != anim) {
+             final boolean res;
+             if( start ) {
+                 if( anim.isPaused() ) { 
+                     res = anim.resume(); 
+                 } else { 
+                     res = anim.start(); 
+                 }
+             } else {
+                 res = anim.stop();
+             }
+             Log.d(MD.TAG, "Animator glad["+i+"]: start "+start+", result "+res);
+         }
+     }
+   }
+       
    public NewtBaseActivity() {
        super();
        isDelegatedActivity = false;
@@ -59,8 +96,8 @@ public class NewtBaseActivity extends Activity {
    }
    
    public void setRootActivity(Activity rootActivity) {
-       this.isDelegatedActivity = true;
        this.rootActivity = rootActivity;
+       this.isDelegatedActivity = this != rootActivity;
    }
    
    public final boolean isDelegatedActivity() {
@@ -79,19 +116,21 @@ public class NewtBaseActivity extends Activity {
     * </p>  
     * @param androidWindow
     * @param newtWindow
+    * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
+    * @see #registerNEWTWindow(Window)
     * @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
     */
-   public void setContentView(android.view.Window androidWindow, Window newtWindow) {
-       newtWindow = newtWindow.getDelegatedWindow();
-       if(newtWindow instanceof WindowDriver) {
-           adaptTheme4Transparency(newtWindow.getRequestedCapabilities());
-           layoutForNEWTWindow(androidWindow, newtWindow);
-           WindowDriver newtAWindow = (WindowDriver)newtWindow;
+   public void setContentView(final android.view.Window androidWindow, final Window newtWindow) throws IllegalArgumentException {
+       final Window delegateWindow = newtWindow.getDelegatedWindow();
+       if(delegateWindow instanceof WindowDriver) {
+           adaptTheme4Transparency(delegateWindow.getRequestedCapabilities());
+           layoutForNEWTWindow(androidWindow, delegateWindow);
+           final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
            androidWindow.setContentView(newtAWindow.getAndroidView());
-           registerNEWTWindow(newtAWindow);
        } else {
-           throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass()); 
+           throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass().getName()); 
        }
+       registerNEWTWindow(newtWindow);
    }
    /**
     * This is one of the three registration methods (see below).
@@ -102,32 +141,68 @@ public class NewtBaseActivity extends Activity {
     * @param androidWindow
     * @param newtWindow
     * @param params
-    * @see #setContentView(android.view.Window, Window)
+    * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
     * @see #registerNEWTWindow(Window)
+    * @see #setContentView(android.view.Window, Window)
     */
-   public void addContentView(android.view.Window androidWindow, Window newtWindow, android.view.ViewGroup.LayoutParams params) {
-       newtWindow = newtWindow.getDelegatedWindow();
-       if(newtWindow instanceof WindowDriver) {
-           WindowDriver newtAWindow = (WindowDriver)newtWindow;
+   public void addContentView(final android.view.Window androidWindow, final Window newtWindow, final android.view.ViewGroup.LayoutParams params) throws IllegalArgumentException {
+       final Window delegateWindow = newtWindow.getDelegatedWindow();
+       if(delegateWindow instanceof WindowDriver) {
+           final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
            androidWindow.addContentView(newtAWindow.getAndroidView(), params);
-           registerNEWTWindow(newtAWindow);
        } else {
-           throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass()); 
+           throw new IllegalArgumentException("Given NEWT Window's Delegate is not an Android Window: "+delegateWindow.getClass().getName()); 
        }       
+       registerNEWTWindow(newtWindow);
    }
    /**
     * This is one of the three registration methods (see below).
     * <p>
-    * This methods simply registers the given NEWT window to ensure it's destruction at {@link #onDestroy()}.
-    * </p>  
+    * This methods registers the given NEWT window to ensure it's destruction at {@link #onDestroy()}.
+    * </p>
+    * <p>
+    * If adding a {@link GLAutoDrawable} implementation, the {@link GLAnimatorControl} retrieved by {@link GLAutoDrawable#getAnimator()} 
+    * will be used for {@link #onPause()} and {@link #onResume()}.
+    * </p>
+    * <p>
+    * If adding a {@link GLAutoDrawable} implementation, the {@link GLEventListenerState} will preserve it's state 
+    * when {@link #onPause()} is being called while not {@link #isFinishing()}. A later {@link #onResume()} will 
+    * reinstate the {@link GLEventListenerState}.
+    * </p>
     * 
     * @param newtWindow
+    * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
     * @see #setContentView(android.view.Window, Window)
     * @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
     */
-   public void registerNEWTWindow(Window newtWindow) {
+   public void registerNEWTWindow(final Window newtWindow) throws IllegalArgumentException {
+       final Window delegateWindow = newtWindow.getDelegatedWindow();
+       Log.d(MD.TAG, "registerNEWTWindow: Type "+newtWindow.getClass().getName()+", delegate "+delegateWindow.getClass().getName());
+       if(delegateWindow instanceof WindowDriver) {
+           final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
+           newtAWindow.registerActivity(getActivity());
+       } else {
+           throw new IllegalArgumentException("Given NEWT Window's Delegate is not an Android Window: "+delegateWindow.getClass().getName()); 
+       }       
        newtWindows.add(newtWindow);
+       if(newtWindow instanceof GLAutoDrawable) {
+           glAutoDrawables.add((GLAutoDrawable)newtWindow);
+       }
+       if(newtWindow instanceof GLStateKeeper) {
+           ((GLStateKeeper)newtWindow).setGLStateKeeperListener(glStateKeeperListener);
+       }
    }
+   private final GLStateKeeper.Listener glStateKeeperListener = new GLStateKeeper.Listener() {
+       @Override
+       public void glStatePreserveNotify(GLStateKeeper glsk) {
+           Log.d(MD.TAG, "GLStateKeeper Preserving: 0x"+Integer.toHexString(glsk.hashCode()));
+       }
+       @Override
+       public void glStateRestored(GLStateKeeper glsk) {
+           Log.d(MD.TAG, "GLStateKeeper Restored: 0x"+Integer.toHexString(glsk.hashCode()));
+           startAnimation(true);
+       }
+   };
    
    /**
     * Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window. 
@@ -221,7 +296,19 @@ public class NewtBaseActivity extends Activity {
        }
    }
    
-   public void setAnimator(Animator animator) {
+   /**
+    * Setting up a global {@Link GLAnimatorControl} for {@link #onPause()} and {@link #onResume()}.
+    * <p>
+    * Note that if adding a {@link GLAutoDrawable} implementation via {@link #registerNEWTWindow(Window)},
+    * {@link #setContentView(android.view.Window, Window)} or {@link #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)}
+    * their {@link GLAnimatorControl} retrieved by {@link GLAutoDrawable#getAnimator()} will be used as well.
+    * In this case, using this global {@Link GLAnimatorControl} is redundant. 
+    * </p>
+    * @see #registerNEWTWindow(Window)
+    * @see #setContentView(android.view.Window, Window)
+    * @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
+    */
+   public void setAnimator(GLAnimatorControl animator) {
        this.animator = animator;
        if(!animator.isStarted()) {
            animator.start();
@@ -231,37 +318,49 @@ public class NewtBaseActivity extends Activity {
       
    @Override
    public android.view.Window getWindow() {
-       return getActivity().getWindow();
+       if( isDelegatedActivity() ) {
+           return getActivity().getWindow();
+       } else {
+           return super.getWindow();
+       }
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
-       Log.d(MD.TAG, "onCreate");
+       Log.d(MD.TAG, "onCreate.0");
        if(!isDelegatedActivity()) {
            super.onCreate(savedInstanceState);
        }
+       // Extraordinary cleanup, for cases of 'onCreate()' calls w/ valid states, 
+       // i.e. w/o having onDestroy() being called.
+       // Could happened due to spec when App process is killed for memory exhaustion or other reasons.
+       cleanup();
+       
        jogamp.common.os.android.StaticContext.init(rootActivity.getApplicationContext());
+       Log.d(MD.TAG, "onCreate.X");
    }
    
    @Override
    public void onStart() {
-     Log.d(MD.TAG, "onStart");
+     Log.d(MD.TAG, "onStart.0");
      if(!isDelegatedActivity()) {
          super.onStart();
      }
+     Log.d(MD.TAG, "onStart.X");
    }
      
    @Override
    public void onRestart() {
-     Log.d(MD.TAG, "onRestart");
+     Log.d(MD.TAG, "onRestart.0");
      if(!isDelegatedActivity()) {
          super.onRestart();
      }
+     Log.d(MD.TAG, "onRestart.X");
    }
 
    @Override
    public void onResume() {
-     Log.d(MD.TAG, "onResume");
+     Log.d(MD.TAG, "onResume.0");
      if(!isDelegatedActivity()) {
          super.onResume();
      }
@@ -272,49 +371,93 @@ public class NewtBaseActivity extends Activity {
              ((FPSCounter)win).resetFPSCounter();
          }
      }
-     if(null != animator) {
-         animator.resume();
-         animator.resetFPSCounter();
-     }
+     startAnimation(true);
+     Log.d(MD.TAG, "onResume.X");
    }
 
    @Override
    public void onPause() {
-     Log.d(MD.TAG, "onPause");
-     if(null != animator) {
-         animator.pause();
-     }
-     for(int i=0; i<newtWindows.size(); i++) {
-         final Window win = newtWindows.get(i);
-         win.setVisible(false);
+     Log.d(MD.TAG, "onPause.0");
+     if( !getActivity().isFinishing() ) {
+         int ok=0, fail=0;
+         for(int i=0; i<glAutoDrawables.size(); i++) {
+             final GLAutoDrawable glad = glAutoDrawables.get(i);
+             if(glad instanceof GLStateKeeper) {
+                 if( ((GLStateKeeper)glad).preserveGLStateAtDestroy(true) ) {
+                     ok++;
+                 } else {
+                     fail++;
+                 }
+             }
+         }
+         Log.d(MD.TAG, "GLStateKeeper.Mark2Preserve: Total "+glAutoDrawables.size()+", OK "+ok+", Fail "+fail);
      }
-     if(!isDelegatedActivity()) {
+     startAnimation(false);
+     if( !isDelegatedActivity() ) {
          super.onPause();
      }
+     Log.d(MD.TAG, "onPause.X");
    }
 
    @Override
    public void onStop() {
-     Log.d(MD.TAG, "onStop");
-     if(!isDelegatedActivity()) {
+     Log.d(MD.TAG, "onStop.0");
+     for(int i=0; i<newtWindows.size(); i++) {
+         final Window win = newtWindows.get(i);
+         win.setVisible(false);
+     }
+     if( !isDelegatedActivity() ) {
          super.onStop();  
      }
+     Log.d(MD.TAG, "onStop.X");
    }
-
-   @Override
-   public void onDestroy() {
-     Log.d(MD.TAG, "onDestroy");
-     if(null != animator) {
-         animator.stop();
-         animator = null;
+   
+   /**
+    * Performs cleaning up all references,
+    * <p>
+    * Cleaning and destroying up all preserved GLEventListenerState
+    * and clearing the preserve-flag of all GLStateKeeper.
+    * </p>
+    * <p>
+    * Destroying all GLWindow.
+    * </p>
+    */
+   private void cleanup() {
+     Log.d(MD.TAG, "cleanup.0");
+     int glelsKilled = 0, glelsClean = 0;
+     for(int i=0; i<glAutoDrawables.size(); i++) {
+         final GLAutoDrawable glad = glAutoDrawables.get(i);
+         if(glad instanceof GLStateKeeper) {
+             final GLStateKeeper glsk = (GLStateKeeper)glad;
+             glsk.preserveGLStateAtDestroy(false);
+             final GLEventListenerState glels = glsk.clearPreservedGLState();
+             if( null != glels) {
+                 glels.destroy();
+                 glelsKilled++;
+             } else {
+                 glelsClean++;
+             }
+         }
      }
-     while(newtWindows.size()>0) {
-         final Window win = newtWindows.remove(newtWindows.size()-1);
+     Log.d(MD.TAG, "cleanup.1: GLStateKeeper.ForceDestroy: Total "+glAutoDrawables.size()+", destroyed "+glelsKilled+", clean "+glelsClean);
+     for(int i=0; i<newtWindows.size(); i++) {
+         final Window win = newtWindows.get(i);
          win.destroy();
      }
+     newtWindows.clear();
+     glAutoDrawables.clear();
+     Log.d(MD.TAG, "cleanup.1: StaticContext.getContext: "+jogamp.common.os.android.StaticContext.getContext());
      jogamp.common.os.android.StaticContext.clear();
+     Log.d(MD.TAG, "cleanup.X");
+   }
+   
+   @Override
+   public void onDestroy() {
+     Log.d(MD.TAG, "onDestroy.0");
+     cleanup(); // normal cleanup
      if(!isDelegatedActivity()) {
          super.onDestroy(); 
      }
+     Log.d(MD.TAG, "onDestroy.X");
    }   
 }
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
index a49f164..de524d5 100644
--- a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
+++ b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
@@ -60,8 +60,10 @@ public class NewtVersionActivity extends NewtBaseActivity {
        final ScrollView scroller = new ScrollView(getActivity());
        scroller.addView(tv);
        viewGroup.addView(scroller, new android.widget.FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, Gravity.TOP|Gravity.LEFT));
-       
-       tv.setText(VersionUtil.getPlatformInfo()+Platform.NEWLINE+GlueGenVersion.getInstance()+Platform.NEWLINE+JoglVersion.getInstance()+Platform.NEWLINE);               
+
+       final String info1 = VersionUtil.getPlatformInfo()+Platform.NEWLINE+GlueGenVersion.getInstance()+Platform.NEWLINE+JoglVersion.getInstance()+Platform.NEWLINE;
+       Log.d(MD.TAG, info1);
+       tv.setText(info1);               
        
        // create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
        GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
@@ -77,14 +79,17 @@ public class NewtVersionActivity extends NewtBaseActivity {
             public void init(GLAutoDrawable drawable) {
                 GL gl = drawable.getGL();
                 final StringBuffer sb = new StringBuffer();
-                sb.append(JoglVersion.getGLInfo(gl, null)).append(Platform.NEWLINE);
+                sb.append(JoglVersion.getGLInfo(gl, null, true)).append(Platform.NEWLINE);
                 sb.append("Requested: ").append(Platform.NEWLINE);
                 sb.append(drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()).append(Platform.NEWLINE).append(Platform.NEWLINE);
                 sb.append("Chosen: ").append(Platform.NEWLINE);
                 sb.append(drawable.getChosenGLCapabilities()).append(Platform.NEWLINE).append(Platform.NEWLINE);
+                final String info2 = sb.toString();
+                // Log.d(MD.TAG, info2); // too big!
+                System.err.println(info2);
                 viewGroup.post(new Runnable() {
                     public void run() {
-                        tv.append(sb.toString());
+                        tv.append(info2);
                         viewGroup.removeView(androidGLView);
                     } } );                
             }
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java
index cb8799b..9b3c6e2 100644
--- a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java
+++ b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java
@@ -11,7 +11,7 @@ public class NewtVersionActivityLauncher extends Activity {
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            
-           final Uri uri = Uri.parse("launch://jogamp.org/jogamp.newt.driver.android.NewtVersionActivity");
+           final Uri uri = Uri.parse("launch://jogamp.org/jogamp.newt.driver.android.NewtVersionActivity?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/newt/classes/jogamp/newt/driver/android/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
index 795aac5..cc35ff7 100644
--- a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
@@ -28,12 +28,10 @@
 
 package jogamp.newt.driver.android;
 
-import javax.media.nativewindow.*;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.DefaultGraphicsScreen;
 
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.MonitorModeProps.Cache;
 
 import android.content.Context;
 import android.graphics.PixelFormat;
@@ -41,6 +39,9 @@ import android.util.DisplayMetrics;
 import android.view.Surface;
 import android.view.WindowManager;
 
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
 public class ScreenDriver extends jogamp.newt.ScreenImpl {
 
     static {
@@ -50,13 +51,36 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
     public ScreenDriver() {
     }
 
+    @Override
     protected void createNativeImpl() {
         aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
     }
 
+    @Override
     protected void closeNativeImpl() { }
 
-    protected ScreenMode getCurrentScreenModeImpl() {
+    @Override
+    protected int validateScreenIndex(int idx) {
+        return 0; // FIXME: only one screen available ? 
+    }
+    
+    private final MonitorMode getModeImpl(final Cache cache, final android.view.Display aDisplay, DisplayMetrics outMetrics, int modeIdx, int screenSizeNRot, int nrot) {
+        final int[] props = new int[MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL];
+        int i = 0;
+        props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+        i = getScreenSize(outMetrics, screenSizeNRot, props, i); // width, height
+        i = getBpp(aDisplay, props, i); // bpp 
+        props[i++] = (int) ( aDisplay.getRefreshRate() * 100.0f ); // Hz * 100
+        props[i++] = 0; // flags
+        props[i++] = modeIdx; // modeId;
+        props[i++] = nrot;
+        return MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+    }
+    
+    @Override
+    protected void collectNativeMonitorModesAndDevicesImpl(Cache cache) {
+        // FIXME: Multi Monitor Implementation missing [for newer Android version ?]
+        
         final Context ctx = jogamp.common.os.android.StaticContext.getContext();
         final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
         final DisplayMetrics outMetrics = new DisplayMetrics();
@@ -65,27 +89,44 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
         
         final int arot = aDisplay.getRotation();
         final int nrot = androidRotation2NewtRotation(arot);
-        int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
-        int offset = 1; // set later for verification of iterator
-        offset = getScreenSize(outMetrics, nrot, props, offset);
-        offset = getBpp(aDisplay, props, offset); 
-        offset = getScreenSizeMM(outMetrics, props, offset);
-        props[offset++] = (int) aDisplay.getRefreshRate();
-        props[offset++] = nrot;
-        props[offset - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = offset; // count
-        return ScreenModeUtil.streamIn(props, 0);
+        
+        final int modeIdx=0; // no native modeId in use - use 0
+        MonitorMode currentMode = null;
+        for(int r=0; r<4; r++) { // for all rotations
+            final int nrot_i = r*MonitorMode.ROTATE_90;
+            MonitorMode mode = getModeImpl(cache, aDisplay, outMetrics, modeIdx, 0, nrot_i);
+            if( nrot == nrot_i ) {
+                currentMode = mode;
+            }
+        }        
+
+        final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+        int i = 0;
+        props[i++] = props.length;
+        props[i++] = 0; // crt_idx
+        i = getScreenSizeMM(outMetrics, props, i); // sizeMM
+        props[i++] = 0; // rotated viewport x
+        props[i++] = 0; // rotated viewport y
+        props[i++] = outMetrics.widthPixels; // rotated viewport width
+        props[i++] = outMetrics.heightPixels; // rotated viewport height
+        MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);        
     }
-    
-    protected int validateScreenIndex(int idx) {
-        return 0; // FIXME: only one screen available ? 
+
+    @Override
+    protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) {        
+        final Context ctx = jogamp.common.os.android.StaticContext.getContext();
+        final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
+        final DisplayMetrics outMetrics = new DisplayMetrics();
+        final android.view.Display aDisplay = wmgr.getDefaultDisplay();
+        aDisplay.getMetrics(outMetrics);
+        
+        final int currNRot = androidRotation2NewtRotation(aDisplay.getRotation());
+        return getModeImpl(null, aDisplay, outMetrics, 0, currNRot, currNRot);
     }
-    
-    protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
-        virtualOrigin.setX(0);
-        virtualOrigin.setY(0);
-        final ScreenMode sm = getCurrentScreenMode();
-        virtualSize.setWidth(sm.getRotatedWidth());
-        virtualSize.setHeight(sm.getRotatedHeight());
+
+    @Override
+    protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode) {
+        return false;
     }
     
     //----------------------------------------------------------------------
@@ -93,16 +134,16 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
     //
     static int androidRotation2NewtRotation(int arot) {
         switch(arot) {
-            case Surface.ROTATION_270: return ScreenMode.ROTATE_270;
-            case Surface.ROTATION_180: return ScreenMode.ROTATE_180;
-            case Surface.ROTATION_90: return ScreenMode.ROTATE_90;
+            case Surface.ROTATION_270: return MonitorMode.ROTATE_270;
+            case Surface.ROTATION_180: return MonitorMode.ROTATE_180;
+            case Surface.ROTATION_90: return MonitorMode.ROTATE_90;
             case Surface.ROTATION_0:
         }
-        return ScreenMode.ROTATE_0;
+        return MonitorMode.ROTATE_0;
     }
     static int getScreenSize(DisplayMetrics outMetrics, int nrot, int[] props, int offset) {
         // swap width and height, since Android reflects rotated dimension, we don't
-        if (ScreenMode.ROTATE_90 == nrot || ScreenMode.ROTATE_270 == nrot) {
+        if (MonitorMode.ROTATE_90 == nrot || MonitorMode.ROTATE_270 == nrot) {
             props[offset++] = outMetrics.heightPixels;
             props[offset++] = outMetrics.widthPixels;
         } else {
diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
index f185206..653cbf9 100644
--- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
@@ -29,53 +29,143 @@
 package jogamp.newt.driver.android;
 
 import jogamp.common.os.android.StaticContext;
+import jogamp.newt.WindowImpl;
 import jogamp.newt.driver.android.event.AndroidNewtEventFactory;
+import jogamp.newt.driver.android.event.AndroidNewtEventTranslator;
 
+import javax.media.nativewindow.AbstractGraphicsScreen;
 import javax.media.nativewindow.Capabilities;
 import javax.media.nativewindow.CapabilitiesImmutable;
+import javax.media.nativewindow.DefaultGraphicsScreen;
 import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.VisualIDHolder;
 import javax.media.nativewindow.util.Insets;
 import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.RectangleImmutable;
 import javax.media.opengl.GLCapabilitiesChooser;
 import javax.media.opengl.GLCapabilitiesImmutable;
 import javax.media.opengl.GLException;
 
+import com.jogamp.common.os.AndroidVersion;
 import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+import com.jogamp.newt.MonitorDevice;
 
 import jogamp.opengl.egl.EGL;
+import jogamp.opengl.egl.EGLDisplayUtil;
 import jogamp.opengl.egl.EGLGraphicsConfiguration;
 import jogamp.opengl.egl.EGLGraphicsConfigurationFactory;
 
+import android.app.Activity;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.PixelFormat;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.ResultReceiver;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.SurfaceHolder.Callback2;
+import android.view.ViewGroup;
 import android.view.inputmethod.InputMethodManager;
 import android.view.SurfaceView;
-import android.view.View;
+import android.view.KeyEvent;
+
 
 public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {    
     static {
         DisplayDriver.initSingleton();
     }
 
-    public static CapabilitiesImmutable fixCaps(boolean matchFormatPrecise, int format, CapabilitiesImmutable rCaps) {
+    /**
+     * First stage of selecting an Android PixelFormat, 
+     * at construction via {@link SurfaceHolder#setFormat(int)} 
+     * before native realization!
+     * 
+     * @param rCaps requested Capabilities
+     * @return An Android PixelFormat number suitable for {@link SurfaceHolder#setFormat(int)}.
+     */
+    public static final int getSurfaceHolderFormat(CapabilitiesImmutable rCaps) {
+        int fmt = PixelFormat.UNKNOWN;
+        
+        if( !rCaps.isBackgroundOpaque() ) {
+            fmt = PixelFormat.TRANSLUCENT;
+        } else if( rCaps.getRedBits()<=5 &&
+                   rCaps.getGreenBits()<=6 &&
+                   rCaps.getBlueBits()<=5 &&
+                   rCaps.getAlphaBits()==0 ) {
+            fmt = PixelFormat.RGB_565;            
+        } else if( rCaps.getAlphaBits()==0 ) {
+            fmt = PixelFormat.RGB_888;
+        } else {        
+            fmt = PixelFormat.RGBA_8888;
+        }
+        Log.d(MD.TAG, "getSurfaceHolderFormat: requested: "+rCaps);
+        Log.d(MD.TAG, "getSurfaceHolderFormat:  returned: "+fmt);
+        
+        return fmt;
+    }
+    
+    
+    public static final int NATIVE_WINDOW_FORMAT_RGBA_8888          = 1;
+    public static final int NATIVE_WINDOW_FORMAT_RGBX_8888          = 2;
+    public static final int NATIVE_WINDOW_FORMAT_RGB_565            = 4;
+
+    /**
+     * Second stage of selecting an Android PixelFormat, 
+     * at right after native (surface) realization at {@link Callback2#surfaceChanged(SurfaceHolder, int, int, int)}.
+     * Selection happens via {@link #setSurfaceVisualID0(long, int)} before native EGL creation.
+     * 
+     * @param androidPixelFormat An Android PixelFormat delivered via {@link Callback2#surfaceChanged(SurfaceHolder, int, int, int)} params.
+     * @return A native Android PixelFormat number suitable for {@link #setSurfaceVisualID0(long, int)}.
+     */
+    public static final int getANativeWindowFormat(int androidPixelFormat) {
+        final int nativePixelFormat;
+        switch(androidPixelFormat) {
+            case PixelFormat.RGBA_8888:
+            case PixelFormat.RGBA_5551:
+            case PixelFormat.RGBA_4444:
+                nativePixelFormat = NATIVE_WINDOW_FORMAT_RGBA_8888; 
+                break;
+            
+            case PixelFormat.RGBX_8888:
+            case PixelFormat.RGB_888:   
+                nativePixelFormat = NATIVE_WINDOW_FORMAT_RGBX_8888; 
+                break;
+                
+            case PixelFormat.RGB_565:   
+            case PixelFormat.RGB_332:   
+                nativePixelFormat = NATIVE_WINDOW_FORMAT_RGB_565; 
+                break;
+            default: nativePixelFormat = NATIVE_WINDOW_FORMAT_RGBA_8888;
+        }
+        Log.d(MD.TAG, "getANativeWindowFormat: android: "+androidPixelFormat+" -> native "+nativePixelFormat);
+        return nativePixelFormat;
+    }
+    
+    /**
+     * Final stage of Android PixelFormat operation, 
+     * match the requested Capabilities w/ Android PixelFormat number. 
+     * This is done at native realization @ {@link Callback2#surfaceChanged(SurfaceHolder, int, int, int)}.
+     * 
+     * @param matchFormatPrecise
+     * @param format
+     * @param rCaps requested Capabilities
+     * @return The fixed Capabilities
+     */    
+    public static final CapabilitiesImmutable fixCaps(boolean matchFormatPrecise, int format, CapabilitiesImmutable rCaps) {
         PixelFormat pf = new PixelFormat(); 
         PixelFormat.getPixelFormatInfo(format, pf);
         final CapabilitiesImmutable res;        
         int r, g, b, a;
         
         switch(format) {
-            case PixelFormat.RGBA_8888: r=8; g=8; b=8; a=8; break;
-            case PixelFormat.RGBX_8888: r=8; g=8; b=8; a=0; break;
+            case PixelFormat.RGBA_8888: r=8; g=8; b=8; a=8; break; // NATIVE_WINDOW_FORMAT_RGBA_8888
+            case PixelFormat.RGBX_8888: r=8; g=8; b=8; a=0; break; // NATIVE_WINDOW_FORMAT_RGBX_8888
             case PixelFormat.RGB_888:   r=8; g=8; b=8; a=0; break;
-            case PixelFormat.RGB_565:   r=5; g=6; b=5; a=0; break;
+            case PixelFormat.RGB_565:   r=5; g=6; b=5; a=0; break; // NATIVE_WINDOW_FORMAT_RGB_565
             case PixelFormat.RGBA_5551: r=5; g=5; b=5; a=1; break;
             case PixelFormat.RGBA_4444: r=4; g=4; b=4; a=4; break;
             case PixelFormat.RGB_332:   r=3; g=3; b=2; a=0; break;
@@ -104,33 +194,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
         return res;
     }
     
-    public static int getFormat(CapabilitiesImmutable rCaps) {
-        int fmt = PixelFormat.UNKNOWN;
-        
-        if(!rCaps.isBackgroundOpaque()) {
-            fmt = PixelFormat.TRANSLUCENT;
-        } else if(rCaps.getRedBits()<=5 &&
-           rCaps.getGreenBits()<=6 &&
-           rCaps.getBlueBits()<=5 &&
-           rCaps.getAlphaBits()==0) {
-            fmt = PixelFormat.RGB_565;            
-        } 
-        /* else if(rCaps.getRedBits()<=5 &&
-           rCaps.getGreenBits()<=5 &&
-           rCaps.getBlueBits()<=5 &&
-           rCaps.getAlphaBits()==1) {
-            fmt = PixelFormat.RGBA_5551; // FIXME: Supported ?             
-        } */ 
-        else {        
-            fmt = PixelFormat.RGBA_8888;
-        }
-        Log.d(MD.TAG, "getFormat: requested: "+rCaps);
-        Log.d(MD.TAG, "getFormat:  returned: "+fmt);
-        
-        return fmt;
-    }
-    
-    public static boolean isAndroidFormatTransparent(int aFormat) {
+    public static final boolean isAndroidFormatTransparent(int aFormat) {
         switch (aFormat) {
             case PixelFormat.TRANSLUCENT:
             case PixelFormat.TRANSPARENT:
@@ -139,42 +203,6 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
         return false;
     }
     
-    class AndroidEvents implements View.OnKeyListener, View.OnTouchListener, View.OnFocusChangeListener {
-
-        @Override
-        public boolean onTouch(View v, android.view.MotionEvent event) {
-            final com.jogamp.newt.event.MouseEvent[] newtEvents = AndroidNewtEventFactory.createMouseEvents(event, WindowDriver.this);
-            if(null != newtEvents) {
-                focusChanged(false, true);
-                for(int i=0; i<newtEvents.length; i++) {
-                    WindowDriver.this.enqueueEvent(false, newtEvents[i]);
-                }
-                try { Thread.sleep((long) (1000.0F/30.0F)); }
-                catch(InterruptedException e) { }
-                return true; // consumed/handled, further interest in events
-            }
-            return false; // no mapping, no further interest in the event!
-        }
-
-        @Override
-        public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
-            final com.jogamp.newt.event.KeyEvent[] newtEvents = AndroidNewtEventFactory.createKeyEvents(keyCode, event, WindowDriver.this);
-            if(null != newtEvents) {
-                for(int i=0; i<newtEvents.length; i++) {
-                    WindowDriver.this.enqueueEvent(false, newtEvents[i]);
-                }
-                return true;
-            }
-            return false;
-        }
-        
-        @Override
-        public void onFocusChange(View v, boolean hasFocus) {
-            WindowDriver.this.focusChanged(false, hasFocus);
-        }
-        
-    }
-
     public static Class<?>[] getCustomConstructorArgumentTypes() {
         return new Class<?>[] { Context.class } ;
     }
@@ -182,9 +210,14 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
     public WindowDriver() {
         reset();
     }
+    
+    public void registerActivity(Activity activity) {
+        this.activity = activity;
+    }
+    protected Activity activity = null;
 
-    private void reset() {
-        ownAndroidWindow = false;
+    private final void reset() {
+        added2StaticViewGroup = false;
         androidView = null;
         nativeFormat = VisualIDHolder.VID_UNDEFINED;
         androidFormat = VisualIDHolder.VID_UNDEFINED;
@@ -193,64 +226,132 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
         surfaceHandle = 0;
         eglSurface = 0;
         definePosition(0, 0); // default to 0/0
+        defineSize(0, 0); // default size -> TBD !
+        
         setBrokenFocusChange(true);
     }
     
+    private final void setupInputListener(final boolean enable) {
+        Log.d(MD.TAG, "setupInputListener(enable "+enable+") - "+Thread.currentThread().getName());
+        
+        final AndroidNewtEventTranslator eventTranslator = 
+                enable ? new AndroidNewtEventTranslator(this, androidView.getContext(), androidView.getHandler()) : null; 
+        androidView.setOnTouchListener(eventTranslator);
+        androidView.setOnKeyListener(eventTranslator);
+        androidView.setOnFocusChangeListener(eventTranslator);
+        if(AndroidVersion.SDK_INT >= 12) { // API Level 12
+            Log.d(MD.TAG, "setupInputListener - enable GenericMotionListener - "+Thread.currentThread().getName());
+            androidView.setOnGenericMotionListener(eventTranslator);
+        }
+        if( enable ) {
+            androidView.post(new Runnable() {
+                public void run() {
+                    androidView.setClickable(false);
+                    androidView.setFocusable(true);
+                    androidView.setFocusableInTouchMode(true);
+                } } );
+        }
+    }
+    
+    private final void setupAndroidView(Context ctx) {
+        androidView = new MSurfaceView(ctx);
+                
+        final SurfaceHolder sh = androidView.getHolder();
+        sh.addCallback(WindowDriver.this); 
+        sh.setFormat(getSurfaceHolderFormat(getRequestedCapabilities()));        
+    }
+    
+    public final SurfaceView getAndroidView() { return androidView; }
+    
     @Override
-    protected void instantiationFinished() {
+    protected final void instantiationFinished() {
+        Log.d(MD.TAG, "instantiationFinished() - "+Thread.currentThread().getName());
+                
         final Context ctx = StaticContext.getContext();        
         if(null == ctx) {
             throw new NativeWindowException("No static [Application] Context has been set. Call StaticContext.setContext(Context) first.");
         }
-        androidView = new MSurfaceView(ctx);
-        
-        final AndroidEvents ae = new AndroidEvents();
-        androidView.setOnTouchListener(ae);
-        androidView.setClickable(false);
-        androidView.setOnKeyListener(ae);
-        androidView.setOnFocusChangeListener(ae);
-        androidView.setFocusable(true);
-        androidView.setFocusableInTouchMode(true);
         
-        final SurfaceHolder sh = androidView.getHolder();
-        sh.addCallback(WindowDriver.this); 
-        sh.setFormat(getFormat(getRequestedCapabilities()));
-        
-        // default size -> TBD ! 
-        defineSize(0, 0);
+        if( null != Looper.myLooper() ) {
+            setupAndroidView(ctx);
+        }
     }
     
-    public SurfaceView getAndroidView() { return androidView; }
-    
     @Override
-    protected boolean canCreateNativeImpl() {
-        final boolean b = 0 != surfaceHandle;
-        Log.d(MD.TAG, "canCreateNativeImpl: "+b);
+    protected final boolean canCreateNativeImpl() {
+        Log.d(MD.TAG, "canCreateNativeImpl.0: surfaceHandle ready "+(0!=surfaceHandle)+" - on thread "+Thread.currentThread().getName());
+        if(WindowImpl.DEBUG_IMPLEMENTATION) {
+            Thread.dumpStack();
+        }
+        
+        if( isFullscreen() ) {
+            final MonitorDevice mainMonitor = getMainMonitor();
+            final RectangleImmutable viewport = mainMonitor.getViewport();
+            definePosition(viewport.getX(), viewport.getY());
+            defineSize(viewport.getWidth(), viewport.getHeight());
+        }
+        
+        final boolean b;
+        
+        if( 0 == surfaceHandle ) {
+            // Static ViewGroup, i.e. self contained main code
+            final ViewGroup viewGroup = StaticContext.getContentViewGroup();
+            Log.d(MD.TAG, "canCreateNativeImpl: viewGroup "+viewGroup);
+            if( null != viewGroup && !added2StaticViewGroup ) {
+                added2StaticViewGroup = true;
+                viewGroup.post(new Runnable() {
+                    public void run() {
+                        if(null == androidView) {
+                            setupAndroidView( StaticContext.getContext() );
+                        }
+                        viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(getWidth(), getHeight(), Gravity.BOTTOM|Gravity.RIGHT));
+                        Log.d(MD.TAG, "canCreateNativeImpl: added to static ViewGroup - on thread "+Thread.currentThread().getName());                        
+                    } });
+                for(long sleep = TIMEOUT_NATIVEWINDOW; 0<sleep && 0 == surfaceHandle; sleep-=10 ) {
+                    try { Thread.sleep(10); } catch (InterruptedException ie) {}
+                }
+                b = 0 != surfaceHandle;
+                Log.d(MD.TAG, "canCreateNativeImpl: surfaceHandle ready(2) "+b+" - on thread "+Thread.currentThread().getName());                
+            } else {
+                // No surfaceHandle defined, No static ViewGroup to add ourselves
+                b = false;
+            }
+        } else {
+            // surfaceHandle already defined
+            b = true; 
+        }
         return b;
     }
 
     @Override
-    protected void createNativeImpl() {
-        Log.d(MD.TAG, "createNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
-                    ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName());
+    protected final void createNativeImpl() {
+        // Create own screen/device resource instance allowing independent ownership,
+        // while still utilizing shared EGL resources.
+        final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen();
+        final EGLGraphicsDevice aDevice = (EGLGraphicsDevice) aScreen.getDevice();
+        final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(aDevice.getNativeDisplayID(), aDevice.getConnection(), aDevice.getUnitID());
+        final DefaultGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aScreen.getIndex());
+        
+        Log.d(MD.TAG, "createNativeImpl 0 - eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
+                    ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - on thread "+Thread.currentThread().getName());
 
         if(0!=getParentWindowHandle()) {
             throw new NativeWindowException("Window parenting not supported (yet)");
         }
         if(0==surfaceHandle) {
-            throw new InternalError("XXX");
+            throw new InternalError("surfaceHandle null");
         }
        
-        final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice();
         final EGLGraphicsConfiguration eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
                 capsByFormat, (GLCapabilitiesImmutable) getRequestedCapabilities(), 
-                (GLCapabilitiesChooser)capabilitiesChooser, getScreen().getGraphicsScreen(), nativeFormat, 
-                isAndroidFormatTransparent(androidFormat));
+                (GLCapabilitiesChooser)capabilitiesChooser, eglScreen, nativeFormat, isAndroidFormatTransparent(androidFormat));
         if (eglConfig == null) {
             throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
         }
         final int nativeVisualID = eglConfig.getVisualID(VisualIDHolder.VIDType.NATIVE);
         Log.d(MD.TAG, "nativeVisualID 0x"+Integer.toHexString(nativeVisualID));
+        Log.d(MD.TAG, "requestedCaps: "+eglConfig.getRequestedCapabilities());
+        Log.d(MD.TAG, "chosenCaps   : "+eglConfig.getChosenCapabilities());
         if(VisualIDHolder.VID_UNDEFINED != nativeVisualID) {
             setSurfaceVisualID0(surfaceHandle, nativeVisualID);
         }
@@ -259,27 +360,61 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
         if (EGL.EGL_NO_SURFACE==eglSurface) {
             throw new NativeWindowException("Creation of window surface failed: "+eglConfig+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+", error "+toHexString(EGL.eglGetError()));
         }
-        
+                
         // propagate data ..
         setGraphicsConfiguration(eglConfig);
         setWindowHandle(surfaceHandle);
+        visibleChanged(false, true);
         focusChanged(false, true);
-        Log.d(MD.TAG, "createNativeImpl X: eglSurfaceHandle 0x"+Long.toHexString(eglSurface));
+        
+        setupInputListener(true);
+        
+        Log.d(MD.TAG, "createNativeImpl X: eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", eglSurfaceHandle 0x"+Long.toHexString(eglSurface));
     }
 
     @Override
-    protected void closeNativeImpl() {
-        Log.d(MD.TAG, "closeNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
+    protected final void closeNativeImpl() {
+        final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getGraphicsConfiguration().getScreen().getDevice();
+        
+        Log.d(MD.TAG, "closeNativeImpl 0 - eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
                     ", eglSurfaceHandle 0x"+Long.toHexString(eglSurface)+
-                    ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName());
+                    ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - on thread "+Thread.currentThread().getName());
+        if(WindowImpl.DEBUG_IMPLEMENTATION) {
+            Thread.dumpStack();
+        }
+        
+        setupInputListener(false);
+        
         if(0 != eglSurface) {
-            final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice();
-            if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) {
-                throw new GLException("Error destroying window surface (eglDestroySurface)");
+            try {
+                if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) {
+                    throw new GLException("Error destroying window surface (eglDestroySurface)");
+                }
+            } catch (Throwable t) {
+                Log.d(MD.TAG, "closeNativeImpl: Catch exception "+t.getMessage());
+                t.printStackTrace();
+            } finally {
+                eglSurface = 0;
             }
-            eglSurface = 0;        
         }        
         release0(surfaceHandle);
+        
+        eglDevice.close();
+
+        if( null != androidView ) {
+            if( added2StaticViewGroup ) {
+                added2StaticViewGroup = false;
+                final ViewGroup viewGroup = StaticContext.getContentViewGroup();
+                if( null != viewGroup) {
+                    viewGroup.post(new Runnable() {
+                        public void run() {
+                            viewGroup.removeView(androidView);
+                            Log.d(MD.TAG, "closeNativeImpl: removed from static ViewGroup - on thread "+Thread.currentThread().getName());
+                        } });
+                }
+            }
+        }
+        
         surface = null;
         surfaceHandle = 0;
     }
@@ -289,7 +424,20 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
         return eglSurface;
     }
     
-    protected void requestFocusImpl(boolean reparented) { 
+    /**
+     * <p>
+     * Accessible protected method!
+     * </p>
+     * 
+     * {@inheritDoc}
+     */
+    @Override
+    public final void focusChanged(boolean defer, boolean focusGained) {
+        super.focusChanged(defer, focusGained);
+    }
+    
+    @Override
+    protected final void requestFocusImpl(boolean reparented) { 
         if(null != androidView) {
             Log.d(MD.TAG, "requestFocusImpl: reparented "+reparented);
             androidView.post(new Runnable() {
@@ -301,7 +449,8 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
         }
     }
 
-    protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {        
+    @Override
+    protected final boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {        
         boolean res = true;
         
         if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
@@ -330,11 +479,13 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
         return res;
     }
 
-    protected Point getLocationOnScreenImpl(int x, int y) {
+    @Override
+    protected final Point getLocationOnScreenImpl(int x, int y) {
         return new Point(x,y);
     }
 
-    protected void updateInsetsImpl(Insets insets) {
+    @Override
+    protected final void updateInsetsImpl(Insets insets) {
         // nop ..        
     }
     
@@ -367,18 +518,20 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
     }
     private KeyboardVisibleReceiver keyboardVisibleReceiver = new KeyboardVisibleReceiver();
     
+    @Override
     protected final boolean setKeyboardVisibleImpl(boolean visible) {
         if(null != androidView) {
             final InputMethodManager imm = (InputMethodManager) getAndroidView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
             final IBinder winid = getAndroidView().getWindowToken();
+            final boolean result;
             if(visible) {
                 // Show soft-keyboard:
-                imm.showSoftInput(androidView, 0, keyboardVisibleReceiver);
+                result = imm.showSoftInput(androidView, 0, keyboardVisibleReceiver);
             } else {
                 // hide keyboard :
-                imm.hideSoftInputFromWindow(winid, 0, keyboardVisibleReceiver);
+                result = imm.hideSoftInputFromWindow(winid, 0, keyboardVisibleReceiver);
             }
-            return visible;
+            return result;
         } else {
             return false; // nop
         }
@@ -388,12 +541,17 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
     // Surface Callbacks 
     //
     
-    public void surfaceCreated(SurfaceHolder holder) {    
-        Log.d(MD.TAG, "surfaceCreated: "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
+    @Override
+    public final void surfaceCreated(SurfaceHolder holder) {    
+        Log.d(MD.TAG, "surfaceCreated: "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - on thread "+Thread.currentThread().getName());
     }
 
-    public void surfaceChanged(SurfaceHolder aHolder, int aFormat, int aWidth, int aHeight) {
-        Log.d(MD.TAG, "surfaceChanged: f "+nativeFormat+" -> "+aFormat+", "+aWidth+"x"+aHeight+", current surfaceHandle: 0x"+Long.toHexString(surfaceHandle));
+    @Override
+    public final void surfaceChanged(SurfaceHolder aHolder, int aFormat, int aWidth, int aHeight) {
+        Log.d(MD.TAG, "surfaceChanged: f "+nativeFormat+" -> "+aFormat+", "+aWidth+"x"+aHeight+", current surfaceHandle: 0x"+Long.toHexString(surfaceHandle)+" - on thread "+Thread.currentThread().getName());
+        if(WindowImpl.DEBUG_IMPLEMENTATION) {
+            Thread.dumpStack();
+        }
         if(0!=surfaceHandle && androidFormat != aFormat ) {
             // re-create
             Log.d(MD.TAG, "surfaceChanged (destroy old)");
@@ -404,7 +562,9 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
             surface=null;
         }
         if(getScreen().isNativeValid()) {
-            getScreen().getCurrentScreenMode(); // if ScreenMode changed .. trigger ScreenMode event
+            // if MonitorMode changed .. trigger MonitorMode event
+            final MonitorDevice mainMonitor = getMainMonitor();
+            mainMonitor.queryCurrentMode();
         }
 
         if(0>getX() || 0>getY()) {
@@ -416,7 +576,11 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
             surface = aHolder.getSurface();
             surfaceHandle = getSurfaceHandle0(surface);
             acquire0(surfaceHandle);
+            final int aNativeWindowFormat = getANativeWindowFormat(androidFormat);
+            setSurfaceVisualID0(surfaceHandle, aNativeWindowFormat);            
             nativeFormat = getSurfaceVisualID0(surfaceHandle);
+            Log.d(MD.TAG, "surfaceChanged: androidFormat "+androidFormat+" -- (set-native "+aNativeWindowFormat+") --> nativeFormat "+nativeFormat);
+
             final int nWidth = getWidth0(surfaceHandle);
             final int nHeight = getHeight0(surfaceHandle);
             capsByFormat = (GLCapabilitiesImmutable) fixCaps(true /* matchFormatPrecise */, nativeFormat, getRequestedCapabilities());
@@ -436,17 +600,77 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
         Log.d(MD.TAG, "surfaceChanged: X");
     }
     
-    public void surfaceDestroyed(SurfaceHolder holder) {
-        Log.d(MD.TAG, "surfaceDestroyed");
+    @Override
+    public final void surfaceDestroyed(SurfaceHolder holder) {
+        Log.d(MD.TAG, "surfaceDestroyed - on thread "+Thread.currentThread().getName());
         windowDestroyNotify(true); // actually too late .. however ..
+        Thread.dumpStack();
     }
 
-    public void surfaceRedrawNeeded(SurfaceHolder holder) {
-        Log.d(MD.TAG, "surfaceRedrawNeeded");
+    @Override
+    public final void surfaceRedrawNeeded(SurfaceHolder holder) {
+        Log.d(MD.TAG, "surfaceRedrawNeeded  - on thread "+Thread.currentThread().getName());
         windowRepaint(0, 0, getWidth(), getHeight());
     }
         
-    private boolean ownAndroidWindow;
+    protected boolean handleKeyCodeBack(KeyEvent.DispatcherState state, android.view.KeyEvent event) {
+        if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
+            Log.d(MD.TAG, "handleKeyCodeBack.0 : "+event);
+            state.startTracking(event, this);
+        } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled() && state.isTracking(event)) {
+            // Since we cannot trust the visibility state 'completly', 
+            // assume an already invisible state if the invisible operation fails. 
+            final boolean wasVisible = setKeyboardVisibleImpl(false);
+            Log.d(MD.TAG, "handleKeyCodeBack.1 : wasVisible "+wasVisible+": "+event);
+            keyboardVisibilityChanged(false);
+            if( wasVisible ) {
+                // event processed, just send invisible event, no activity.finished()
+                enqueueAKey2NKeyUpDown(event, com.jogamp.newt.event.KeyEvent.VK_KEYBOARD_INVISIBLE);
+                return true;
+            } else if( null != activity ) {
+                // process event on our own, since we have an activity to call finish()
+                // and decide in overriden consumeKeyEvent(..) whether we suppress or proceed w/ activity.finish().
+                enqueueAKey2NKeyUpDown(event, com.jogamp.newt.event.KeyEvent.VK_ESCAPE);
+                return true;
+            } else {
+                Log.d(MD.TAG, "handleKeyCodeBack.X1 : "+event);
+                windowDestroyNotify(true);
+                // -> default BACK action, usually activity.finish() 
+            }
+        }
+        return false; // continue w/ further processing
+    }
+    private void enqueueAKey2NKeyUpDown(android.view.KeyEvent aEvent, short newtKeyCode) {
+        final com.jogamp.newt.event.KeyEvent eDown = AndroidNewtEventFactory.createKeyEvent(aEvent, newtKeyCode, com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED, this);
+        final com.jogamp.newt.event.KeyEvent eUp = AndroidNewtEventFactory.createKeyEvent(aEvent, newtKeyCode, com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED, this);
+        enqueueEvent(false, eDown);
+        enqueueEvent(false, eUp);
+    }
+    
+    @Override
+    protected void consumeKeyEvent(com.jogamp.newt.event.KeyEvent e) {
+        super.consumeKeyEvent(e); // consume event, i.e. call all KeyListener
+        if( com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED == e.getEventType() && !e.isConsumed() ) {
+            if( com.jogamp.newt.event.KeyEvent.VK_ESCAPE == e.getKeyCode() ) {
+                Log.d(MD.TAG, "handleKeyCodeBack.X2 : "+e);
+                activity.finish();
+            } else if( com.jogamp.newt.event.KeyEvent.VK_HOME == e.getKeyCode() ) {
+                Log.d(MD.TAG, "handleKeyCodeHome.X2 : "+e);
+                triggerHome();
+            }
+        }
+    }    
+    private void triggerHome() {
+       Context ctx = StaticContext.getContext();
+       if(null == ctx) {
+           throw new NativeWindowException("No static [Application] Context has been set. Call StaticContext.setContext(Context) first.");
+       }
+       Intent showOptions = new Intent(Intent.ACTION_MAIN);
+       showOptions.addCategory(Intent.CATEGORY_HOME);
+       ctx.startActivity(showOptions);
+    }
+    
+    private boolean added2StaticViewGroup;
     private MSurfaceView androidView;
     private int nativeFormat; // chosen current native PixelFormat (suitable for EGL)
     private int androidFormat; // chosen current android PixelFormat (-1, -2 ..)
@@ -461,13 +685,27 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
             setBackgroundDrawable(null);
             // setBackgroundColor(Color.TRANSPARENT);
         }
+
+        @Override
+        public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+            Log.d(MD.TAG, "onKeyPreIme : "+event);
+            if ( event.getKeyCode() == KeyEvent.KEYCODE_BACK ) {
+                final KeyEvent.DispatcherState state = getKeyDispatcherState();
+                if (state != null) {
+                    return handleKeyCodeBack(state, event);
+                }
+            }
+            return false; // cont. processing
+        }        
     }
     //----------------------------------------------------------------------
     // Internals only
     //
     protected static native boolean initIDs0();
     protected static native long getSurfaceHandle0(Surface surface);
+    /** Return the native window format via <code>ANativeWindow_getFormat(..)</code>. */
     protected static native int getSurfaceVisualID0(long surfaceHandle);
+    /** Set the native window format via <code>ANativeWindow_setBuffersGeometry(..)</code>. */
     protected static native void setSurfaceVisualID0(long surfaceHandle, int nativeVisualID);
     protected static native int getWidth0(long surfaceHandle);
     protected static native int getHeight0(long surfaceHandle);
diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
index d23b5f5..364a348 100644
--- a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
+++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
@@ -28,49 +28,90 @@
  
 package jogamp.newt.driver.android.event;
 
-import java.awt.event.MouseEvent;
+import jogamp.newt.Debug;
+import android.view.MotionEvent;
 
-import com.jogamp.common.util.IntIntHashMap;
-import com.jogamp.newt.Window;
+import com.jogamp.common.os.AndroidVersion;
 import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.NEWTEvent;
 
 public class AndroidNewtEventFactory {
-
-    protected static final IntIntHashMap eventTypeANDROID2NEWT;
-
-    private static final String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
-                                            "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
+    private static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Android.MouseEvent");
+    private static final boolean DEBUG_KEY_EVENT = Debug.debug("Android.KeyEvent");
     
-    static {
-        IntIntHashMap map = new IntIntHashMap();
-        map.setKeyNotFoundValue(0xFFFFFFFF);
-        
-        map.put(android.view.MotionEvent.ACTION_DOWN, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED);
-        map.put(android.view.MotionEvent.ACTION_UP, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
-        map.put(android.view.MotionEvent.ACTION_CANCEL, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
-        map.put(android.view.MotionEvent.ACTION_MOVE, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED);
-        map.put(android.view.MotionEvent.ACTION_OUTSIDE, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED);
-        
-        map.put(android.view.MotionEvent.ACTION_POINTER_DOWN, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED);
-        map.put(android.view.MotionEvent.ACTION_POINTER_UP, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
-        
-        map.put(android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
+    /** API Level 12: {@link android.view.MotionEvent#ACTION_SCROLL} = {@value} */
+    private static final int ACTION_SCROLL = 8;
 
-        eventTypeANDROID2NEWT = map;
+    private static final com.jogamp.newt.event.MouseEvent.PointerType aToolType2PointerType(int aToolType) {
+        switch( aToolType ) {
+            case MotionEvent.TOOL_TYPE_FINGER:
+                return com.jogamp.newt.event.MouseEvent.PointerType.TouchScreen;
+            case MotionEvent.TOOL_TYPE_MOUSE:
+                return com.jogamp.newt.event.MouseEvent.PointerType.Mouse;
+            case MotionEvent.TOOL_TYPE_STYLUS:
+            case MotionEvent.TOOL_TYPE_ERASER:
+                return com.jogamp.newt.event.MouseEvent.PointerType.Pen;
+            default:
+                return com.jogamp.newt.event.MouseEvent.PointerType.Undefined;       
+        }
+    }
+    
+    private static final short aMotionEventType2Newt(int aType) {
+        switch( aType ) {
+            case android.view.MotionEvent.ACTION_DOWN: 
+                return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED; 
+            case android.view.MotionEvent.ACTION_UP: 
+                return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED; 
+            case android.view.MotionEvent.ACTION_MOVE: 
+                return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED; 
+            case android.view.MotionEvent.ACTION_CANCEL: 
+                return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED; 
+            case android.view.MotionEvent.ACTION_OUTSIDE: 
+                return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED; 
+            case android.view.MotionEvent.ACTION_POINTER_DOWN: 
+                return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED; 
+            case android.view.MotionEvent.ACTION_POINTER_UP: 
+                return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED; 
+            // case ACTION_HOVER_MOVE
+            case ACTION_SCROLL:  // API Level 12 !
+                return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED; 
+            // case ACTION_HOVER_ENTER
+            // case ACTION_HOVER_EXIT
+        }
+        return (short)0;
+    }
+    
+    private static final short aAccessibilityEventType2Newt(int aType) {
+        switch( aType ) {
+            case android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED: 
+                return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+        }
+        return (short)0;
     }
 
-    static final int androidKeyCode2Newt(int androidKeyCode) {
+    private static final short aKeyEventType2NewtEventType(int androidKeyAction) {
+        switch(androidKeyAction) {
+            case android.view.KeyEvent.ACTION_DOWN: 
+            case android.view.KeyEvent.ACTION_MULTIPLE:
+                return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
+            case android.view.KeyEvent.ACTION_UP:
+                return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
+        }
+        return (short)0;
+    }
+    
+    private static final short aKeyCode2NewtKeyCode(int androidKeyCode, boolean inclSysKeys) {
         if(android.view.KeyEvent.KEYCODE_0 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_9) {
-            return com.jogamp.newt.event.KeyEvent.VK_0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_0 ) ; 
+            return (short) ( com.jogamp.newt.event.KeyEvent.VK_0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_0 ) ); 
         }
         if(android.view.KeyEvent.KEYCODE_A <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_Z) {
-            return com.jogamp.newt.event.KeyEvent.VK_A + ( androidKeyCode - android.view.KeyEvent.KEYCODE_A ) ; 
+            return (short) ( com.jogamp.newt.event.KeyEvent.VK_A + ( androidKeyCode - android.view.KeyEvent.KEYCODE_A ) ); 
         }
         if(android.view.KeyEvent.KEYCODE_F1 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_F12) {
-            return com.jogamp.newt.event.KeyEvent.VK_F1 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_F1 ) ; 
+            return (short) ( com.jogamp.newt.event.KeyEvent.VK_F1 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_F1 ) ); 
         }
         if(android.view.KeyEvent.KEYCODE_NUMPAD_0 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_NUMPAD_9) {
-            return com.jogamp.newt.event.KeyEvent.VK_NUMPAD0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_NUMPAD_0 ) ; 
+            return (short) ( com.jogamp.newt.event.KeyEvent.VK_NUMPAD0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_NUMPAD_0 ) ); 
         }           
         switch(androidKeyCode) {
             case android.view.KeyEvent.KEYCODE_COMMA: return com.jogamp.newt.event.KeyEvent.VK_COMMA; 
@@ -82,7 +123,7 @@ public class AndroidNewtEventFactory {
             case android.view.KeyEvent.KEYCODE_TAB: return com.jogamp.newt.event.KeyEvent.VK_TAB;
             case android.view.KeyEvent.KEYCODE_SPACE: return com.jogamp.newt.event.KeyEvent.VK_SPACE;
             case android.view.KeyEvent.KEYCODE_ENTER: return com.jogamp.newt.event.KeyEvent.VK_ENTER;
-            case android.view.KeyEvent.KEYCODE_DEL: return com.jogamp.newt.event.KeyEvent.VK_DELETE;
+            case android.view.KeyEvent.KEYCODE_DEL: return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
             case android.view.KeyEvent.KEYCODE_MINUS: return com.jogamp.newt.event.KeyEvent.VK_MINUS;
             case android.view.KeyEvent.KEYCODE_EQUALS: return com.jogamp.newt.event.KeyEvent.VK_EQUALS;
             case android.view.KeyEvent.KEYCODE_LEFT_BRACKET: return com.jogamp.newt.event.KeyEvent.VK_LEFT_PARENTHESIS;
@@ -95,24 +136,29 @@ public class AndroidNewtEventFactory {
             // case android.view.KeyEvent.KEYCODE_MUTE: ??
             case android.view.KeyEvent.KEYCODE_PAGE_UP: return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP;
             case android.view.KeyEvent.KEYCODE_PAGE_DOWN: return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN;
-            // case android.view.KeyEvent.KEYCODE_HOME: return com.jogamp.newt.event.KeyEvent.VK_HOME;
-            // case android.view.KeyEvent.KEYCODE_BACK: return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
             case android.view.KeyEvent.KEYCODE_ESCAPE: return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
             case android.view.KeyEvent.KEYCODE_CTRL_LEFT: return com.jogamp.newt.event.KeyEvent.VK_CONTROL;
             case android.view.KeyEvent.KEYCODE_CTRL_RIGHT: return com.jogamp.newt.event.KeyEvent.VK_CONTROL; // ??
+            case android.view.KeyEvent.KEYCODE_BACK: 
+                if( inclSysKeys ) {
+                    // Note that manual mapping is performed, based on the keyboard state.
+                    // I.e. we map to VK_KEYBOARD_INVISIBLE if keyboard was visible and now becomes invisible!
+                    // Otherwise we map to VK_ESCAPE, and if not consumed by user, the application will be terminated.
+                    return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
+                }
+                break;
+            case android.view.KeyEvent.KEYCODE_HOME:
+                if( inclSysKeys ) {
+                    // If not consumed by user, the application will be 'paused',
+                    // i.e. resources (GLEventListener) pulled before surface gets destroyed!
+                    return com.jogamp.newt.event.KeyEvent.VK_HOME;
+                }
+                break;
         }        
-        return 0;
+        return com.jogamp.newt.event.KeyEvent.VK_UNDEFINED;
     }
     
-    public static final com.jogamp.newt.event.WindowEvent createWindowEvent(android.view.accessibility.AccessibilityEvent event, com.jogamp.newt.Window newtSource) {
-        int type = eventTypeANDROID2NEWT.get(event.getEventType());
-        if(0xFFFFFFFF != type) {
-            return new com.jogamp.newt.event.WindowEvent(type, ((null==newtSource)?null:(Object)newtSource), event.getEventTime());
-        }
-        return null; // no mapping ..
-    }
-
-    static final int androidKeyModifiers2Newt(int androidMods) {
+    private static final int aKeyModifiers2Newt(int androidMods) {
         int newtMods = 0;
         if ((androidMods & android.view.KeyEvent.META_SYM_ON)   != 0)   newtMods |= com.jogamp.newt.event.InputEvent.META_MASK;
         if ((androidMods & android.view.KeyEvent.META_SHIFT_ON) != 0)   newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
@@ -121,69 +167,229 @@ public class AndroidNewtEventFactory {
         return newtMods;
     }
     
-    private static final int androidKeyAction2NewtEventType(int androidKeyAction) {
-        switch(androidKeyAction) {
-            case android.view.KeyEvent.ACTION_DOWN: 
-            case android.view.KeyEvent.ACTION_MULTIPLE:
-                return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
-            case android.view.KeyEvent.ACTION_UP:
-                return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
-            default: 
-                return 0;
+    public static com.jogamp.newt.event.WindowEvent createWindowEvent(android.view.accessibility.AccessibilityEvent event, com.jogamp.newt.Window newtSource) {
+        final int aType = event.getEventType();
+        final short nType = aAccessibilityEventType2Newt(aType);
+        
+        if( (short)0 != nType) {
+            return new com.jogamp.newt.event.WindowEvent(nType, ((null==newtSource)?null:(Object)newtSource), event.getEventTime());
         }
+        return null; // no mapping ..
     }
+
     
-    public static final com.jogamp.newt.event.KeyEvent[] createKeyEvents(int keyCode, android.view.KeyEvent event, com.jogamp.newt.Window newtSource) {
-        final int type = androidKeyAction2NewtEventType(event.getAction());        
-        if(Window.DEBUG_MOUSE_EVENT) {
-            System.err.println("createKeyEvent: type 0x"+Integer.toHexString(type)+", keyCode 0x"+Integer.toHexString(keyCode)+", "+event);
-        }
-        if(0xFFFFFFFF != type) {
-            final int newtKeyCode = androidKeyCode2Newt(keyCode);
-            if(0 != newtKeyCode) {
-                final Object src = (null==newtSource)?null:(Object)newtSource;
-                final long unixTime = System.currentTimeMillis() + ( event.getEventTime() - android.os.SystemClock.uptimeMillis() );
-                final int newtMods = androidKeyModifiers2Newt(event.getMetaState());
-                
-                final com.jogamp.newt.event.KeyEvent ke1 = new com.jogamp.newt.event.KeyEvent(
-                                    type, src, unixTime, newtMods, newtKeyCode, event.getDisplayLabel());
-                
-                if( com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED == type ) {
-                    return new com.jogamp.newt.event.KeyEvent[] { ke1,
-                            new com.jogamp.newt.event.KeyEvent(
-                                    com.jogamp.newt.event.KeyEvent.EVENT_KEY_TYPED,
-                                    src, unixTime, newtMods, newtKeyCode, event.getDisplayLabel()) };
-                } else {
-                    return new com.jogamp.newt.event.KeyEvent[] { ke1 };
-                }
-            }
+    public static com.jogamp.newt.event.KeyEvent createKeyEvent(android.view.KeyEvent aEvent, com.jogamp.newt.Window newtSource, boolean inclSysKeys) {
+        final com.jogamp.newt.event.KeyEvent res;
+        final short newtType = aKeyEventType2NewtEventType(aEvent.getAction());        
+        if( (short)0 != newtType) {
+            final short newtKeyCode = aKeyCode2NewtKeyCode(aEvent.getKeyCode(), inclSysKeys);
+            res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+        } else {
+            res = null;
+        }
+        if(DEBUG_KEY_EVENT) {
+            System.err.println("createKeyEvent0: "+aEvent+" -> "+res);
+        }
+        return res;
+    }
+
+    public static com.jogamp.newt.event.KeyEvent createKeyEvent(android.view.KeyEvent aEvent, short newtType, com.jogamp.newt.Window newtSource, boolean inclSysKeys) {
+        final short newtKeyCode = aKeyCode2NewtKeyCode(aEvent.getKeyCode(), inclSysKeys);
+        final com.jogamp.newt.event.KeyEvent res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+        if(DEBUG_KEY_EVENT) {
+            System.err.println("createKeyEvent1: newtType "+NEWTEvent.toHexString(newtType)+", "+aEvent+" -> "+res);
+        }
+        return res;
+    }
+    
+    public static com.jogamp.newt.event.KeyEvent createKeyEvent(android.view.KeyEvent aEvent, short newtKeyCode, short newtType, com.jogamp.newt.Window newtSource) {
+        final com.jogamp.newt.event.KeyEvent res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+        if(DEBUG_KEY_EVENT) {
+            System.err.println("createKeyEvent2: newtType "+NEWTEvent.toHexString(newtType)+", "+aEvent+" -> "+res);
+        }
+        return res;
+    }
+    
+    private static com.jogamp.newt.event.KeyEvent createKeyEventImpl(android.view.KeyEvent aEvent, short newtType, short newtKeyCode, com.jogamp.newt.Window newtSource) {
+        if( (short)0 != newtType && com.jogamp.newt.event.KeyEvent.VK_UNDEFINED != newtKeyCode ) {
+            final Object src = null==newtSource ? null : newtSource;
+            final long unixTime = System.currentTimeMillis() + ( aEvent.getEventTime() - android.os.SystemClock.uptimeMillis() );
+            final int newtMods = aKeyModifiers2Newt(aEvent.getMetaState());
+            
+            return com.jogamp.newt.event.KeyEvent.create(
+                                newtType, src, unixTime, newtMods, newtKeyCode, newtKeyCode, (char) aEvent.getUnicodeChar());
         }
         return null;
     }
+    
+    private static float maxPressure = 0.7f; // experienced maximum value (Amazon HD = 0.8f)
+    
+    /**
+     * Dynamic calibration of maximum MotionEvent pressure, starting from 0.7f
+     * <p>
+     * Specification says no pressure is 0.0f and
+     * normal pressure is 1.0f, where > 1.0f denominates very high pressure.
+     * </p>
+     * <p>
+     * Some devices exceed this spec, or better, most devices do.
+     * <ul>
+     *   <li>Asus TF2*: Pressure always > 1.0f</li>
+     *   <li>Amazon HD: Pressure always ≤ 0.8f</li>
+     * </ul>
+     * </p>
+     *   
+     * @return
+     */
+    public static float getMaxPressure() {
+        return maxPressure;
+    }
+    
+    private final int touchSlop, touchSlopSquare, doubleTapSlop, doubleTapSlopSquare;
+    
+    public AndroidNewtEventFactory(android.content.Context context, android.os.Handler handler) {
+        final android.view.ViewConfiguration configuration = android.view.ViewConfiguration.get(context);
+        touchSlop = configuration.getScaledTouchSlop();
+        touchSlopSquare = touchSlop * touchSlop;         
+        doubleTapSlop = configuration.getScaledDoubleTapSlop();
+        doubleTapSlopSquare = doubleTapSlop * doubleTapSlop;  
+        if(DEBUG_MOUSE_EVENT) {
+            System.err.println("GestureListener     touchSlop (scaled) "+touchSlop);                               
+            System.err.println("GestureListener doubleTapSlop (scaled) "+doubleTapSlop);                               
+        }
+    }
+            
+    private static void collectPointerData(MotionEvent e, int eIdx, int dIdx, final int[] x, final int[] y, final float[] pressure, short[] pointerIds, final com.jogamp.newt.event.MouseEvent.PointerType[] pointerTypes) {
+        x[dIdx] = (int)e.getX(eIdx);
+        y[dIdx] = (int)e.getY(eIdx);
+        pressure[dIdx] = e.getPressure(eIdx);
+        pointerIds[dIdx] = (short)e.getPointerId(eIdx);
+        if( pressure[dIdx] > maxPressure ) {
+            maxPressure = pressure[dIdx];
+        }
+        pointerTypes[dIdx] = aToolType2PointerType( e.getToolType(eIdx) );   
+        if(DEBUG_MOUSE_EVENT) {
+            System.err.println("createMouseEvent: ptr-data["+eIdx+" -> "+dIdx+"] "+x[dIdx]+"/"+y[dIdx]+", pressure "+pressure[dIdx]+", id "+pointerIds[dIdx]+", type "+pointerTypes[dIdx]);
+        }
+    }
+    
+    public com.jogamp.newt.event.MouseEvent[] createMouseEvents(boolean isOnTouchEvent, 
+                                                                android.view.MotionEvent event, com.jogamp.newt.Window newtSource) {
+        if(DEBUG_MOUSE_EVENT) {
+            System.err.println("createMouseEvent: isOnTouchEvent "+isOnTouchEvent+", "+event);                               
+        }
 
-    public static final com.jogamp.newt.event.MouseEvent[] createMouseEvents(android.view.MotionEvent event, com.jogamp.newt.Window newtSource) {
-        if(Window.DEBUG_MOUSE_EVENT) {
-            System.err.println("createMouseEvent: "+toString(event));
-        }
-        int type = eventTypeANDROID2NEWT.get(event.getAction());
-        if(0xFFFFFFFF != type) {
-            int rotation = 0;
-            int clickCount = 1;
+        if( event.getPressure() > maxPressure ) {
+            maxPressure = event.getPressure();
+        }
+        
+        //
+        // Prefilter Android Event (Gesture, ..) and determine final type
+        //
+        final int aType;
+        final short nType;
+        final float rotationScale = touchSlop;
+        final float[] rotationXYZ = new float[] { 0f, 0f, 0f };
+        int rotationSource = 0; // 1 - Gesture, 2 - ACTION_SCROLL        
+        {
+            final int aType0 = event.getActionMasked();
+            if( isOnTouchEvent ) {
+                switch ( aType0 ) {
+                    case MotionEvent.ACTION_DOWN:
+                    case MotionEvent.ACTION_POINTER_DOWN:
+                        gesture2FingerScrl.onDown(event);
+                        break;
+                    case MotionEvent.ACTION_UP:
+                    case MotionEvent.ACTION_POINTER_UP:
+                        gesture2FingerScrl.onUp(event);
+                        break;
+                    case MotionEvent.ACTION_MOVE:
+                        gesture2FingerScrl.onMove(event);
+                        break;
+                }
+            }
+                        
+            if( gesture2FingerScrl.gestureStarted() ) {
+                if( gesture2FingerScrl.hasGesture(true) ) {
+                    final float[] rot = gesture2FingerScrl.getScrollDistanceXY();            
+                    rotationXYZ[0] = rot[0] / rotationScale;
+                    rotationXYZ[1] = rot[1] / rotationScale;
+                    aType = ACTION_SCROLL; // 8
+                    rotationSource = 1;
+                } else {
+                    return new com.jogamp.newt.event.MouseEvent[0]; // skip, but cont. sending events
+                }
+            } else {
+                aType = aType0;
+            }
+            nType = aMotionEventType2Newt(aType);            
+        }
+        
+        if( (short)0 != nType ) {            
+            final short clickCount = 1;
             int modifiers = 0;
             
-            int[] x = new int[event.getPointerCount()];
-            int[] y = new int[event.getPointerCount()];
-            float[] pressure = new float[event.getPointerCount()];
-            int[] pointers = new int[event.getPointerCount()];
-            int index = 0;
-            while(index < event.getPointerCount()) {
-                x[index] = (int)event.getX(index);
-                y[index] = (int)event.getY(index);
-                pressure[index] = event.getPressure(index);
-                pointers[index] = event.getPointerId(index);  
-                index++;
+            if( 0 == rotationSource && AndroidVersion.SDK_INT >= 12 && ACTION_SCROLL == aType ) { // API Level 12
+                rotationXYZ[0] = event.getAxisValue(android.view.MotionEvent.AXIS_X) / rotationScale;
+                rotationXYZ[1] = event.getAxisValue(android.view.MotionEvent.AXIS_Y) / rotationScale;
+                rotationSource = 2;
             }
-
+            
+            if( 0 != rotationSource ) {
+                if( rotationXYZ[0]*rotationXYZ[0] > rotationXYZ[1]*rotationXYZ[1] ) {
+                    // Horizontal
+                    modifiers |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+                }
+                if(DEBUG_MOUSE_EVENT) {
+                    System.err.println("createMouseEvent: Gesture2FingerScrl Scroll "+rotationXYZ[0]+"/"+rotationXYZ[1]+", "+rotationScale+", mods "+modifiers+", source "+rotationSource);
+                }      
+            }
+            
+            //
+            // Determine newt-button and whether dedicated pointer is pressed
+            //
+            final int pIndex;
+            final short button;
+            switch( aType ) {
+                case android.view.MotionEvent.ACTION_POINTER_DOWN:
+                case android.view.MotionEvent.ACTION_POINTER_UP: {
+                        pIndex = event.getActionIndex();
+                        final int b = event.getPointerId(pIndex) + 1; // FIXME: Assumption that Pointer-ID starts w/ 0 !
+                        if( com.jogamp.newt.event.MouseEvent.BUTTON1 <= b && b <= com.jogamp.newt.event.MouseEvent.BUTTON_NUMBER ) {
+                            button = (short)b;
+                        } else {
+                            button = com.jogamp.newt.event.MouseEvent.BUTTON1;
+                        }
+                    }
+                    break;
+                default: {
+                        pIndex = 0;
+                        button = com.jogamp.newt.event.MouseEvent.BUTTON1;
+                    }
+            }
+            final int pCount = event.getPointerCount(); // all
+            
+            //
+            // Collect common data
+            //
+            final int[] x = new int[pCount];
+            final int[] y = new int[pCount];
+            final float[] pressure = new float[pCount];
+            final short[] pointerIds = new short[pCount];
+            final com.jogamp.newt.event.MouseEvent.PointerType[] pointerTypes = new com.jogamp.newt.event.MouseEvent.PointerType[pCount];
+            if( 0 < pCount ) {
+                if(DEBUG_MOUSE_EVENT) {
+                    System.err.println("createMouseEvent: collect ptr-data [0.."+(pCount-1)+", count "+pCount+", action "+pIndex+"], aType "+aType+", button "+button+", twoFingerScrollGesture "+gesture2FingerScrl);
+                }
+                int j = 0; 
+                // Always put action-pointer data at index 0
+                collectPointerData(event, pIndex, j++, x, y, pressure, pointerIds, pointerTypes);
+                for(int i=0; i < pCount; i++) {
+                    if( pIndex != i ) {
+                        collectPointerData(event, i, j++, x, y, pressure, pointerIds, pointerTypes);
+                    }
+                }
+            }
+            
             if(null!=newtSource) {
                 if(newtSource.isPointerConfined()) {
                     modifiers |= InputEvent.CONFINED_MASK;
@@ -195,49 +401,203 @@ public class AndroidNewtEventFactory {
                                 
             final Object src = (null==newtSource)?null:(Object)newtSource;
             final long unixTime = System.currentTimeMillis() + ( event.getEventTime() - android.os.SystemClock.uptimeMillis() );
-            final int button = pointers.length==1 ? MouseEvent.BUTTON1 : 0;
             
             final com.jogamp.newt.event.MouseEvent me1 = new com.jogamp.newt.event.MouseEvent(
-                           type,  src, unixTime,
-                           modifiers, x, y, pressure, pointers, clickCount, 
-                           button, rotation);
+                           nType,  src, unixTime,
+                           modifiers, x, y, pressure, maxPressure, pointerTypes, pointerIds, 
+                           clickCount, button, rotationXYZ, rotationScale);
             
-            if(type == com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED) {
+            if( com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED == nType ) {
                 return new com.jogamp.newt.event.MouseEvent[] { me1, 
                     new com.jogamp.newt.event.MouseEvent(
                            com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED, 
-                           src, unixTime, modifiers, x, y, pressure, pointers, clickCount, 
-                           button, rotation) };
+                           src, unixTime, modifiers, x, y, pressure, maxPressure, pointerTypes, pointerIds, 
+                           clickCount, button, rotationXYZ, rotationScale) };
             } else {
-                return new com.jogamp.newt.event.MouseEvent[] { me1 }; 
+                return new com.jogamp.newt.event.MouseEvent[] { me1 };
             }
         } 
         return null; // no mapping ..
     }
+        
+    static interface GestureHandler {
+        /** 
+         * Returns true if last on* command produced a gesture, otherwise false. 
+         * @param clear if true, method clears the gesture flag. 
+         */ 
+        public boolean hasGesture(boolean clear);
+        /** Returns true if the gesture has started */ 
+        public boolean gestureStarted();
+        /** Returns distance of the last consecutive double-tab scrolling. */ 
+        public float[] getScrollDistanceXY();
+        public void onDown(android.view.MotionEvent e);
+        public void onUp(android.view.MotionEvent e);
+        public void onMove(android.view.MotionEvent e);
+    }
     
-    
-    public static String toString(android.view.MotionEvent event) {
-        StringBuilder sb = new StringBuilder();
-        int action = event.getAction();
-        int actionCode = action & android.view.MotionEvent.ACTION_MASK;
-        sb.append("ACTION_" ).append(names[actionCode]);
-        if (actionCode == android.view.MotionEvent.ACTION_POINTER_DOWN
-                || actionCode == android.view.MotionEvent.ACTION_POINTER_UP) {
-            sb.append("(pid " ).append(
-                    action >> android.view.MotionEvent.ACTION_POINTER_ID_SHIFT);
-            sb.append(")" );
-        }
-        sb.append("[" );
-        for (int i = 0; i < event.getPointerCount(); i++) {
-            sb.append("#" ).append(i);
-            sb.append("(pid " ).append(event.getPointerId(i));
-            sb.append(")=" ).append((int) event.getX(i));
-            sb.append("," ).append((int) event.getY(i));
-            if (i + 1 < event.getPointerCount())
-                sb.append(";" );
-        }
-        sb.append("]" );
-        return sb.toString();
-    }    
+    /**
+     * Criteria related to Android parameter:
+     *    - ScaledDoubleTapSlop:
+     *       - Max 2 finger distance to start 'scroll' mode
+     *
+     *    - ScaledTouchSlop:
+     *       - Min. movement w/ 2 pointer withing ScaledDoubleTapSlop starting 'scroll' mode
+     *       - Max. distance growth in respect to initiated 2-finger distance.
+     *       
+     *    - Tolerate temporary lift of 1/2 pointer
+     *    
+     *     - Always validate pointer-id
+     */
+    private final GestureHandler gesture2FingerScrl = new GestureHandler() {
+        private final float[] scrollDistance = new float[] { 0f, 0f };
+        private int[] pIds = new int[] { -1, -1 };
+        private int startDist = -1;
+        private float downY = 0;
+        private float downX = 0;
+        private float lastY = 0;
+        private float lastX = 0;
+        private int pointerDownCount = 0;
+        private boolean withinGesture = false;
+        private boolean hasGesture = false;
+        
+        public String toString() {
+            return "Gesture2FingerScrl[in "+withinGesture+", has "+hasGesture+", pc "+pointerDownCount+"]";
+        }
+        
+        private void clear() {
+            downX = 0f;
+            downY = 0f;
+            lastX = 0f;
+            lastY = 0f;
+            startDist = -1;
+            withinGesture = false;
+            hasGesture = false;
+            pIds[0] = -1;
+            pIds[1] = -1;
+        }
+        
+        private final int getSquareDistance(float x1, float y1, float x2, float y2) {
+            final int deltaX = (int) x1 - (int) x2;
+            final int deltaY = (int) y1 - (int) y2;
+            return deltaX * deltaX + deltaY * deltaY;
+        }
+        
+        private int gesturePointers(final android.view.MotionEvent e, final int excludeIndex) {
+            int j = 0;       
+            for(int i=e.getPointerCount()-1; i>=0; i--) {
+                if( excludeIndex != i ) {
+                    final int id = e.getPointerId(i); 
+                    if( pIds[0] == id || pIds[1] == id ) {
+                        j++;
+                    }
+                }
+            }
+            return j;
+        }
+        
+        @Override
+        public boolean gestureStarted() {
+            return 0 <= startDist && withinGesture;
+        }
+        
+        @Override
+        public boolean hasGesture(boolean clear) {
+            final boolean r = hasGesture;
+            if( clear ) {
+                hasGesture = false;
+            }
+            return r;
+        }
+        
+        @Override
+        public final float[] getScrollDistanceXY() {
+            return scrollDistance;
+        }
+        
+        @Override
+        public void onDown(android.view.MotionEvent e) {
+            pointerDownCount = e.getPointerCount();
+            final int gPtr = gesturePointers(e, -1);
+            if( 2 <= gPtr ) { // pick-up dLast coordinate to cont. gesture after temp loosing 1/2 pointers
+                lastX = e.getX(0);
+                lastY = e.getY(0);
+            }
+            if(DEBUG_MOUSE_EVENT) {
+                System.err.println(this+".onDown: gPtr "+gPtr+", "+e);
+            }
+        }
+        
+        @Override
+        public void onUp(android.view.MotionEvent e) {
+            pointerDownCount = e.getPointerCount();
+            final int gPtr = gesturePointers(e, e.getActionIndex()); // w/o lifted pointer
+            if( 1 > gPtr ) { // tolerate lifting 1/2 gesture pointers temporary
+                clear();
+            }
+            pointerDownCount--; // lifted now!
+            if(DEBUG_MOUSE_EVENT) {
+                System.err.println(this+".onUp: gPtr "+gPtr+", "+e);
+            }
+        }
+        
+        @Override
+        public void onMove(android.view.MotionEvent e) {
+            pointerDownCount = e.getPointerCount();
+            if( 2 <= pointerDownCount ) {
+                final float x0 = e.getX(0);
+                final float y0 = e.getY(0);
+                final int sqDist = getSquareDistance(x0, y0, e.getX(1), e.getY(1));
+                final boolean isDistWithinDoubleTapSlop = sqDist < doubleTapSlopSquare;
+                final int dist = (int)Math.sqrt(sqDist);
+                if( !withinGesture ) {
+                    int gPtr = 0;
+                    if( isDistWithinDoubleTapSlop ) {
+                        if( 0 > startDist ) {
+                            gPtr = 2;
+                            pIds[0] = e.getPointerId(0);
+                            pIds[1] = e.getPointerId(1);
+                            downX = x0;
+                            downY = y0;
+                            lastX = x0;
+                            lastY = y0;
+                            startDist = dist;
+                        } else {
+                            gPtr = gesturePointers(e, -1);
+                            if( 2 <= gPtr ) {
+                                final int dX = (int) (x0 - downX);
+                                final int dY = (int) (y0 - downY);
+                                final int d = (dX * dX) + (dY * dY);
+                                withinGesture = d > touchSlopSquare;                            
+                            }
+                        }
+                    }
+                    if(DEBUG_MOUSE_EVENT) {
+                        final double dX = x0 - downX;
+                        final double dY = y0 - downY;
+                        final double d = Math.sqrt( (dX * dX) + (dY * dY) );
+                        System.err.println(this+".onMove.0: mDist "+d+", pStartDist "+dist+", gPtr "+gPtr+", distWithin2DTSlop "+isDistWithinDoubleTapSlop+", dLast "+lastX+"/"+lastY+", "+e);
+                    }
+                }
+                if( withinGesture ) {
+                    final int gPtr = gesturePointers(e, -1);
+                    final boolean isDistGrowthWithinTouchSlop = dist - startDist <= touchSlop; 
+                    if( 2 > gPtr || !isDistGrowthWithinTouchSlop ) {
+                        clear();
+                    } else {
+                        scrollDistance[0] = lastX - x0;
+                        scrollDistance[1] = lastY - y0;
+                        lastX = x0;
+                        lastY = y0;
+                        hasGesture = true;
+                    }
+                    if(DEBUG_MOUSE_EVENT) {
+                        System.err.println(this+".onMove.1: pStartDist "+startDist+", pDist "+dist+", gPtr "+gPtr+" ["+pIds[0]+", "+pIds[1]+"]"+
+                                           ", distWithin2DTSlop "+isDistWithinDoubleTapSlop+", distGrowthWithinTSlop "+isDistGrowthWithinTouchSlop+
+                                           ", dLast "+lastX+"/"+lastY+", d "+scrollDistance[0]+"/"+scrollDistance[1]+", "+e);
+                    }
+                }
+            }
+        }
+    };
 }
 
diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java
new file mode 100644
index 0000000..9373586
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java
@@ -0,0 +1,53 @@
+package jogamp.newt.driver.android.event;
+
+import jogamp.newt.driver.android.WindowDriver;
+import android.view.View;
+
+public class AndroidNewtEventTranslator implements View.OnKeyListener, View.OnTouchListener, View.OnFocusChangeListener, View.OnGenericMotionListener {
+        private final WindowDriver newtWindow;
+        private final AndroidNewtEventFactory factory;
+        
+        public AndroidNewtEventTranslator(WindowDriver newtWindow, android.content.Context context, android.os.Handler handler) {
+            this.newtWindow = newtWindow;
+            this.factory = new AndroidNewtEventFactory(context, handler); 
+        }
+        
+        private final boolean processTouchMotionEvents(View v, android.view.MotionEvent event, boolean isOnTouchEvent) {
+            final com.jogamp.newt.event.MouseEvent[] newtEvents = factory.createMouseEvents(isOnTouchEvent, event, newtWindow);
+            if(null != newtEvents) {
+                newtWindow.focusChanged(false, true);
+                for(int i=0; i<newtEvents.length; i++) {
+                    newtWindow.enqueueEvent(false, newtEvents[i]);
+                }
+                try { Thread.sleep((long) (1000.0F/30.0F)); }
+                catch(InterruptedException e) { }
+                return true; // consumed/handled, further interest in events
+            }
+            return false; // no mapping, no further interest in the event!            
+        }
+        
+        @Override
+        public boolean onTouch(View v, android.view.MotionEvent event) {
+            return processTouchMotionEvents(v, event, true);
+        }
+
+        @Override
+        public boolean onGenericMotion(View v, android.view.MotionEvent event) {
+            return processTouchMotionEvents(v, event, false);
+        }
+        
+        @Override
+        public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
+            final com.jogamp.newt.event.KeyEvent newtEvent = AndroidNewtEventFactory.createKeyEvent(event, newtWindow, false /* no system keys */);
+            if(null != newtEvent) {
+                newtWindow.enqueueEvent(false, newtEvent);
+                return true;
+            }
+            return false;
+        }
+        
+        @Override
+        public void onFocusChange(View v, boolean hasFocus) {
+            newtWindow.focusChanged(false, hasFocus);
+        }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
index 17eb6a2..9a16321 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
@@ -47,13 +47,15 @@ import javax.media.nativewindow.AbstractGraphicsScreen;
 import javax.media.nativewindow.CapabilitiesChooser;
 import javax.media.nativewindow.CapabilitiesImmutable;
 import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.NativeWindow;
 import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.nativewindow.VisualIDHolder;
 
-
 import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
 import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
 import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.awt.JAWTWindow;
 import com.jogamp.newt.Window;
 
 @SuppressWarnings("serial")
@@ -61,17 +63,15 @@ public class AWTCanvas extends Canvas {
   private GraphicsDevice device;
   private GraphicsConfiguration chosen;
   private AWTGraphicsConfiguration awtConfig;
-
-  private WindowDriver newtWindowImpl;
+  private volatile JAWTWindow jawtWindow=null; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
   private CapabilitiesChooser chooser=null;
   private CapabilitiesImmutable capabilities;
 
   private boolean displayConfigChanged=false;
 
-  public AWTCanvas(WindowDriver newtWindowImpl, CapabilitiesImmutable capabilities, CapabilitiesChooser chooser) {
+  public AWTCanvas(CapabilitiesImmutable capabilities, CapabilitiesChooser chooser) {
     super();
 
-    this.newtWindowImpl = newtWindowImpl;
     if(null==capabilities) {
         throw new NativeWindowException("Capabilities null");
     }
@@ -89,7 +89,7 @@ public class AWTCanvas extends Canvas {
    */
   @Override
   public void update(Graphics g) {
-    paint(g);
+    // paint(g);
   }
 
   /** Overridden to cause OpenGL rendering to be performed during
@@ -99,7 +99,6 @@ public class AWTCanvas extends Canvas {
    */
   @Override
   public void paint(Graphics g) {
-    newtWindowImpl.windowRepaint(0, 0, getWidth(), getHeight());
   }
   
   public boolean hasDeviceChanged() {
@@ -120,8 +119,7 @@ public class AWTCanvas extends Canvas {
      */
     awtConfig = chooseGraphicsConfiguration(capabilities, capabilities, chooser, device);
     if(Window.DEBUG_IMPLEMENTATION) {
-        Exception e = new Exception("Info: Created Config: "+awtConfig);
-        e.printStackTrace();
+        System.err.println(getThreadName()+": AWTCanvas.addNotify.0: Created Config: "+awtConfig);
     }
     if(null==awtConfig) {
         throw new NativeWindowException("Error: NULL AWTGraphicsConfiguration");
@@ -137,12 +135,31 @@ public class AWTCanvas extends Canvas {
     // after native peer is valid: Windows
     disableBackgroundErase();
 
+    {
+        jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
+        // trigger initialization cycle
+        jawtWindow.lockSurface();
+        jawtWindow.unlockSurface();
+    }
+
     GraphicsConfiguration gc = super.getGraphicsConfiguration();
     if(null!=gc) {
         device = gc.getDevice();
     }
+    if(Window.DEBUG_IMPLEMENTATION) {
+        System.err.println(getThreadName()+": AWTCanvas.addNotify.X");
+    }
   }
 
+  public NativeWindow getNativeWindow() {
+    final JAWTWindow _jawtWindow = jawtWindow;
+    return (null != _jawtWindow) ? _jawtWindow : null;
+  }  
+  
+  public boolean isOffscreenLayerSurfaceEnabled() {
+      return null != jawtWindow ? jawtWindow.isOffscreenLayerSurfaceEnabled() : false; 
+  }
+  
   public void removeNotify() {
       try {
         dispose();
@@ -152,6 +169,13 @@ public class AWTCanvas extends Canvas {
   }
 
   private void dispose() {
+    if( null != jawtWindow ) {
+        jawtWindow.destroy();
+        if(Window.DEBUG_IMPLEMENTATION) {
+            System.err.println(getThreadName()+": AWTCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post JAWTWindow: "+jawtWindow);
+        }
+        jawtWindow=null;
+    }
     if(null != awtConfig) {
         AbstractGraphicsDevice adevice = awtConfig.getNativeGraphicsConfiguration().getScreen().getDevice();
         String adeviceMsg=null;
@@ -160,10 +184,12 @@ public class AWTCanvas extends Canvas {
         }
         boolean closed = adevice.close();
         if(Window.DEBUG_IMPLEMENTATION) {
-            System.err.println("AWTCanvas.dispose(): closed GraphicsDevice: "+adeviceMsg+", result: "+closed);
+            System.err.println(getThreadName()+": AWTCanvas.dispose(): closed GraphicsDevice: "+adeviceMsg+", result: "+closed);
         }
     }
   }
+  
+  private String getThreadName() { return Thread.currentThread().getName(); }
 
   /**
    * Overridden to choose a GraphicsConfiguration on a parent container's
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
index 8771f5c..0cc5ddb 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
@@ -30,9 +30,12 @@ package jogamp.newt.driver.awt;
 
 import java.awt.EventQueue;
 
+import javax.media.nativewindow.NativeWindowException;
+
+import com.jogamp.common.util.RunnableTask;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
 import com.jogamp.newt.util.EDTUtil;
 
-import jogamp.common.awt.AWTEDTExecutor;
 import jogamp.newt.Debug;
 
 public class AWTEDTUtil implements EDTUtil {
@@ -69,7 +72,7 @@ public class AWTEDTUtil implements EDTUtil {
         synchronized(edtLock) { 
             waitUntilStopped();
             if(DEBUG) {
-                System.err.println(Thread.currentThread()+": EDT reset - edt: "+nedt);
+                System.err.println(Thread.currentThread()+": AWT-EDT reset - edt: "+nedt);
             }
             this.nedt = new NewtEventDispatchThread(threadGroup, name);
             this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
@@ -78,13 +81,13 @@ public class AWTEDTUtil implements EDTUtil {
 
     private final void startImpl() {
         if(nedt.isAlive()) {
-            throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt);
+            throw new RuntimeException("AWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt);
         }
         start_iter++;
         nedt.setName(name+start_iter);
         nedt.shouldStop = false;
         if(DEBUG) {
-            System.err.println(Thread.currentThread()+": EDT START - edt: "+nedt);
+            System.err.println(Thread.currentThread()+": AWT-EDT START - edt: "+nedt);
             // Thread.dumpStack();
         }
         nedt.start();
@@ -111,8 +114,8 @@ public class AWTEDTUtil implements EDTUtil {
     }
 
     @Override
-    public final void invokeStop(Runnable task) {
-        invokeImpl(true, task, true);
+    public final void invokeStop(boolean wait, Runnable task) {
+        invokeImpl(wait, task, true);
     }
 
     @Override
@@ -121,34 +124,64 @@ public class AWTEDTUtil implements EDTUtil {
     }
     
     private void invokeImpl(boolean wait, Runnable task, boolean stop) {
-        if(task == null) {
-            throw new RuntimeException("Null Runnable");
-        }
-        synchronized(edtLock) { // lock the EDT status
-            if( nedt.shouldStop ) {
-                // drop task ..
-                if(DEBUG) {
-                    System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+nedt);
-                    Thread.dumpStack();
+        Throwable throwable = null;
+        RunnableTask rTask = null;
+        Object rTaskLock = new Object();
+        synchronized(rTaskLock) { // lock the optional task execution
+            synchronized(edtLock) { // lock the EDT status
+                if( nedt.shouldStop ) {
+                    // drop task ..
+                    if(DEBUG) {
+                        System.err.println(Thread.currentThread()+": Warning: AWT-EDT about (1) to stop, won't enqueue new task: "+nedt);
+                        Thread.dumpStack();
+                    }
+                    return; 
                 }
-                return; 
-            }
-            // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
-            // Thread.dumpStack();
-            if(stop) {
-                nedt.shouldStop = true;
-                if(DEBUG) {
-                    System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt);
-                    // Thread.dumpStack();
+                // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
+                // Thread.dumpStack();
+                if(stop) {
+                    synchronized(nedt.sync) {
+                        nedt.shouldStop = true;
+                        nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
+                    }
+                    if(DEBUG) {
+                        System.err.println(Thread.currentThread()+": AWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt);
+                        // Thread.dumpStack();
+                    }
+                } else if( !nedt.isRunning() ) {
+                    // start if should not stop && not started yet
+                    startImpl();
+                }
+                if( null == task ) {
+                    wait = false;
+                } else if( isCurrentThreadEDT() ) {
+                    task.run();
+                    wait = false; // running in same thread (EDT) -> no wait
+                } else {            
+                    rTask = new RunnableTask(task,
+                                             wait ? rTaskLock : null,
+                                             true /* always catch and report Exceptions, don't disturb EDT */, 
+                                             wait ? null : System.err);
+                    AWTEDTExecutor.singleton.invoke(false, rTask);
                 }
             }
-            
-            // start if should not stop && not started yet                    
-            if( !stop && !nedt.isRunning() ) {
-                startImpl();
+            if( wait ) {
+                try {
+                    rTaskLock.wait(); // free lock, allow execution of rTask
+                } catch (InterruptedException ie) {
+                    throwable = ie;
+                }
+                if(null==throwable) {
+                    throwable = rTask.getThrowable();
+                }
+                if(null!=throwable) {
+                    if(throwable instanceof NativeWindowException) {
+                        throw (NativeWindowException)throwable;
+                    }
+                    throw new RuntimeException(throwable);
+                }
             }
         }
-        AWTEDTExecutor.singleton.invoke(wait, task);
     }    
 
     @Override
@@ -157,7 +190,7 @@ public class AWTEDTUtil implements EDTUtil {
         synchronized(edtLock) {
             _edt = nedt;
         }
-        if(!_edt.isRunning() || EventQueue.isDispatchThread()  || _edt == Thread.currentThread()) {
+        if(!_edt.isRunning() || _edt == Thread.currentThread() || EventQueue.isDispatchThread()) {
             return;
         }
         try {
@@ -170,7 +203,7 @@ public class AWTEDTUtil implements EDTUtil {
     @Override
     final public void waitUntilStopped() {
         synchronized(edtLock) {
-            if(nedt.isRunning() && nedt != Thread.currentThread() ) {
+            if(nedt.isRunning() && nedt != Thread.currentThread() && !EventQueue.isDispatchThread()) {
                 while(nedt.isRunning()) {
                     try {
                         edtLock.wait();
@@ -208,19 +241,18 @@ public class AWTEDTUtil implements EDTUtil {
         @Override
         final public void run() {
             if(DEBUG) {
-                System.err.println(getName()+": EDT run() START "+ getName());
+                System.err.println(getName()+": AWT-EDT run() START "+ getName());
             }
             RuntimeException error = null;
             try {
                 do {
                     // event dispatch
                     if(!shouldStop) {
-                        // FIXME: Determine whether we require to run the 
-                        // delivery of events (dispatch) on AWT-EDT.
-                        // Since the WindowDriver itself delivers all Window related events,
-                        // this shall not be required.
-                        //   AWTEDTExecutor.singleton.invoke(true, dispatchMessages);
-                        dispatchMessages.run();
+                        // EDT invoke thread is AWT-EDT,
+                        // hence dispatching is required to run on AWT-EDT as well.
+                        // Otherwise a deadlock may happen due to dispatched event's
+                        // triggering a locking action.
+                        AWTEDTExecutor.singleton.invoke(true, dispatchMessages);
                     }
                     // wait
                     synchronized(sync) {
@@ -239,11 +271,11 @@ public class AWTEDTUtil implements EDTUtil {
                 if(t instanceof RuntimeException) {
                     error = (RuntimeException) t;
                 } else {
-                    error = new RuntimeException("Within EDT", t);
+                    error = new RuntimeException("Within AWT-EDT", t);
                 }
             } finally {
                 if(DEBUG) {
-                    System.err.println(getName()+": EDT run() END "+ getName()+", "+error); 
+                    System.err.println(getName()+": AWT-EDT run() END "+ getName()+", "+error); 
                 }
                 synchronized(edtLock) {
                     isRunning = !shouldStop;
@@ -252,7 +284,7 @@ public class AWTEDTUtil implements EDTUtil {
                     }
                 }
                 if(DEBUG) {
-                    System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error);
+                    System.err.println(getName()+": AWT-EDT run() EXIT "+ getName()+", exception: "+error);
                 }
                 if(null!=error) {
                     throw error;
diff --git a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
index ead567d..4139951 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
@@ -38,7 +38,6 @@ import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
 import com.jogamp.newt.NewtFactory;
 import com.jogamp.newt.util.EDTUtil;
 
-import jogamp.newt.DefaultEDTUtil;
 import jogamp.newt.DisplayImpl;
 
 public class DisplayDriver extends DisplayImpl {
diff --git a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
index 6b1283a..126143e 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
@@ -34,13 +34,16 @@
 package jogamp.newt.driver.awt;
 
 import java.awt.DisplayMode;
+import java.awt.GraphicsDevice;
 
+import jogamp.newt.MonitorModeProps.Cache;
+import jogamp.newt.MonitorModeProps;
 import jogamp.newt.ScreenImpl;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
 
 import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
 import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
 
 public class ScreenDriver extends ScreenImpl {
     public ScreenDriver() {
@@ -68,14 +71,58 @@ public class ScreenDriver extends ScreenImpl {
         return idx; // pass through ... 
     }    
 
-    protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
-        final DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode();
-        if(null != mode) {
-            virtualOrigin.setX(0);
-            virtualOrigin.setY(0);
-            virtualSize.setWidth(mode.getWidth());
-            virtualSize.setHeight(mode.getHeight());
+    private static MonitorMode getModeProps(Cache cache, DisplayMode mode) {
+        int rate = mode.getRefreshRate();
+        if( DisplayMode.REFRESH_RATE_UNKNOWN == rate ) {
+            rate = ScreenImpl.default_sm_rate;
         }
+        int bpp = mode.getBitDepth();
+        if( DisplayMode.BIT_DEPTH_MULTI == bpp ) {
+            bpp= ScreenImpl.default_sm_bpp;
+        }
+        int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+        int i = 0;
+        props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+        props[i++] = mode.getWidth();
+        props[i++] = mode.getHeight();
+        props[i++] = bpp;
+        props[i++] = rate * 100;
+        props[i++] = 0; // flags
+        props[i++] = 0; // mode_idx
+        props[i++] = 0; // rotation
+        return MonitorModeProps.streamInMonitorMode(null, cache, props, 0);        
+    }
+    
+    @Override
+    protected void collectNativeMonitorModesAndDevicesImpl(Cache cache) {
+        final GraphicsDevice awtGD = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice();
+        final DisplayMode[] awtModes = awtGD.getDisplayModes();
+        for(int i=0; i<awtModes.length; i++) {
+            getModeProps(cache, awtModes[i]);
+        }        
+        final MonitorMode currentMode = getModeProps(cache, awtGD.getDisplayMode());
+
+        int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+        int i = 0;
+        props[i++] = props.length;
+        props[i++] = 0; // crt_idx
+        props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+        props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+        props[i++] = 0; // rotated viewport x
+        props[i++] = 0; // rotated viewport y
+        props[i++] = currentMode.getRotatedWidth(); // rotated viewport width
+        props[i++] = currentMode.getRotatedHeight(); // rotated viewport height
+        MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+    }
+
+    @Override
+    protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) {        
+        return null;
+    }
+
+    @Override
+    protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode) {
+        return false;
     }
     
 }
diff --git a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java
index bee43a9..c45a5ae 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java
@@ -40,11 +40,15 @@ import java.awt.Dimension;
 import java.awt.Frame;
 import java.awt.Insets;
 
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
 import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.util.Point;
 
+import jogamp.nativewindow.awt.AWTMisc;
 import jogamp.newt.WindowImpl;
 
+import com.jogamp.common.os.Platform;
 import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
 import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
 import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
@@ -70,25 +74,26 @@ public class WindowDriver extends WindowImpl {
 
     public WindowDriver(Container container) {
         super();
-        this.container = container;
+        this.awtContainer = container;
         if(container instanceof Frame) {
-            frame = (Frame) container;
+            awtFrame = (Frame) container;
         }
     }
 
     private boolean owningFrame;
-    private Container container = null;
-    private Frame frame = null; // same instance as container, just for impl. convenience
-    private AWTCanvas canvas;
+    private Container awtContainer = null;
+    /** same instance as container, just for impl. convenience */
+    private Frame awtFrame = null;
+    private AWTCanvas awtCanvas;
 
     protected void requestFocusImpl(boolean reparented) {
-        container.requestFocus();
+        awtContainer.requestFocus();
     }
 
     @Override
     protected void setTitleImpl(final String title) {
-        if (frame != null) {
-            frame.setTitle(title);
+        if (awtFrame != null) {
+            awtFrame.setTitle(title);
         }
     }
 
@@ -97,58 +102,66 @@ public class WindowDriver extends WindowImpl {
             throw new RuntimeException("Window parenting not supported in AWT, use AWTWindow(Frame) cstr for wrapping instead");
         }
 
-        if(null==container) {
-            frame = new Frame();
-            container = frame;
+        if(null==awtContainer) {
+            awtFrame = new Frame();
+            awtContainer = awtFrame;
             owningFrame=true;
         } else {
             owningFrame=false;
-            defineSize(container.getWidth(), container.getHeight());
-            definePosition(container.getX(), container.getY());            
+            defineSize(awtContainer.getWidth(), awtContainer.getHeight());
+            definePosition(awtContainer.getX(), awtContainer.getY());            
         }
-        if(null!=frame) {
-            frame.setTitle(getTitle());
+        if(null!=awtFrame) {
+            awtFrame.setTitle(getTitle());
         }
-        container.setLayout(new BorderLayout());
+        awtContainer.setLayout(new BorderLayout());
         
-        canvas = new AWTCanvas(this, capsRequested, WindowDriver.this.capabilitiesChooser);
+        if( null == awtCanvas ) {
+            awtCanvas = new AWTCanvas(capsRequested, WindowDriver.this.capabilitiesChooser);
 
-        // canvas.addComponentListener(listener);
-        container.add(canvas, BorderLayout.CENTER);
+            // canvas.addComponentListener(listener);
+            awtContainer.add(awtCanvas, BorderLayout.CENTER);
         
-        // via EDT ..
-        new AWTMouseAdapter(this).addTo(canvas); // fwd all AWT Mouse events to here
-        new AWTKeyAdapter(this).addTo(canvas); // fwd all AWT Key events to here
+            // via EDT ..
+            new AWTMouseAdapter(this).addTo(awtCanvas); // fwd all AWT Mouse events to here
+            new AWTKeyAdapter(this).addTo(awtCanvas); // fwd all AWT Key events to here
         
-        // direct w/o EDT
-        new AWTWindowAdapter(new LocalWindowListener(), this).addTo(canvas); // fwd all AWT Window events to here
+            // direct w/o EDT
+            new AWTWindowAdapter(new LocalWindowListener(), this).addTo(awtCanvas); // fwd all AWT Window events to here
+        }
 
         reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true));
         // throws exception if failed ..
         
-        setWindowHandle(1); // just a marker ..
+        final NativeWindow nw = awtCanvas.getNativeWindow();
+        if( null != nw ) {
+            setGraphicsConfiguration( awtCanvas.getAWTGraphicsConfiguration() );            
+            setWindowHandle( nw.getWindowHandle() );
+        }
     }
 
     protected void closeNativeImpl() {
-        setWindowHandle(0); // just a marker ..
-        if(null!=container) {
-            container.setVisible(false);
-            container.remove(canvas);
-            container.setEnabled(false);
-            canvas.setEnabled(false);
+        setWindowHandle(0);
+        if(null!=awtContainer) {
+            awtContainer.setVisible(false);
+            awtContainer.remove(awtCanvas);
+            awtContainer.setEnabled(false);
+            awtCanvas.setEnabled(false);
         }
-        if(owningFrame && null!=frame) {
-            frame.dispose();
+        if(owningFrame && null!=awtFrame) {
+            awtFrame.dispose();
             owningFrame=false;
-            frame = null;
         }
+        awtCanvas = null;
+        awtFrame = null;            
+        awtContainer = null;
     }
 
     @Override
     public boolean hasDeviceChanged() {
-        boolean res = canvas.hasDeviceChanged();
+        boolean res = awtCanvas.hasDeviceChanged();
         if(res) {
-            final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration();
+            final AWTGraphicsConfiguration cfg = awtCanvas.getAWTGraphicsConfiguration();
             if (null == cfg) {
                 throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this);
             }
@@ -164,17 +177,54 @@ public class WindowDriver extends WindowImpl {
     }
 
     protected void updateInsetsImpl(javax.media.nativewindow.util.Insets insets) {
-        Insets contInsets = container.getInsets();
+        Insets contInsets = awtContainer.getInsets();
         insets.setLeftWidth(contInsets.left);
         insets.setRightWidth(contInsets.right);
         insets.setTopHeight(contInsets.top);
         insets.setBottomHeight(contInsets.bottom);
     }
 
+    private void setCanvasSizeImpl(int width, int height) {
+        final Dimension szClient = new Dimension(width, height);
+        final java.awt.Window awtWindow = AWTMisc.getWindow(awtCanvas);
+        final Container c= null != awtWindow ? awtWindow : awtContainer;
+        awtCanvas.setMinimumSize(szClient);
+        awtCanvas.setPreferredSize(szClient);
+        if(DEBUG_IMPLEMENTATION) {
+            final Insets insets = c.getInsets();
+            final Dimension szContainer = new Dimension(width + insets.left + insets.right,
+                                                        height + insets.top + insets.bottom);
+            System.err.println(getThreadName()+": AWTWindow setCanvasSize: szClient "+szClient+", szCont "+szContainer+", insets "+insets);
+        }
+        awtCanvas.setSize(szClient);
+        awtCanvas.invalidate();
+        if(null != awtWindow) {
+            awtWindow.pack();
+        } else {
+            awtContainer.validate();
+        }
+    }
+    private void setFrameSizeImpl(int width, int height) {
+        final Insets insets = awtContainer.getInsets();
+        final Dimension szContainer = new Dimension(width + insets.left + insets.right,
+                                                    height + insets.top + insets.bottom);
+        if(DEBUG_IMPLEMENTATION) {
+            final Dimension szClient = new Dimension(width, height);
+            System.err.println(getThreadName()+": AWTWindow setFrameSize: szClient "+szClient+", szCont "+szContainer+", insets "+insets);
+        }
+        awtContainer.setSize(szContainer);
+        awtCanvas.invalidate();
+        awtContainer.validate();
+    }
+    
     protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
-        if(0 != ( FLAG_CHANGE_DECORATION & flags) && null!=frame) {
-            if(!container.isDisplayable()) {
-                frame.setUndecorated(isUndecorated());
+        if(DEBUG_IMPLEMENTATION) {
+            System.err.println("AWTWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
+                               getReconfigureFlagsAsString(null, flags));
+        }
+        if(0 != ( FLAG_CHANGE_DECORATION & flags) && null!=awtFrame) {
+            if(!awtContainer.isDisplayable()) {
+                awtFrame.setUndecorated(isUndecorated());
             } else {
                 if(DEBUG_IMPLEMENTATION) {
                     System.err.println(getThreadName()+": AWTWindow can't undecorate already created frame");
@@ -182,32 +232,31 @@ public class WindowDriver extends WindowImpl {
             }
         }
         
-        final Dimension szClient = new Dimension(width, height);
-        canvas.setMinimumSize(szClient);
-        canvas.setPreferredSize(szClient);
-        canvas.setSize(szClient);
-        if(DEBUG_IMPLEMENTATION) {
-            final Insets insets = container.getInsets();
-            final Dimension szContainer = new Dimension(width + insets.left + insets.right,
-                                                        height + insets.top + insets.bottom);
-            System.err.println(getThreadName()+": AWTWindow new size: szClient "+szClient+", szCont "+szContainer+", insets "+insets);
-        }
-        
         if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            if(null != frame) {
-                frame.pack();
+            if( 0 != ( FLAG_IS_VISIBLE & flags) ) {
+                setCanvasSizeImpl(width, height);
+                awtContainer.setVisible( true );
+            } else {
+                awtContainer.setVisible( false );
+            }
+        } else if( awtCanvas.getWidth() != width || awtCanvas.getHeight() != height ) {
+            if( Platform.OSType.MACOS == Platform.getOSType() && awtCanvas.isOffscreenLayerSurfaceEnabled() ) {
+                setFrameSizeImpl(width, height);
+            } else {
+                setCanvasSizeImpl(width, height);
             }
-            container.validate();            
-            container.setVisible(0 != ( FLAG_IS_VISIBLE & flags));
         }
+        defineSize(width, height); // we are on AWT-EDT .. change values immediately
         
-        container.setLocation(x, y);
+        if( awtContainer.getX() != x || awtContainer.getY() != y ) {
+            awtContainer.setLocation(x, y);
+        }
         
         if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
             if( 0 != ( FLAG_IS_VISIBLE & flags ) ) {
                 if( !hasDeviceChanged() ) {
                     // oops ??                   
-                    final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration();
+                    final AWTGraphicsConfiguration cfg = awtCanvas.getAWTGraphicsConfiguration();
                     if(null == cfg) {
                         throw new NativeWindowException("Error: !hasDeviceChanged && null == GraphicsConfiguration: "+this);
                     }
@@ -215,39 +264,37 @@ public class WindowDriver extends WindowImpl {
                 }
             }
             visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
-        } else {
-            container.invalidate();
-            if(null != frame) {
-                frame.pack();
-            }
-            container.validate();            
         }
         
         return true;
     }
 
     protected Point getLocationOnScreenImpl(int x, int y) {
-        java.awt.Point ap = canvas.getLocationOnScreen();
+        java.awt.Point ap = awtCanvas.getLocationOnScreen();
         ap.translate(x, y);
         return new Point((int)(ap.getX()+0.5),(int)(ap.getY()+0.5));
     }
    
     @Override
-    public Object getWrappedWindow() {
-        return canvas;
+    public NativeSurface getWrappedSurface() {
+        return ( null != awtCanvas ) ? awtCanvas.getNativeWindow() : null;
     }
 
     class LocalWindowListener implements com.jogamp.newt.event.WindowListener { 
         @Override
         public void windowMoved(com.jogamp.newt.event.WindowEvent e) {
-            if(null!=container) {
-                WindowDriver.this.positionChanged(false, container.getX(), container.getY());
+            if(null!=awtContainer) {
+                WindowDriver.this.positionChanged(false, awtContainer.getX(), awtContainer.getY());
             }
         }
         @Override
         public void windowResized(com.jogamp.newt.event.WindowEvent e) {
-            if(null!=canvas) {
-                WindowDriver.this.sizeChanged(false, canvas.getWidth(), canvas.getHeight(), false);
+            if(null!=awtCanvas) {
+                if(DEBUG_IMPLEMENTATION) {
+                    System.err.println("Window Resized: "+awtCanvas);
+                }
+                WindowDriver.this.sizeChanged(false, awtCanvas.getWidth(), awtCanvas.getHeight(), true);
+                WindowDriver.this.windowRepaint(false, 0, 0, getWidth(), getHeight());
             }
         }
         @Override
@@ -256,10 +303,7 @@ public class WindowDriver extends WindowImpl {
         }
         @Override
         public void windowDestroyed(WindowEvent e) {
-            if(isNativeValid()) {
-                WindowDriver.this.windowDestroyNotify(true);
-            }
-            
+            // Not fwd by AWTWindowAdapter, synthesized by NEWT
         }
         @Override
         public void windowGainedFocus(WindowEvent e) {
@@ -271,7 +315,12 @@ public class WindowDriver extends WindowImpl {
         }
         @Override
         public void windowRepaint(WindowUpdateEvent e) {
-            WindowDriver.this.windowRepaint(false, 0, 0, getWidth(), getHeight());            
+            if(null!=awtCanvas) {
+                if(DEBUG_IMPLEMENTATION) {
+                    System.err.println("Window Repaint: "+awtCanvas);
+                }
+                WindowDriver.this.windowRepaint(false, 0, 0, getWidth(), getHeight());
+            }
         }
     }
 }
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
index deb2a53..afaedff 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
@@ -35,8 +35,13 @@
 package jogamp.newt.driver.bcm.egl;
 
 import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
 
 public class ScreenDriver extends jogamp.newt.ScreenImpl {
 
@@ -58,11 +63,48 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
         return 0; // only one screen available 
     }
      
-    protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
-        virtualOrigin.setX(0);
-        virtualOrigin.setY(0);
-        virtualSize.setWidth(fixedWidth); // FIXME
-        virtualSize.setHeight(fixedHeight); // FIXME
+    @Override
+    protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+        int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+        int i = 0;
+        props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+        props[i++] = fixedWidth; // FIXME
+        props[i++] = fixedHeight; // FIXME
+        props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+        props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+        props[i++] = 0; // flags
+        props[i++] = 0; // mode_idx
+        props[i++] = 0; // rotation
+        final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+        props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+        i = 0;
+        props[i++] = props.length;
+        props[i++] = 0; // crt_idx
+        props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+        props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+        props[i++] = 0; // rotated viewport x
+        props[i++] = 0; // rotated viewport y
+        props[i++] = fixedWidth; // FIXME rotated viewport width
+        props[i++] = fixedHeight; // FIXME rotated viewport height
+        MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+    }
+
+    @Override
+    protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+        return monitor.getSupportedModes().get(0);
+    }
+
+    @Override
+    protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+        return false;
+    }
+    
+    protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) {
+        vOriginSize.setX(0);
+        vOriginSize.setY(0);
+        vOriginSize.setWidth(fixedWidth); // FIXME
+        vOriginSize.setHeight(fixedHeight); // FIXME
     }
     
     //----------------------------------------------------------------------
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
index 787d1a1..f7973de 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
@@ -29,9 +29,12 @@
 package jogamp.newt.driver.bcm.vc.iv;
 
 import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
 
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+import jogamp.newt.MonitorModeProps;
 import jogamp.newt.ScreenImpl;
 
 public class ScreenDriver extends ScreenImpl {
@@ -53,13 +56,52 @@ public class ScreenDriver extends ScreenImpl {
         return 0; // only one screen available 
     }       
     
-    protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
-        virtualOrigin.setX(0);
-        virtualOrigin.setY(0);
-        virtualSize.setWidth(cachedWidth);
-        virtualSize.setHeight(cachedHeight);
+    @Override
+    protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+        int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+        int i = 0;
+        props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+        props[i++] = cachedWidth; // width
+        props[i++] = cachedHeight; // height
+        props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+        props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+        props[i++] = 0; // flags
+        props[i++] = 0; // mode_idx
+        props[i++] = 0; // rotation
+        final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+        props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+        i = 0;
+        props[i++] = props.length;
+        props[i++] = 0; // crt_idx
+        props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+        props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+        props[i++] = 0; // rotated viewport x
+        props[i++] = 0; // rotated viewport y
+        props[i++] = cachedWidth; // rotated viewport width
+        props[i++] = cachedWidth; // rotated viewport height
+        MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+    }
+
+    @Override
+    protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+        return monitor.getSupportedModes().get(0);
+    }
+
+    @Override
+    protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+        return false;
+    }
+    
+    @Override
+    protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) {
+        vOriginSize.setX(0);
+        vOriginSize.setY(0);
+        vOriginSize.setWidth(cachedWidth);
+        vOriginSize.setHeight(cachedHeight);
     }
     
+    /** Called from {@link #initNative()}. */
     protected void setScreenSize(int width, int height) {
         cachedWidth = width;
         cachedHeight = height;
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java
index 21fbea9..e820439 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java
@@ -29,15 +29,21 @@
 package jogamp.newt.driver.bcm.vc.iv;
 
 import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsScreen;
 import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.DefaultGraphicsScreen;
 import javax.media.nativewindow.GraphicsConfigurationFactory;
 import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.VisualIDHolder;
 import javax.media.nativewindow.util.Insets;
 import javax.media.nativewindow.util.Point;
 
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+
 import jogamp.newt.WindowImpl;
+import jogamp.newt.driver.linux.LinuxEventDeviceTracker;
 import jogamp.newt.driver.linux.LinuxMouseTracker;
+import jogamp.opengl.egl.EGLDisplayUtil;
 
 public class WindowDriver extends WindowImpl {
     private static final String WINDOW_CLASS_NAME = "NewtWindow";
@@ -53,9 +59,15 @@ public class WindowDriver extends WindowImpl {
         if(0!=getParentWindowHandle()) {
             throw new RuntimeException("Window parenting not supported (yet)");
         }
+        // Create own screen/device resource instance allowing independent ownership,
+        // while still utilizing shared EGL resources.
+        final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen();
+        final EGLGraphicsDevice aDevice = (EGLGraphicsDevice) aScreen.getDevice();
+        final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(aDevice.getNativeDisplayID(), aDevice.getConnection(), aDevice.getUnitID());
+        final DefaultGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aScreen.getIndex());
         
         final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
-                capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
+                capsRequested, capsRequested, capabilitiesChooser, eglScreen, VisualIDHolder.VID_UNDEFINED);
         if (null == cfg) {
             throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
         }
@@ -76,16 +88,22 @@ public class WindowDriver extends WindowImpl {
         }
         windowHandleClose = nativeWindowHandle;
         addWindowListener(LinuxMouseTracker.getSingleton());
+        addWindowListener(LinuxEventDeviceTracker.getSingleton());
         focusChanged(false, true);        
     }
 
     protected void closeNativeImpl() {
+        final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getGraphicsConfiguration().getScreen().getDevice();
+        
         removeWindowListener(LinuxMouseTracker.getSingleton());
+        removeWindowListener(LinuxEventDeviceTracker.getSingleton());
         
         if(0!=windowHandleClose) {
             CloseWindow(windowHandleClose, windowUserData);
             windowUserData=0;
         }
+        
+        eglDevice.close();
     }
 
     protected void requestFocusImpl(boolean reparented) { 
diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
index 8eed14d..4c47eb0 100644
--- a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
@@ -36,8 +36,13 @@ package jogamp.newt.driver.intel.gdl;
 
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
 
 public class ScreenDriver extends jogamp.newt.ScreenImpl {
 
@@ -60,11 +65,48 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
         return 0; // only one screen available 
     }
         
-    protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
-        virtualOrigin.setX(0);
-        virtualOrigin.setY(0);
-        virtualSize.setWidth(cachedWidth);
-        virtualSize.setHeight(cachedHeight);
+    @Override
+    protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+        int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+        int i = 0;
+        props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+        props[i++] = cachedWidth; // width
+        props[i++] = cachedHeight; // height
+        props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+        props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+        props[i++] = 0; // flags
+        props[i++] = 0; // mode_idx
+        props[i++] = 0; // rotation
+        final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+        props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+        i = 0;
+        props[i++] = props.length;
+        props[i++] = 0; // crt_idx
+        props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+        props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+        props[i++] = 0; // rotated viewport x
+        props[i++] = 0; // rotated viewport y
+        props[i++] = cachedWidth; // rotated viewport width
+        props[i++] = cachedWidth; // rotated viewport height
+        MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+    }
+
+    @Override
+    protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+        return monitor.getSupportedModes().get(0);
+    }
+
+    @Override
+    protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+        return false;
+    }
+    
+    protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) {
+        vOriginSize.setX(0);
+        vOriginSize.setY(0);
+        vOriginSize.setWidth(cachedWidth);
+        vOriginSize.setHeight(cachedHeight);
     }
     
     //----------------------------------------------------------------------
diff --git a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
index 656bcf5..dc87c3c 100644
--- a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
@@ -35,9 +35,12 @@
 package jogamp.newt.driver.kd;
 
 import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
 
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+import jogamp.newt.MonitorModeProps;
 import jogamp.newt.ScreenImpl;
 
 public class ScreenDriver extends ScreenImpl {
@@ -58,11 +61,48 @@ public class ScreenDriver extends ScreenImpl {
         return 0; // only one screen available 
     }       
     
-    protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
-        virtualOrigin.setX(0);
-        virtualOrigin.setY(0);
-        virtualSize.setWidth(cachedWidth);
-        virtualSize.setHeight(cachedHeight);
+    @Override
+    protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+        int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+        int i = 0;
+        props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+        props[i++] = cachedWidth; // width
+        props[i++] = cachedHeight; // height
+        props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+        props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+        props[i++] = 0; // flags
+        props[i++] = 0; // mode_idx
+        props[i++] = 0; // rotation
+        final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+        props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+        i = 0;
+        props[i++] = props.length;
+        props[i++] = 0; // crt_idx
+        props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+        props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+        props[i++] = 0; // rotated viewport x
+        props[i++] = 0; // rotated viewport y
+        props[i++] = cachedWidth; // rotated viewport width
+        props[i++] = cachedWidth; // rotated viewport height
+        MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+    }
+
+    @Override
+    protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+        return monitor.getSupportedModes().get(0);
+    }
+
+    @Override
+    protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+        return false;
+    }
+    
+    protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) {
+        vOriginSize.setX(0);
+        vOriginSize.setY(0);
+        vOriginSize.setWidth(cachedWidth);
+        vOriginSize.setHeight(cachedHeight);
     }
     
     protected void sizeChanged(int w, int h) {
diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java
new file mode 100644
index 0000000..e68b91d
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java
@@ -0,0 +1,959 @@
+/**
+ * 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 jogamp.newt.driver.linux;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.Integer;
+import java.lang.Runnable;
+import java.lang.String;
+import java.lang.Thread;
+import java.nio.ByteBuffer;
+
+import jogamp.newt.WindowImpl;
+
+import com.jogamp.common.nio.StructAccessor;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.event.WindowUpdateEvent;
+import com.jogamp.newt.event.KeyEvent;
+
+/**
+ * Experimental native event device tracker thread for GNU/Linux
+ * just reading <code>/dev/input/event*</code>
+ * within it's own polling thread.
+ */
+
+public class LinuxEventDeviceTracker implements WindowListener {
+
+    private static final LinuxEventDeviceTracker ledt;
+
+
+    static {
+        ledt = new LinuxEventDeviceTracker();
+        final Thread t = new Thread(ledt.eventDeviceManager, "NEWT-LinuxEventDeviceManager");
+        t.setDaemon(true);
+        t.start();
+    }
+
+    public static LinuxEventDeviceTracker getSingleton() {
+        return ledt;
+    }
+
+    private WindowImpl focusedWindow = null;
+    private EventDeviceManager eventDeviceManager = new EventDeviceManager();
+
+    /*
+      The devices are in /dev/input:
+
+	crw-r--r--   1 root     root      13,  64 Apr  1 10:49 event0
+	crw-r--r--   1 root     root      13,  65 Apr  1 10:50 event1
+	crw-r--r--   1 root     root      13,  66 Apr  1 10:50 event2
+	crw-r--r--   1 root     root      13,  67 Apr  1 10:50 event3
+	...
+
+      And so on up to event31.
+     */
+    private EventDevicePoller[] eventDevicePollers = new EventDevicePoller[32];
+
+    @Override
+    public void windowResized(WindowEvent e) { }
+
+    @Override
+    public void windowMoved(WindowEvent e) { }
+
+    @Override
+    public void windowDestroyNotify(WindowEvent e) {
+        Object s = e.getSource();
+        if(focusedWindow == s) {
+            focusedWindow = null;
+        }
+    }
+
+    @Override
+    public void windowDestroyed(WindowEvent e) { }
+
+    @Override
+    public void windowGainedFocus(WindowEvent e) {
+        Object s = e.getSource();
+        if(s instanceof WindowImpl) {
+            focusedWindow = (WindowImpl) s;
+        }
+    }
+
+    @Override
+    public void windowLostFocus(WindowEvent e) {
+        Object s = e.getSource();
+        if(focusedWindow == s) {
+            focusedWindow = null;
+        }
+    }
+
+    public static void main(String[] args ){
+        System.setProperty("newt.debug.Window.KeyEvent", "true");
+        LinuxEventDeviceTracker.getSingleton();
+        try {
+            while(true) {
+                Thread.sleep(1000);
+            } 
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void windowRepaint(WindowUpdateEvent e) { }
+
+    class EventDeviceManager implements Runnable {
+
+        private volatile boolean stop = false;
+
+        @Override
+        public void run() {
+            File f = new File("/dev/input/");
+            int number;
+            while(!stop){
+                for(String path:f.list()){
+                    if(path.startsWith("event")) {
+                        String stringNumber = path.substring(5);
+                        number = Integer.parseInt(stringNumber);
+                        if(number<32&&number>=0) {
+                            if(eventDevicePollers[number]==null){
+                                eventDevicePollers[number] = new EventDevicePoller(number);
+                                Thread t = new Thread(eventDevicePollers[number], "NEWT-LinuxEventDeviceTracker-event"+number);
+                                t.setDaemon(true);
+                                t.start();
+                            } else if(eventDevicePollers[number].stop) {
+                                eventDevicePollers[number]=null;
+                            }
+                        }
+                    }
+                }
+                try {
+                    Thread.sleep(2000);
+                } catch (InterruptedException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    class EventDevicePoller implements Runnable {
+
+        private volatile boolean stop = false;
+        private String eventDeviceName;
+
+        public EventDevicePoller(int eventDeviceNumber){
+            this.eventDeviceName="/dev/input/event"+eventDeviceNumber;
+        }
+
+        @Override
+        public void run() {
+            final byte[] b = new byte[16];
+            /**
+             * The Linux input event interface.
+             * http://www.kernel.org/doc/Documentation/input/input.txt
+             * 
+             * struct input_event {
+             *  struct timeval time;
+             *	unsigned short type;
+             *	unsigned short code;
+             *	unsigned int value;
+             * };
+             */
+            ByteBuffer bb = ByteBuffer.wrap(b);
+            StructAccessor s = new StructAccessor(bb);
+            final File f = new File(eventDeviceName);
+            f.setReadOnly();
+            InputStream fis;
+            try {
+                fis = new FileInputStream(f);
+            } catch (FileNotFoundException e) {
+                stop=true;
+                return;
+            }
+
+            int timeSeconds;
+            int timeSecondFraction;
+            short type;
+            short code;
+            int value;
+
+            short keyCode=KeyEvent.VK_UNDEFINED;
+            char keyChar=' ';
+            short eventType=0;
+            int modifiers=0;
+
+            loop:
+                while(!stop) {
+                    int remaining=16;
+                    while(remaining>0) {
+                        int read = 0;
+                        try {
+                            read = fis.read(b, 0, remaining);
+                        } catch (IOException e) {
+                            stop = true;
+                            break loop;
+                        }
+                        if(read<0) {
+                            stop = true; // EOF of event device file !?
+                            break loop;
+                        } else {
+                            remaining -= read;
+                        }
+                    }
+
+                    timeSeconds = s.getIntAt(0);
+                    timeSecondFraction = s.getShortAt(4);
+                    type = s.getShortAt(8);
+                    code = s.getShortAt(10);
+                    value = s.getIntAt(12);
+
+
+                    /*
+                     * Linux sends Keyboard events in the following order:
+                     * EV_MSC (optional, contains scancode)
+                     * EV_KEY
+                     * SYN_REPORT (sent before next key)
+                     */
+
+                    switch(type) {
+                    case 0: // SYN_REPORT
+                        // Clear
+                        eventType = 0;
+                        keyCode = KeyEvent.VK_UNDEFINED;
+                        keyChar = 0; // Print null for unprintable char.
+                        if(Window.DEBUG_KEY_EVENT) {
+                            System.out.println("[SYN_REPORT----]");
+                        }
+                        break;
+                    case 1: // EV_KEY
+                        keyCode = LinuxEVKey2NewtVKey(code); // The device independent code.
+                        keyChar = NewtVKey2Unicode(keyCode, modifiers); // The printable character w/ key modifiers.						
+                        if(Window.DEBUG_KEY_EVENT) {
+                            System.out.println("[EV_KEY: [time "+timeSeconds+":"+timeSecondFraction+"] type "+type+" / code "+code+" = value "+value);
+                        }
+
+                        switch(value) {
+                        case 0:
+                            eventType=KeyEvent.EVENT_KEY_RELEASED;
+
+                            switch(keyCode) {
+                            case KeyEvent.VK_SHIFT:
+                                modifiers &= ~InputEvent.SHIFT_MASK;
+                                break;
+                            case KeyEvent.VK_ALT:
+                                modifiers &= ~InputEvent.ALT_MASK;
+                                break;
+                            case KeyEvent.VK_ALT_GRAPH:
+                                modifiers &= ~InputEvent.ALT_GRAPH_MASK;
+                                break;
+                            case KeyEvent.VK_CONTROL:
+                                modifiers &= ~InputEvent.CTRL_MASK;
+                                break;
+                            }
+
+                            if(null != focusedWindow) {
+                                focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyCode, keyChar);
+                            }
+                            if(Window.DEBUG_KEY_EVENT) {
+                                System.out.println("[event released] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+                            }
+                            break;
+                        case 1:
+                            eventType=KeyEvent.EVENT_KEY_PRESSED;
+
+                            switch(keyCode) {
+                            case KeyEvent.VK_SHIFT:
+                                modifiers |= InputEvent.SHIFT_MASK;
+                                break;
+                            case KeyEvent.VK_ALT:
+                                modifiers |= InputEvent.ALT_MASK;
+                                break;
+                            case KeyEvent.VK_ALT_GRAPH:
+                                modifiers |= InputEvent.ALT_GRAPH_MASK;
+                                break;
+                            case KeyEvent.VK_CONTROL:
+                                modifiers |= InputEvent.CTRL_MASK;
+                                break;
+                            }
+
+                            if(null != focusedWindow) {
+                                focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyCode, keyChar);
+                            }
+                            if(Window.DEBUG_KEY_EVENT) {
+                                System.out.println("[event pressed] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+                            }
+                            break;
+                        case 2:
+                            eventType=KeyEvent.EVENT_KEY_PRESSED;
+                            modifiers |= InputEvent.AUTOREPEAT_MASK;
+
+                            switch(keyCode) {
+                            case KeyEvent.VK_SHIFT:
+                                modifiers |= InputEvent.SHIFT_MASK;
+                                break;
+                            case KeyEvent.VK_ALT:
+                                modifiers |= InputEvent.ALT_MASK;
+                                break;
+                            case KeyEvent.VK_ALT_GRAPH:
+                                modifiers |= InputEvent.ALT_GRAPH_MASK;
+                                break;
+                            case KeyEvent.VK_CONTROL:
+                                modifiers |= InputEvent.CTRL_MASK;
+                                break;
+                            }
+
+                            if(null != focusedWindow) {
+                                //Send syntetic autorepeat release
+                                focusedWindow.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keyCode, keyChar);
+
+                                focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyCode, keyChar);
+                            }
+                            if(Window.DEBUG_KEY_EVENT) {
+                                System.out.println("[event released auto] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+                                System.out.println("[event pressed auto] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+                            }
+                            modifiers &= ~InputEvent.AUTOREPEAT_MASK;
+                            break;
+                        }
+                        break;
+                    case 4: // EV_MSC
+                        if(code==4) { // MSC_SCAN
+                            // scancode ignore, linux kernel specific
+                        }
+                        break;
+                        // TODO: handle joystick events
+                        // TODO: handle mouse events
+                        // TODO: handle headphone/hdmi connector events
+                    default: // Print number.
+                        if(Window.DEBUG_KEY_EVENT) {
+                            System.out.println("TODO EventDevicePoller: [time "+timeSeconds+":"+timeSecondFraction+"] type "+type+" / code "+code+" = value "+value);
+                        }
+                    }
+                }
+
+            if(null != fis) {
+                try {
+                    fis.close();
+                } catch (IOException e) {
+                }
+            }
+            stop=true;
+        }
+
+        private char NewtVKey2Unicode(short VK, int modifiers) {
+            if( KeyEvent.isPrintableKey(VK, true) ) {
+                if((modifiers & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) {
+                    return (char)VK;
+                } else {
+                    return String.valueOf((char)VK).toLowerCase().charAt(0);
+                }
+            }
+            return 0;
+        }
+
+        @SuppressWarnings("unused")
+        private char LinuxEVKey2Unicode(short EVKey) {
+            // This is the stuff normally mapped by a system keymap
+
+            switch(EVKey) {
+            case 17: // w
+                return 'w';
+            case 31: // s
+                return 's';
+            case 30: // a
+                return 'a';
+            case 32: // d
+                return 'd';
+            case 1: // ESC
+                return 27;
+            case 28: // Enter
+            case 96: // Keypad Enter
+                return '\n';
+            case 57: // Space
+                return ' ';
+            case 11: // 0
+            case 82: // Numpad 0
+                return '0';
+            case 2: // 1
+            case 79: // Numpad 1
+                return '1';
+            case 3: // 2
+            case 80: // Numpad 1
+                return '2';
+            case 4: // 3
+            case 81: // Numpad 3
+                return '3';
+            case 5: // 4
+            case 75: // Numpad 4
+                return '4';
+            case 6: // 5
+            case 76: // Numpad 5
+                return '5';
+            case 7: // 6
+            case 77: // Numpad 6
+                return '6';
+            case 8: // 7
+            case 71: // Numpad 7
+                return '7';
+            case 9: // 8
+            case 72: // Numpad 8
+                return '8';
+            case 10: // 9
+            case 73: // Numpad 9
+                return '9';
+
+            default:
+            }
+
+            return 0;
+        }
+
+        private short LinuxEVKey2NewtVKey(short EVKey) {
+
+            switch(EVKey) {
+            case 1: // ESC
+                return KeyEvent.VK_ESCAPE;
+            case 2: // 1
+                return KeyEvent.VK_1;
+            case 79: // Numpad 1
+                return KeyEvent.VK_NUMPAD1;
+            case 3: // 2
+                return KeyEvent.VK_2;
+            case 80: // Numpad 2
+                return KeyEvent.VK_NUMPAD2;
+            case 4: // 3
+                return KeyEvent.VK_3;
+            case 81: // Numpad 3
+                return KeyEvent.VK_NUMPAD3;
+            case 5: // 4
+                return KeyEvent.VK_4;
+            case 75: // Numpad 4
+                return KeyEvent.VK_NUMPAD4;
+            case 6: // 5
+                return KeyEvent.VK_5;
+            case 76: // Numpad 5
+                return KeyEvent.VK_NUMPAD5;
+            case 7: // 6
+                return KeyEvent.VK_6;
+            case 77: // Numpad 6
+                return KeyEvent.VK_NUMPAD6;
+            case 8: // 7
+                return KeyEvent.VK_7;
+            case 71: // Numpad 7
+                return KeyEvent.VK_NUMPAD7;
+            case 9: // 8
+                return KeyEvent.VK_8;
+            case 72: // Numpad 8
+                return KeyEvent.VK_NUMPAD8;
+            case 10: // 9
+                return KeyEvent.VK_9;
+            case 73: // Numpad 9
+                return KeyEvent.VK_NUMPAD9;
+            case 11: // 0
+                return KeyEvent.VK_0;
+            case 82: // Numpad 0
+                return KeyEvent.VK_NUMPAD0;
+            case 12:
+                return KeyEvent.VK_MINUS;
+            case 13:
+                return KeyEvent.VK_EQUALS;
+            case 14: // Backspace
+                return KeyEvent.VK_BACK_SPACE;
+
+            case 15:
+                return KeyEvent.VK_TAB;
+            case 16:
+                return KeyEvent.VK_Q;
+            case 17: // w
+                return KeyEvent.VK_W;
+            case 18:
+                return KeyEvent.VK_E;
+            case 19:
+                return KeyEvent.VK_R;
+            case 20:
+                return KeyEvent.VK_T;
+            case 21:
+                return KeyEvent.VK_Y;
+            case 22:
+                return KeyEvent.VK_U;
+            case 23:
+                return KeyEvent.VK_I;
+            case 24:
+                return KeyEvent.VK_O;
+            case 25:
+                return KeyEvent.VK_P;
+            case 26: // left brace
+                return KeyEvent.VK_LEFT_PARENTHESIS;
+            case 27: // right brace
+                return KeyEvent.VK_RIGHT_PARENTHESIS;
+            case 28: // Enter
+            case 96: // Keypad Enter
+                return KeyEvent.VK_ENTER;
+
+            case 29: // left ctrl
+                return KeyEvent.VK_CONTROL;
+            case 30: // a
+                return KeyEvent.VK_A;
+            case 31: // s
+                return KeyEvent.VK_S;
+            case 32: // d
+                return KeyEvent.VK_D;
+            case 33:
+                return KeyEvent.VK_F;
+            case 34:
+                return KeyEvent.VK_G;
+            case 35:
+                return KeyEvent.VK_H;
+            case 36:
+                return KeyEvent.VK_J;
+            case 37:
+                return KeyEvent.VK_K;
+            case 38:
+                return KeyEvent.VK_L;
+            case 39:
+                return KeyEvent.VK_SEMICOLON;
+            case 40: // apostrophe
+                return KeyEvent.VK_QUOTE;
+            case 41: // grave
+                return KeyEvent.VK_BACK_QUOTE;
+
+            case 42: // left shift
+                return KeyEvent.VK_SHIFT;
+            case 43:
+                return KeyEvent.VK_BACK_SLASH;
+            case 44:
+                return KeyEvent.VK_Z;
+            case 45:
+                return KeyEvent.VK_X;
+            case 46:
+                return KeyEvent.VK_C;
+            case 47:
+                return KeyEvent.VK_V;
+            case 48:
+                return KeyEvent.VK_B;
+            case 49:
+                return KeyEvent.VK_N;
+            case 50:
+                return KeyEvent.VK_M;
+            case 51:
+                return KeyEvent.VK_COMMA;
+            case 52: // dot
+                return KeyEvent.VK_PERIOD;
+            case 53:
+                return KeyEvent.VK_SLASH;
+            case 54:
+                return KeyEvent.VK_SHIFT;
+            case 55: // kp asterisk
+                return KeyEvent.VK_ASTERISK;
+            case 56: // left alt
+                return KeyEvent.VK_ALT;
+            case 57: // Space
+                return KeyEvent.VK_SPACE;
+            case 58:
+                return KeyEvent.VK_CAPS_LOCK;
+
+            case 59:
+                return KeyEvent.VK_F1;
+            case 60:
+                return KeyEvent.VK_F2;
+            case 61:
+                return KeyEvent.VK_F3;
+            case 62:
+                return KeyEvent.VK_F4;
+            case 63:
+                return KeyEvent.VK_F5;
+            case 64:
+                return KeyEvent.VK_F6;
+            case 65:
+                return KeyEvent.VK_F7;
+            case 66:
+                return KeyEvent.VK_F8;
+            case 67:
+                return KeyEvent.VK_F9;
+            case 68:
+                return KeyEvent.VK_F10;
+
+            case 69:
+                return KeyEvent.VK_NUM_LOCK;
+            case 70:
+                return KeyEvent.VK_SCROLL_LOCK;
+
+            case 74: // kp minus
+                return KeyEvent.VK_MINUS;
+            case 78: // kp plus
+                return KeyEvent.VK_PLUS;
+            case 83: // kp dot
+                return KeyEvent.VK_PERIOD;
+
+            // TODO: add mappings for japanese special buttons
+            case 85: // zenkakuhankaku
+            case 86: // 102nd
+                break; // FIXME
+
+            case 87:
+                return KeyEvent.VK_F11;
+            case 88:
+                return KeyEvent.VK_F12;
+
+            case 89: // ro
+                return KeyEvent.VK_ROMAN_CHARACTERS;
+            case 90: // Katakana
+                return KeyEvent.VK_KATAKANA;
+            case 91:
+                return KeyEvent.VK_HIRAGANA;
+
+            case 92: // kenkan
+                break; // FIXME
+            case 93: // katakana hiragana
+                break; // FIXME
+            case 94: // mu henkan
+                break; // FIXME
+            case 95: // kp jp comma
+                break; // FIXME
+
+            case 97: // right ctrl
+                return KeyEvent.VK_CONTROL;
+            case 98: // kp slash
+                return KeyEvent.VK_SLASH;
+
+            case 99: // sysrq
+                break; // FIXME
+
+            case 100: // right alt
+                return KeyEvent.VK_ALT;
+            case 101: // linefeed
+                break; // FIXME
+            case 102: // home
+                return KeyEvent.VK_HOME;
+            case 103: // KEY_UP
+                return KeyEvent.VK_UP;
+            case 104:
+                return KeyEvent.VK_PAGE_UP;
+            case 105: // KEY_LEFT
+                return KeyEvent.VK_LEFT;
+            case 106: // KEY_RIGHT
+                return KeyEvent.VK_RIGHT;
+            case 107:
+                return KeyEvent.VK_END;
+            case 108: // KEY_DOWN
+                return KeyEvent.VK_DOWN;
+            case 109:
+                return KeyEvent.VK_PAGE_DOWN;
+            case 110:
+                return KeyEvent.VK_INSERT;
+            case 111: // del
+                return KeyEvent.VK_DELETE;
+
+            case 112: // macro
+                break; // FIXME DEAD_MACRON?
+            case 113: // mute
+                break; // FIXME
+            case 114: // vol up
+                break; // FIXME
+            case 115: // vol down
+                break; // FIXME
+            case 116: // power
+                break; // FIXME
+
+            case 117: // kp equals
+                return KeyEvent.VK_EQUALS;
+            case 118: // kp plus minux
+                break; // FIXME
+            case 119: // pause
+                return KeyEvent.VK_PAUSE;
+            case 120: // scale AL compiz scale expose
+                break; // FIXME
+            case 121: // kp comma
+                return KeyEvent.VK_COMMA;
+            case 122: // hangeul
+                break; // FIXME
+            case 123: // hanja
+                break; // FIXME
+            case 124: // yen
+                break; // FIXME
+
+            case 125: // left meta
+            case 126: // right meta
+                return KeyEvent.VK_META;
+            case 127: // compose
+                return KeyEvent.VK_COMPOSE;
+
+            case 128: // stop
+                return KeyEvent.VK_STOP;
+            case 129: // again
+                return KeyEvent.VK_AGAIN;
+            case 130: // properties
+                return KeyEvent.VK_PROPS;
+            case 131: // undo
+                return KeyEvent.VK_UNDO;
+            case 132: // front
+                break; // FIXME
+            case 133: // copy
+                return KeyEvent.VK_COPY;
+            case 134: // open
+                break; // FIXME
+            case 135: // paste
+                return KeyEvent.VK_PASTE;
+            case 136: // find
+                return KeyEvent.VK_FIND;
+            case 137: // cut
+                return KeyEvent.VK_CUT;
+            case 138: // help
+                return KeyEvent.VK_HELP;
+            case 139: // menu
+                break; // FIXME
+            case 140: // calc
+                break; // FIXME
+            case 141: // setup
+                break; // FIXME
+            case 142: // sleep
+                break; // FIXME
+            case 143: // wakeup
+                break; // FIXME
+            case 144: // file
+                break; // FIXME
+            case 145: // send file
+                break; // FIXME
+            case 146: // delete file
+                break; // FIXME
+            case 147: // xfer
+                break; // FIXME
+            case 148: // prog1
+                break; // FIXME
+            case 149: // prog2
+                break; // FIXME
+            case 150: // www
+                break; // FIXME
+            case 151: // msdos
+                break; // FIXME
+            case 152: // coffee
+                break; // FIXME
+            case 153: // direction
+                break; // FIXME
+            case 154: // cycle windows
+                break; // FIXME
+            case 155: // mail
+                break; // FIXME
+            case 156: // bookmarks
+                break; // FIXME
+            case 157: // computer
+                break; // FIXME
+            case 158: // back
+                break; // FIXME
+            case 159: // forward
+                break; // FIXME
+            case 160: // close cd
+                break; // FIXME
+            case 161: // eject cd
+                break; // FIXME
+            case 162: // eject close cd
+                break; // FIXME
+            case 163: // next song
+                break; // FIXME
+            case 164: // play pause
+                break; // FIXME
+            case 165: // previous song
+                break; // FIXME
+            case 166: // stop cd
+                break; // FIXME
+            case 167: // record
+                break; // FIXME
+            case 168: // rewind
+                break; // FIXME
+            case 169: // phone
+                break; // FIXME
+            case 170: // ISO
+                break; // FIXME
+            case 171: // config
+                break; // FIXME
+            case 172: // home page
+                break; // FIXME
+            case 173: // refresh
+                break; // FIXME
+            case 174: // exit
+                break; // FIXME
+            case 175: // move
+                break; // FIXME
+            case 176: // edit
+                break; // FIXME
+            case 177: // scroll up
+                break; // FIXME PAGE_UP?
+            case 178: // scroll down
+                break; // FIXME PAGE_DOWN?
+            case 179: // kp left paren
+                return KeyEvent.VK_LEFT_PARENTHESIS;
+            case 180: // kp right paren
+                return KeyEvent.VK_RIGHT_PARENTHESIS;
+            case 181: // new
+                break; // FIXME
+            case 182: // redo
+                break; // FIXME
+
+            case 183: // F13
+                return KeyEvent.VK_F13;
+            case 184: // F14
+                return KeyEvent.VK_F14;
+            case 185: // F15
+                return KeyEvent.VK_F15;
+            case 186: // F16
+                return KeyEvent.VK_F16;
+            case 187: // F17
+                return KeyEvent.VK_F17;
+            case 188: // F18
+                return KeyEvent.VK_F18;
+            case 189: // F19
+                return KeyEvent.VK_F19;
+            case 190: // F20
+                return KeyEvent.VK_F20;
+            case 191: // F21
+                return KeyEvent.VK_F21;
+            case 192: // F22
+                return KeyEvent.VK_F22;
+            case 193: // F23
+                return KeyEvent.VK_F23;
+            case 194: // F24
+                return KeyEvent.VK_F24;
+
+            case 200: // play cd
+                break; // FIXME
+            case 201: // pause cd
+                break; // FIXME
+            case 202: // prog 3
+                break; // FIXME
+            case 203: // prog 4
+                break; // FIXME
+            case 204: // dashboard
+                break; // FIXME
+            case 205: // suspend
+                break; // FIXME
+            case 206: // close
+                break; // FIXME
+            case 207: // play
+                break; // FIXME
+            case 208: // fast forward
+                break; // FIXME
+            case 210: // print
+                return KeyEvent.VK_PRINTSCREEN; // FIXME ?
+            case 211: // HP
+                break; // FIXME
+            case 212: // camera
+                break; // FIXME
+            case 213: // sound
+                break; // FIXME
+            case 214: // question
+                break; // FIXME
+            case 215: // email
+                break; // FIXME
+            case 216: // chat
+                break; // FIXME
+            case 217: // search
+                break; // FIXME
+            case 218: // connect
+                break; // FIXME
+            case 219: // finance
+                break; // FIXME
+            case 220: // sport
+                break; // FIXME
+            case 221: // shop
+                break; // FIXME
+            case 222: // alt erase
+                break; // FIXME
+            case 223: // cancel
+                break; // FIXME
+            case 224: // brightness down
+                break; // FIXME
+            case 225: // brightness up
+                break; // FIXME
+            case 226: // media
+                break; // FIXME
+            case 227: // switch video mode
+                break; // FIXME
+            case 228: // kb dillum toggle
+                break; // FIXME
+            case 229: // kb dillum down
+                break; // FIXME
+            case 230: // kb dillum up
+                break; // FIXME
+            case 231: // send
+                break; // FIXME
+            case 232: // reply
+                break; // FIXME
+            case 233: // forward mail
+                break; // FIXME
+            case 234: // save
+                break; // FIXME
+            case 235: // documents
+                break; // FIXME
+            case 236: // battery
+                break; // FIXME
+            case 237: // bluetooth
+                break; // FIXME
+            case 238: // wlan
+                break; // FIXME
+            case 239: // UWB
+                break; // FIXME
+            case 240: // unknown
+                return KeyEvent.VK_UNDEFINED;
+            case 241: // video next
+                break; // FIXME
+            case 242: // video prev
+                break; // FIXME
+            case 243: // brightness cycle
+                break; // FIXME
+            case 244: // brightness zero
+                break; // FIXME
+            case 245: // display off
+                break; // FIXME
+            case 246: // wimax
+                break; // FIXME
+            case 247: // rf kill radio off
+                break; // FIXME
+            case 248: // mic mute
+                break; // FIXME
+
+            default: 
+            }
+
+            if(Window.DEBUG_KEY_EVENT) {
+                System.out.println("TODO LinuxEVKey2NewtVKey: Unmapped EVKey "+EVKey);
+            }
+
+            return KeyEvent.VK_UNDEFINED;
+        }
+    }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java
index 885649d..0d6278b 100644
--- a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java
+++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java
@@ -65,10 +65,10 @@ public class LinuxMouseTracker implements WindowListener {
     private volatile boolean stop = false;
     private int x = 0;
     private int y = 0;
-    private int buttonDown = 0;
+    private short buttonDown = 0;
     private int old_x = 0;
     private int old_y = 0;
-    private int old_buttonDown = 0;
+    private short old_buttonDown = 0;
     private WindowImpl focusedWindow = null;
     private MouseDevicePoller mouseDevicePoller = new MouseDevicePoller();
     
@@ -152,7 +152,7 @@ public class LinuxMouseTracker implements WindowListener {
                 yd=b[2];
             
                 x+=xd;
-                y+=yd;
+                y-=yd;
                 
                 if(x<0) {
                     x=0;
@@ -161,6 +161,7 @@ public class LinuxMouseTracker implements WindowListener {
                     y=0;
                 }
                 
+                buttonDown = 0;
                 if(lb) {
                     buttonDown = MouseEvent.BUTTON1;
                 }
@@ -182,19 +183,15 @@ public class LinuxMouseTracker implements WindowListener {
                     
                     if(old_x != x || old_y != y) {
                         // mouse moved
-                        focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_MOVED, 0, wx, wy, 0, 0 ); 
+                        focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_MOVED, 0, wx, wy, (short)0, 0 ); 
                     }
                     
                     if(old_buttonDown != buttonDown) {
                         // press/release
                         if( 0 != buttonDown ) {
-                            focusedWindow.sendMouseEvent(                            
-                                    MouseEvent.EVENT_MOUSE_PRESSED, 
-                                    0, wx, wy, buttonDown, 0 ); 
+                            focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_PRESSED, 0, wx, wy, buttonDown, 0 ); 
                         } else {
-                            focusedWindow.sendMouseEvent(                            
-                                    MouseEvent.EVENT_MOUSE_RELEASED, 
-                                    0, wx, wy, old_buttonDown, 0 ); 
+                            focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_RELEASED, 0, wx, wy, old_buttonDown, 0 ); 
                         }
                     }                
                 } else {
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java b/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java
index 5966bd3..baa94fa 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java
@@ -31,56 +31,129 @@ import com.jogamp.newt.event.KeyEvent;
 
 public class MacKeyUtil {
       
-    // KeyCodes (independent)
-    private static final int kVK_Return                    = 0x24;
-    private static final int kVK_Tab                       = 0x30;
-    private static final int kVK_Space                     = 0x31;
-    private static final int kVK_Delete                    = 0x33;
-    private static final int kVK_Escape                    = 0x35;
-    private static final int kVK_Command                   = 0x37;
-    private static final int kVK_Shift                     = 0x38;
-    private static final int kVK_CapsLock                  = 0x39;
-    private static final int kVK_Option                    = 0x3A;
-    private static final int kVK_Control                   = 0x3B;
-    private static final int kVK_RightShift                = 0x3C;
-    private static final int kVK_RightOption               = 0x3D;
-    private static final int kVK_RightControl              = 0x3E;
-    private static final int kVK_Function                  = 0x3F;
-    private static final int kVK_F17                       = 0x40;
-    private static final int kVK_VolumeUp                  = 0x48;
-    private static final int kVK_VolumeDown                = 0x49;
-    private static final int kVK_Mute                      = 0x4A;
-    private static final int kVK_F18                       = 0x4F;
-    private static final int kVK_F19                       = 0x50;
-    private static final int kVK_F20                       = 0x5A;
-    private static final int kVK_F5                        = 0x60;
-    private static final int kVK_F6                        = 0x61;
-    private static final int kVK_F7                        = 0x62;
-    private static final int kVK_F3                        = 0x63;
-    private static final int kVK_F8                        = 0x64;
-    private static final int kVK_F9                        = 0x65;
-    private static final int kVK_F11                       = 0x67;
-    private static final int kVK_F13                       = 0x69;
-    private static final int kVK_F16                       = 0x6A;
-    private static final int kVK_F14                       = 0x6B;
-    private static final int kVK_F10                       = 0x6D;
-    private static final int kVK_F12                       = 0x6F;
-    private static final int kVK_F15                       = 0x71;
-    private static final int kVK_Help                      = 0x72;
-    private static final int kVK_Home                      = 0x73;
-    private static final int kVK_PageUp                    = 0x74;
-    private static final int kVK_ForwardDelete             = 0x75;
-    private static final int kVK_F4                        = 0x76;
-    private static final int kVK_End                       = 0x77;
-    private static final int kVK_F2                        = 0x78;
-    private static final int kVK_PageDown                  = 0x79;
-    private static final int kVK_F1                        = 0x7A;
-    private static final int kVK_LeftArrow                 = 0x7B;
-    private static final int kVK_RightArrow                = 0x7C;
-    private static final int kVK_DownArrow                 = 0x7D;
-    private static final int kVK_UpArrow                   = 0x7E;
+    //
+    // KeyCodes (Layout Dependent)
+    //
+    private static final short kVK_ANSI_A                    = 0x00;
+    private static final short kVK_ANSI_S                    = 0x01;
+    private static final short kVK_ANSI_D                    = 0x02;
+    private static final short kVK_ANSI_F                    = 0x03;
+    private static final short kVK_ANSI_H                    = 0x04;
+    private static final short kVK_ANSI_G                    = 0x05;
+    private static final short kVK_ANSI_Z                    = 0x06;
+    private static final short kVK_ANSI_X                    = 0x07;
+    private static final short kVK_ANSI_C                    = 0x08;
+    private static final short kVK_ANSI_V                    = 0x09;
+    private static final short kVK_ANSI_B                    = 0x0B;
+    private static final short kVK_ANSI_Q                    = 0x0C;
+    private static final short kVK_ANSI_W                    = 0x0D;
+    private static final short kVK_ANSI_E                    = 0x0E;
+    private static final short kVK_ANSI_R                    = 0x0F;
+    private static final short kVK_ANSI_Y                    = 0x10;
+    private static final short kVK_ANSI_T                    = 0x11;
+    private static final short kVK_ANSI_1                    = 0x12;
+    private static final short kVK_ANSI_2                    = 0x13;
+    private static final short kVK_ANSI_3                    = 0x14;
+    private static final short kVK_ANSI_4                    = 0x15;
+    private static final short kVK_ANSI_6                    = 0x16;
+    private static final short kVK_ANSI_5                    = 0x17;
+    private static final short kVK_ANSI_Equal                = 0x18;
+    private static final short kVK_ANSI_9                    = 0x19;
+    private static final short kVK_ANSI_7                    = 0x1A;
+    private static final short kVK_ANSI_Minus                = 0x1B;
+    private static final short kVK_ANSI_8                    = 0x1C;
+    private static final short kVK_ANSI_0                    = 0x1D;
+    private static final short kVK_ANSI_RightBracket         = 0x1E;
+    private static final short kVK_ANSI_O                    = 0x1F; 
+    private static final short kVK_ANSI_U                    = 0x20;
+    private static final short kVK_ANSI_LeftBracket          = 0x21;
+    private static final short kVK_ANSI_I                    = 0x22;
+    private static final short kVK_ANSI_P                    = 0x23;
+    private static final short kVK_ANSI_L                    = 0x25;
+    private static final short kVK_ANSI_J                    = 0x26;
+    private static final short kVK_ANSI_Quote                = 0x27; 
+    private static final short kVK_ANSI_K                    = 0x28;
+    private static final short kVK_ANSI_Semicolon            = 0x29;
+    private static final short kVK_ANSI_Backslash            = 0x2A; 
+    private static final short kVK_ANSI_Comma                = 0x2B;
+    private static final short kVK_ANSI_Slash                = 0x2C;
+    private static final short kVK_ANSI_N                    = 0x2D;
+    private static final short kVK_ANSI_M                    = 0x2E;
+    private static final short kVK_ANSI_Period               = 0x2F;
+    private static final short kVK_ANSI_Grave                = 0x32;
+    private static final short kVK_ANSI_KeypadDecimal        = 0x41;
+    private static final short kVK_ANSI_KeypadMultiply       = 0x43;
+    private static final short kVK_ANSI_KeypadPlus           = 0x45;
+    private static final short kVK_ANSI_KeypadClear          = 0x47;
+    private static final short kVK_ANSI_KeypadDivide         = 0x4B;
+    private static final short kVK_ANSI_KeypadEnter          = 0x4C;
+    private static final short kVK_ANSI_KeypadMinus          = 0x4E;
+    private static final short kVK_ANSI_KeypadEquals         = 0x51;
+    private static final short kVK_ANSI_Keypad0              = 0x52;
+    private static final short kVK_ANSI_Keypad1              = 0x53;
+    private static final short kVK_ANSI_Keypad2              = 0x54;
+    private static final short kVK_ANSI_Keypad3              = 0x55;
+    private static final short kVK_ANSI_Keypad4              = 0x56;
+    private static final short kVK_ANSI_Keypad5              = 0x57;
+    private static final short kVK_ANSI_Keypad6              = 0x58;
+    private static final short kVK_ANSI_Keypad7              = 0x59;
+    private static final short kVK_ANSI_Keypad8              = 0x5B;
+    private static final short kVK_ANSI_Keypad9              = 0x5C;
+    
+    //
+    // KeyCodes (Layout Independent)
+    //
+    private static final short kVK_Return                    = 0x24;
+    private static final short kVK_Tab                       = 0x30;
+    private static final short kVK_Space                     = 0x31;
+    private static final short kVK_Delete                    = 0x33;
+    private static final short kVK_Escape                    = 0x35;
+    private static final short kVK_Command                   = 0x37;
+    private static final short kVK_Shift                     = 0x38;
+    private static final short kVK_CapsLock                  = 0x39;
+    private static final short kVK_Option                    = 0x3A;
+    private static final short kVK_Control                   = 0x3B;
+    private static final short kVK_RightShift                = 0x3C;
+    private static final short kVK_RightOption               = 0x3D;
+    private static final short kVK_RightControl              = 0x3E;
+    // private static final short kVK_Function                  = 0x3F;
+    private static final short kVK_F17                       = 0x40;
+    // private static final short kVK_VolumeUp                  = 0x48;
+    // private static final short kVK_VolumeDown                = 0x49;
+    // private static final short kVK_Mute                      = 0x4A;
+    private static final short kVK_F18                       = 0x4F;
+    private static final short kVK_F19                       = 0x50;
+    private static final short kVK_F20                       = 0x5A;
+    private static final short kVK_F5                        = 0x60;
+    private static final short kVK_F6                        = 0x61;
+    private static final short kVK_F7                        = 0x62;
+    private static final short kVK_F3                        = 0x63;
+    private static final short kVK_F8                        = 0x64;
+    private static final short kVK_F9                        = 0x65;
+    private static final short kVK_F11                       = 0x67;
+    private static final short kVK_F13                       = 0x69;
+    private static final short kVK_F16                       = 0x6A;
+    private static final short kVK_F14                       = 0x6B;
+    private static final short kVK_F10                       = 0x6D;
+    private static final short kVK_F12                       = 0x6F;
+    private static final short kVK_F15                       = 0x71;
+    private static final short kVK_Help                      = 0x72;
+    private static final short kVK_Home                      = 0x73;
+    private static final short kVK_PageUp                    = 0x74;
+    private static final short kVK_ForwardDelete             = 0x75;
+    private static final short kVK_F4                        = 0x76;
+    private static final short kVK_End                       = 0x77;
+    private static final short kVK_F2                        = 0x78;
+    private static final short kVK_PageDown                  = 0x79;
+    private static final short kVK_F1                        = 0x7A;
+    private static final short kVK_LeftArrow                 = 0x7B;
+    private static final short kVK_RightArrow                = 0x7C;
+    private static final short kVK_DownArrow                 = 0x7D;
+    private static final short kVK_UpArrow                   = 0x7E;
   
+    //
     // Key constants handled differently on Mac OS X than other platforms
+    //
     private static final char NSUpArrowFunctionKey        = 0xF700;
     private static final char NSDownArrowFunctionKey      = 0xF701;
     private static final char NSLeftArrowFunctionKey      = 0xF702;
@@ -109,6 +182,7 @@ public class MacKeyUtil {
     private static final char NSF22FunctionKey            = 0xF719;
     private static final char NSF23FunctionKey            = 0xF71A;
     private static final char NSF24FunctionKey            = 0xF71B;
+    /**
     private static final char NSF25FunctionKey            = 0xF71C;
     private static final char NSF26FunctionKey            = 0xF71D;
     private static final char NSF27FunctionKey            = 0xF71E;
@@ -120,6 +194,7 @@ public class MacKeyUtil {
     private static final char NSF33FunctionKey            = 0xF724;
     private static final char NSF34FunctionKey            = 0xF725;
     private static final char NSF35FunctionKey            = 0xF726;
+    */
     private static final char NSInsertFunctionKey         = 0xF727;
     private static final char NSDeleteFunctionKey         = 0xF728;
     private static final char NSHomeFunctionKey           = 0xF729;
@@ -130,10 +205,11 @@ public class MacKeyUtil {
     private static final char NSPrintScreenFunctionKey    = 0xF72E;
     private static final char NSScrollLockFunctionKey     = 0xF72F;
     private static final char NSPauseFunctionKey          = 0xF730;
-    private static final char NSSysReqFunctionKey         = 0xF731;
-    private static final char NSBreakFunctionKey          = 0xF732;
-    private static final char NSResetFunctionKey          = 0xF733;
+    // private static final char NSSysReqFunctionKey         = 0xF731;
+    // private static final char NSBreakFunctionKey          = 0xF732;
+    // private static final char NSResetFunctionKey          = 0xF733;
     private static final char NSStopFunctionKey           = 0xF734;
+    /**
     private static final char NSMenuFunctionKey           = 0xF735;
     private static final char NSUserFunctionKey           = 0xF736;
     private static final char NSSystemFunctionKey         = 0xF737;
@@ -153,10 +229,83 @@ public class MacKeyUtil {
     private static final char NSFindFunctionKey           = 0xF745;
     private static final char NSHelpFunctionKey           = 0xF746;
     private static final char NSModeSwitchFunctionKey     = 0xF747;
+    */
     
-    static int validateKeyCode(int keyCode, char keyChar) {        
+    static short validateKeyCode(short keyCode, char keyChar) {        
         // OS X Virtual Keycodes
         switch(keyCode) {
+            //
+            // KeyCodes (Layout Dependent)
+            //
+            case kVK_ANSI_A:               return KeyEvent.VK_A;
+            case kVK_ANSI_S:               return KeyEvent.VK_S;
+            case kVK_ANSI_D:               return KeyEvent.VK_D;
+            case kVK_ANSI_F:               return KeyEvent.VK_F;
+            case kVK_ANSI_H:               return KeyEvent.VK_H;
+            case kVK_ANSI_G:               return KeyEvent.VK_G;
+            case kVK_ANSI_Z:               return KeyEvent.VK_Z;
+            case kVK_ANSI_X:               return KeyEvent.VK_X;
+            case kVK_ANSI_C:               return KeyEvent.VK_C;
+            case kVK_ANSI_V:               return KeyEvent.VK_V;
+            case kVK_ANSI_B:               return KeyEvent.VK_B;
+            case kVK_ANSI_Q:               return KeyEvent.VK_Q;
+            case kVK_ANSI_W:               return KeyEvent.VK_W;
+            case kVK_ANSI_E:               return KeyEvent.VK_E;
+            case kVK_ANSI_R:               return KeyEvent.VK_R;
+            case kVK_ANSI_Y:               return KeyEvent.VK_Y;
+            case kVK_ANSI_T:               return KeyEvent.VK_T;
+            case kVK_ANSI_1:               return KeyEvent.VK_1;
+            case kVK_ANSI_2:               return KeyEvent.VK_2;
+            case kVK_ANSI_3:               return KeyEvent.VK_3;
+            case kVK_ANSI_4:               return KeyEvent.VK_4;
+            case kVK_ANSI_6:               return KeyEvent.VK_6;
+            case kVK_ANSI_5:               return KeyEvent.VK_5;
+            case kVK_ANSI_Equal:           return KeyEvent.VK_EQUALS;
+            case kVK_ANSI_9:               return KeyEvent.VK_9;
+            case kVK_ANSI_7:               return KeyEvent.VK_7;
+            case kVK_ANSI_Minus:           return KeyEvent.VK_MINUS;
+            case kVK_ANSI_8:               return KeyEvent.VK_8;
+            case kVK_ANSI_0:               return KeyEvent.VK_0;
+            case kVK_ANSI_RightBracket:    return KeyEvent.VK_CLOSE_BRACKET;
+            case kVK_ANSI_O:               return KeyEvent.VK_O; 
+            case kVK_ANSI_U:               return KeyEvent.VK_U;
+            case kVK_ANSI_LeftBracket:     return KeyEvent.VK_OPEN_BRACKET;
+            case kVK_ANSI_I:               return KeyEvent.VK_I;
+            case kVK_ANSI_P:               return KeyEvent.VK_P;
+            case kVK_ANSI_L:               return KeyEvent.VK_L;
+            case kVK_ANSI_J:               return KeyEvent.VK_J;
+            case kVK_ANSI_Quote:           return KeyEvent.VK_QUOTE; 
+            case kVK_ANSI_K:               return KeyEvent.VK_K;
+            case kVK_ANSI_Semicolon:       return KeyEvent.VK_SEMICOLON;
+            case kVK_ANSI_Backslash:       return KeyEvent.VK_BACK_SLASH; 
+            case kVK_ANSI_Comma:           return KeyEvent.VK_COMMA;
+            case kVK_ANSI_Slash:           return KeyEvent.VK_SLASH;
+            case kVK_ANSI_N:               return KeyEvent.VK_N;
+            case kVK_ANSI_M:               return KeyEvent.VK_M;
+            case kVK_ANSI_Period:          return KeyEvent.VK_PERIOD;
+            case kVK_ANSI_Grave:           return KeyEvent.VK_BACK_QUOTE; // KeyEvent.VK_DEAD_GRAVE
+            case kVK_ANSI_KeypadDecimal:   return KeyEvent.VK_DECIMAL;
+            case kVK_ANSI_KeypadMultiply:  return KeyEvent.VK_MULTIPLY;
+            case kVK_ANSI_KeypadPlus:      return KeyEvent.VK_PLUS;
+            case kVK_ANSI_KeypadClear:     return KeyEvent.VK_CLEAR;
+            case kVK_ANSI_KeypadDivide:    return KeyEvent.VK_DIVIDE;
+            case kVK_ANSI_KeypadEnter:     return KeyEvent.VK_ENTER;
+            case kVK_ANSI_KeypadMinus:     return KeyEvent.VK_MINUS;
+            case kVK_ANSI_KeypadEquals:    return KeyEvent.VK_EQUALS;
+            case kVK_ANSI_Keypad0:         return KeyEvent.VK_0;
+            case kVK_ANSI_Keypad1:         return KeyEvent.VK_1;
+            case kVK_ANSI_Keypad2:         return KeyEvent.VK_2;
+            case kVK_ANSI_Keypad3:         return KeyEvent.VK_3;
+            case kVK_ANSI_Keypad4:         return KeyEvent.VK_4;
+            case kVK_ANSI_Keypad5:         return KeyEvent.VK_5;
+            case kVK_ANSI_Keypad6:         return KeyEvent.VK_6;
+            case kVK_ANSI_Keypad7:         return KeyEvent.VK_7;
+            case kVK_ANSI_Keypad8:         return KeyEvent.VK_8;
+            case kVK_ANSI_Keypad9:         return KeyEvent.VK_9;
+            
+            //
+            // KeyCodes (Layout Independent)
+            //
             case kVK_Return:               return KeyEvent.VK_ENTER;
             case kVK_Tab:                  return KeyEvent.VK_TAB;
             case kVK_Space:                return KeyEvent.VK_SPACE;
@@ -168,7 +317,7 @@ public class MacKeyUtil {
             case kVK_Option:               return KeyEvent.VK_ALT;
             case kVK_Control:              return KeyEvent.VK_CONTROL;
             case kVK_RightShift:           return KeyEvent.VK_SHIFT;
-            case kVK_RightOption:          return KeyEvent.VK_ALT;
+            case kVK_RightOption:          return KeyEvent.VK_ALT_GRAPH;
             case kVK_RightControl:         return KeyEvent.VK_CONTROL;
             // case kVK_Function:             return KeyEvent.VK_F;
             case kVK_F17:                  return KeyEvent.VK_F17;
@@ -270,15 +419,8 @@ public class MacKeyUtil {
             // NSFindFunctionKey
             // NSHelpFunctionKey
             // NSModeSwitchFunctionKey
-            case 0x60: return KeyEvent.VK_BACK_QUOTE; // `
-            case 0x27: return KeyEvent.VK_QUOTE;      // '          
-            case '\r': return KeyEvent.VK_ENTER;
-        }
-
-        if ('a' <= keyChar && keyChar <= 'z') {
-            return KeyEvent.VK_A + ( keyChar - 'a' ) ;
         }
 
-        return (int) keyChar; // let's hope for the best (compatibility of keyChar/keyCode's)
+        return (short) keyChar; // let's hope for the best (compatibility of keyChar/keyCode's)
     }   
 }
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
index 24e60ba..a3bb267 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
@@ -34,28 +34,19 @@
 
 package jogamp.newt.driver.macosx;
 
-import java.util.List;
-
 import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.Point;
 
+import jogamp.newt.MonitorModeProps;
 import jogamp.newt.ScreenImpl;
 
-import com.jogamp.common.util.IntObjectHashMap;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
 
 public class ScreenDriver extends ScreenImpl {
     
-    // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call)
-    private static IntObjectHashMap/*<int, DimensionImmutable>*/ scrnIdx2Dimension;
-    
     static {
         DisplayDriver.initSingleton();
-        scrnIdx2Dimension = new IntObjectHashMap();
-        scrnIdx2Dimension.setKeyNotFoundValue(null);
     }
 
     public ScreenDriver() {
@@ -67,77 +58,67 @@ public class ScreenDriver extends ScreenImpl {
 
     protected void closeNativeImpl() { }
 
-    private static native int getWidthImpl0(int scrn_idx);
-    private static native int getHeightImpl0(int scrn_idx);
-    
-    private int[] getScreenModeIdx(int idx) {
-        // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call)
-        DimensionImmutable dim = (DimensionImmutable) scrnIdx2Dimension.get(screen_idx);
-        if(null == dim) {
-            int[] res = getScreenSizeMM0(screen_idx);
-            if(null == res || 0 == res.length) {
-                return null;
-            }
-            dim = new Dimension(res[0], res[1]);
-            scrnIdx2Dimension.put(screen_idx, dim);
-        }
-
-        int[] modeProps = getScreenMode0(screen_idx, idx, dim.getWidth(), dim.getHeight());
-        if (null == modeProps || 0 == modeProps.length) {
-            return null;
+    private MonitorMode getMonitorModeImpl(MonitorModeProps.Cache cache, int crt_idx, int mode_idx) {
+        final int[] modeProps = getMonitorMode0(crt_idx, mode_idx);
+        final MonitorMode res;
+        if (null == modeProps  || 0 >= modeProps.length) {
+            res = null;
+        } else {
+            res = MonitorModeProps.streamInMonitorMode(null, cache, modeProps, 0);
         }
-        if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) {
-            throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length);
-        }
-        return modeProps;
+        return res;
     }
-
-    private int nativeModeIdx;
     
-    protected int[] getScreenModeFirstImpl() {
-        nativeModeIdx = 0;
-        return getScreenModeNextImpl();
-    }
-
-    protected int[] getScreenModeNextImpl() {
-        int[] modeProps = getScreenModeIdx(nativeModeIdx);
-        if (null != modeProps && 0 < modeProps.length) {
-            nativeModeIdx++;
-            return modeProps;
-        }
-        return null;
+    @Override
+    protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+        int crtIdx = 0;
+        int modeIdx = 0;
+        ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
+        do {
+            final MonitorMode mode = getMonitorModeImpl(cache, crtIdx, modeIdx);
+            if( null != mode ) {
+                supportedModes.getOrAdd(mode);
+                // next mode on same monitor
+                modeIdx++;
+            } else if( 0 < modeIdx ) {
+                // end of monitor modes - got at least one mode
+                final MonitorMode currentMode = getMonitorModeImpl(cache, crtIdx, -1);
+                if ( null == currentMode ) {
+                    throw new InternalError("Could not gather current mode of device "+crtIdx+", but gathered "+modeIdx+" modes");
+                }                
+                final int[] monitorProps = getMonitorProps0(crtIdx);
+                if ( null == monitorProps ) {
+                    throw new InternalError("Could not gather device "+crtIdx+", but gathered "+modeIdx+" modes");
+                }                
+                // merge monitor-props + supported modes
+                MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, monitorProps, 0);
+                
+                // next monitor, 1st mode
+                supportedModes= new ArrayHashSet<MonitorMode>();                
+                crtIdx++;
+                modeIdx=0;
+            } else {
+                // end of monitor
+                break;
+            }
+        } while ( true );
     }
 
-    protected ScreenMode getCurrentScreenModeImpl() {
-        int[] modeProps = getScreenModeIdx(-1);
-        if (null != modeProps && 0 < modeProps.length) {
-            return ScreenModeUtil.streamIn(modeProps, 0);
-        }
-        return null;
+    @Override
+    protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) {
+        return getMonitorModeImpl(null, monitor.getId(), -1);
     }
     
-    protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) {
-        final List<ScreenMode> screenModes = this.getScreenModesOrig();
-        final int screenModeIdx = screenModes.indexOf(screenMode);
-        if(0>screenModeIdx) {
-            throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode);
-        }
-        final int nativeModeIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx);
-        return setScreenMode0(screen_idx, nativeModeIdx);
+    @Override
+    protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode)  {
+        return setMonitorMode0(monitor.getId(), mode.getId(), mode.getRotation());
     }
     
     protected int validateScreenIndex(int idx) {
-        return idx; 
+        return 0; // big-desktop w/ multiple monitor attached, only one screen available 
     }
         
-    protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
-        virtualOrigin.setX(0);
-        virtualOrigin.setY(0);
-        virtualSize.setWidth(getWidthImpl0(screen_idx));
-        virtualSize.setHeight(getHeightImpl0(screen_idx));
-    }
-
-    private native int[] getScreenSizeMM0(int screen_idx);
-    private native int[] getScreenMode0(int screen_index, int mode_index, int widthMM, int heightMM);
-    private native boolean setScreenMode0(int screen_index, int mode_idx);
+    private native int[] getMonitorProps0(int crt_idx);
+    private native int[] getMonitorMode0(int crt_index, int mode_idx);
+    private native boolean setMonitorMode0(int crt_index, int nativeId, int rot);
 }
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
index 5755bdf..6aebf04 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
@@ -41,7 +41,6 @@ import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.MutableSurface;
 import javax.media.nativewindow.VisualIDHolder;
 import javax.media.nativewindow.util.Insets;
-import javax.media.nativewindow.util.InsetsImmutable;
 import javax.media.nativewindow.util.Point;
 import javax.media.nativewindow.util.PointImmutable;
 
@@ -81,12 +80,16 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
         try {
             if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); }
             final long handle = getWindowHandle(); 
+            visibleChanged(true, false);
             setWindowHandle(0);
             surfaceHandle = 0;
             sscSurfaceHandle = 0;
-            isOffscreenInstance = false;            
+            isOffscreenInstance = false;
             if (0 != handle) {
-                close0(handle);
+                OSXUtil.RunOnMainThread(false, new Runnable() {
+                   public void run() {
+                       close0( handle );
+                   } } );
             }
         } catch (Throwable t) {
             if(DEBUG_IMPLEMENTATION) { 
@@ -98,18 +101,31 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
     
     @Override
     protected int lockSurfaceImpl() {
-        if(!isOffscreenInstance) {
-            return lockSurface0(getWindowHandle()) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
+        /** 
+         * if( isOffscreenInstance ) {
+         *    return LOCK_SUCCESS;
+         * }
+         */
+        final long w = getWindowHandle();
+        final long v = surfaceHandle;
+        if( 0 != v && 0 != w ) {
+            return lockSurface0(w, v) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
         }
-        return LOCK_SUCCESS;
+        return LOCK_SURFACE_NOT_READY;
     }
 
     @Override
     protected void unlockSurfaceImpl() {
-        if(!isOffscreenInstance) {
-            final long h = getWindowHandle();
-            if(0 != h) {
-                unlockSurface0(h);
+        /** 
+         * if( isOffscreenInstance ) {
+         *    return;
+         * }
+         */
+        final long w = getWindowHandle();
+        final long v = surfaceHandle;
+        if(0 != w && 0 != v) {
+            if( !unlockSurface0(w, v) ) {
+                throw new NativeWindowException("Failed to unlock surface, probably not locked!");
             }
         }
     }
@@ -127,61 +143,120 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
         sscSurfaceHandle = surfaceHandle;
         if (isNativeValid()) {
             if (0 != sscSurfaceHandle) {
-                orderOut0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+                OSXUtil.RunOnMainThread(false, new Runnable() {
+                    public void run() {
+                        orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+                    } } );
             } /** this is done by recreation! 
               else if (isVisible()){
-                orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+                OSXUtil.RunOnMainThread(false, new Runnable() {
+                    public void run() {
+                        orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+                    } } );
             } */
         }        
     }
 
     @Override
     protected void setTitleImpl(final String title) {
-        setTitle0(getWindowHandle(), title);
+            OSXUtil.RunOnMainThread(false, new Runnable() {
+                public void run() {
+                    setTitle0(getWindowHandle(), title);
+                } } );
     }
 
-    protected void requestFocusImpl(boolean force) {
+    @Override
+    protected void requestFocusImpl(final boolean force) {
         if(!isOffscreenInstance) {
-            requestFocus0(getWindowHandle(), force);
+            OSXUtil.RunOnMainThread(false, new Runnable() {
+                public void run() {
+                    requestFocus0(getWindowHandle(), force);
+                } } );
         } else {
             focusChanged(false, true);
         }
     }
         
+    @Override
     public final void clearFocus() {
         if(DEBUG_IMPLEMENTATION) {
             System.err.println("MacWindow: clearFocus(), isOffscreenInstance "+isOffscreenInstance);
         }
         if(!isOffscreenInstance) {
-            resignFocus0(getWindowHandle());
+            OSXUtil.RunOnMainThread(false, new Runnable() {
+                public void run() {
+                    resignFocus0(getWindowHandle());
+                } } );
         } else {
             focusChanged(false, false);
         }
     }
     
-    public void updatePosition() {
-        final Point pS = getTopLevelLocationOnScreen(getX(), getY());
-        if(DEBUG_IMPLEMENTATION) {
-            System.err.println("MacWindow: updatePosition() - isOffscreenInstance "+isOffscreenInstance+", new abs pos: pS "+pS);
-        }
-        if( !isOffscreenInstance ) {                
-            setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY());
-        } // else no offscreen position
-        // no native event (fullscreen, some reparenting)
-        super.positionChanged(true, getX(), getY());
-    }
+    private boolean useParent(NativeWindow parent) { return null != parent && 0 != parent.getWindowHandle(); }
     
+    @Override
+    public void updatePosition(int x, int y) {
+        final long handle = getWindowHandle();
+        if( 0 != handle && !isOffscreenInstance ) {
+            final NativeWindow parent = getParent();
+            final boolean useParent = useParent(parent);
+            final int pX=parent.getX(), pY=parent.getY();
+            final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
+            if(DEBUG_IMPLEMENTATION) {
+                System.err.println("MacWindow: updatePosition() parent["+useParent+" "+pX+"/"+pY+"] "+x+"/"+y+" ->  "+x+"/"+y+" rel-client-pos, "+p0S+" screen-client-pos");
+            }
+            OSXUtil.RunOnMainThread(false, new Runnable() {
+                public void run() {
+                    setWindowClientTopLeftPoint0(handle, p0S.getX(), p0S.getY(), isVisible());
+                } } );
+            // no native event (fullscreen, some reparenting)
+            positionChanged(true, x, y);
+        }
+    }    
     
-    protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+    @Override
+    protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
+        final long handle = getWindowHandle();
+        if( 0 != handle && !isOffscreenInstance ) {
+            final NativeWindow parent = getParent();
+            final boolean useParent = useParent(parent);
+            if( useParent && ( getWidth() != newWidth || getHeight() != newHeight ) ) {
+                final int x=getX(), y=getY();
+                final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
+                if(DEBUG_IMPLEMENTATION) {
+                    System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" ->  "+p0S+" screen-client-pos");
+                }
+                OSXUtil.RunOnMainThread(false, new Runnable() {
+                    public void run() {
+                        setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
+                    } } );
+            }
+        }
+        super.sizeChanged(defer, newWidth, newHeight, force);
+    }
+   
+    @Override
+    protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, int flags) {
         final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent());
         isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance;
-        final PointImmutable pS = isOffscreenInstance ? new Point(0, 0) : getTopLevelLocationOnScreen(x, y);
+        final PointImmutable pClientLevelOnSreen;
+        if( isOffscreenInstance ) {
+            pClientLevelOnSreen = new Point(0, 0);
+        } else  {
+            final NativeWindow parent = getParent();
+            final boolean useParent = useParent(parent);
+            if( useParent ) {
+                pClientLevelOnSreen = getLocationOnScreenImpl(x, y, parent, useParent);
+            } else {            
+                pClientLevelOnSreen = new Point(x, y);
+            }
+        }
         
         if(DEBUG_IMPLEMENTATION) {
             final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration();
             final NativeWindow pWin = getParent();
             final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null;
-            System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+
+            System.err.println("MacWindow reconfig.0: "+x+"/"+y+" -> clientPos "+pClientLevelOnSreen+" - "+width+"x"+height+
                                ",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+
                                ",\n\t   this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+
                                ",\n\t parent-chosenCaps "+(null != pWinCfg ? pWinCfg.getChosenCapabilities() : null)+
@@ -189,103 +264,111 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
                                ", ioi: "+_isOffscreenInstance+
                                ") -> "+isOffscreenInstance+
                                "\n\t, "+getReconfigureFlagsAsString(null, flags));
+            // Thread.dumpStack();
         }
         
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) {
+        final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags);
+        
+        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && !setVisible ) {
             if ( !isOffscreenInstance ) {
-                orderOut0(getWindowHandle());
+                OSXUtil.RunOnMainThread(false, new Runnable() {
+                    public void run() {
+                        orderOut0(getWindowHandle());
+                        visibleChanged(true, false);
+                    } } );
+            } else {
+                visibleChanged(true, false);
             }
-            // no native event ..
-            visibleChanged(true, false); 
         }
-        if( 0 == getWindowHandle() && 0 != ( FLAG_IS_VISIBLE & flags) ||
+        if( 0 == getWindowHandle() && setVisible ||
             0 != ( FLAG_CHANGE_DECORATION & flags) ||
             0 != ( FLAG_CHANGE_PARENTING & flags) ||
             0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
             if(isOffscreenInstance) {
-                createWindow(true, 0 != getWindowHandle(), pS, 64, 64, false);
+                createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false, setVisible, false);
             } else {
-                createWindow(false, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags));
+                createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height, 
+                                    0 != ( FLAG_IS_FULLSCREEN & flags), setVisible, 0 != ( FLAG_IS_ALWAYSONTOP & flags));
             }
-            if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } 
-        }
-        if(x>=0 && y>=0) {
-            if( !isOffscreenInstance ) {                
-                setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY());
-            } // else no offscreen position
-            // no native event (fullscreen, some reparenting)
-            super.positionChanged(true,  x, y);
-        }
-        if(width>0 && height>0) {
-            if( !isOffscreenInstance ) {                
-                setContentSize0(getWindowHandle(), width, height);
-            } // else offscreen size is realized via recreation
-            // no native event (fullscreen, some reparenting)
-            sizeChanged(true, width, height, false); // incl. validation (incl. repositioning)
-        }
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) {
-            if( !isOffscreenInstance ) {                
-                orderFront0(getWindowHandle());
+        } else {
+            if( width>0 && height>0 ) {        
+                if( !isOffscreenInstance ) {
+                    OSXUtil.RunOnMainThread(false, new Runnable() {
+                        public void run() {
+                            setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height, setVisible);
+                        } } );
+                } // else offscreen size is realized via recreation
+                // no native event (fullscreen, some reparenting)
+                positionChanged(true,  x, y);
+                sizeChanged(true, width, height, false);
+            }
+            if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && setVisible ) {
+                if( !isOffscreenInstance ) {                
+                    OSXUtil.RunOnMainThread(false, new Runnable() {
+                        public void run() {
+                            orderFront0(getWindowHandle());
+                            visibleChanged(true, true);
+                        } } );
+                } else {
+                    visibleChanged(true, true);
+                }
+            }
+            if( !isOffscreenInstance ) {
+                setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
             }
-            // no native event ..
-            visibleChanged(true, true);
-        } 
-        if( !isOffscreenInstance ) {                
-            setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
+        }
+        if(DEBUG_IMPLEMENTATION) {
+            System.err.println("MacWindow reconfig.X: clientPos "+pClientLevelOnSreen+", "+width+"x"+height+" -> clientPos "+getLocationOnScreenImpl(0, 0)+", insets: "+getInsets());            
         }
         return true;
     }
 
+    @Override
     protected Point getLocationOnScreenImpl(int x, int y) {
         final NativeWindow parent = getParent();
-        final boolean useParent = null != parent && 0 != parent.getWindowHandle() ;
+        final boolean useParent = useParent(parent);
+        return getLocationOnScreenImpl(x, y, parent, useParent);
+    }
         
+    private Point getLocationOnScreenImpl(final int x, final int y, final NativeWindow parent, final boolean useParent) {
         if( !useParent && !isOffscreenInstance && 0 != surfaceHandle) {
             return OSXUtil.GetLocationOnScreen(surfaceHandle, true, x, y);
         }
         
         final Point p = new Point(x, y);
-        // min val is 0
-        p.setX(Math.max(p.getX(), 0));
-        p.setY(Math.max(p.getY(), 0));
         if( useParent ) {
-            p.translate(parent.getLocationOnScreen(null));
+            p.translate( parent.getLocationOnScreen(null) );
         }
         return p;
     }
-    
-    private Point getTopLevelLocationOnScreen(int x, int y) {
-        final InsetsImmutable _insets = getInsets(); // zero if undecorated
-        // client position -> top-level window position
-        x -= _insets.getLeftWidth() ;
-        y -= _insets.getTopHeight() ;
-        return getLocationOnScreenImpl(x, y);
-    }
-    
+        
+    @Override
     protected void updateInsetsImpl(Insets insets) {
         // nop - using event driven insetsChange(..)
     }
         
-    @Override
-    protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
-        if(getWidth() != newWidth || getHeight() != newHeight) {
-            final Point p0S = getTopLevelLocationOnScreen(getX(), getY());            
-            setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), p0S.getX(), p0S.getY());               
-        }
-        super.sizeChanged(defer, newWidth, newHeight, force);
-    }
-    
-    @Override
-    protected void positionChanged(boolean defer, int newX, int newY) {        
+    /** Callback for native screen position change event of the client area. */
+    protected void screenPositionChanged(boolean defer, int newX, int newY) {        
         // passed coordinates are in screen position of the client area
-        if(getWindowHandle()!=0) {
-            // screen position -> window position
-            Point absPos = new Point(newX, newY);            
+        if(getWindowHandle()!=0) {            
             final NativeWindow parent = getParent();
-            if(null != parent) {
-                absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) );
+            if( null == parent || isOffscreenInstance ) {
+                if(DEBUG_IMPLEMENTATION) {
+                    System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
+                }
+                positionChanged(defer, newX, newY);
+            } else {
+                // screen position -> rel child window position
+                Point absPos = new Point(newX, newY);            
+                Point parentOnScreen = parent.getLocationOnScreen(null);
+                absPos.translate( parentOnScreen.scale(-1, -1) );
+                if(DEBUG_IMPLEMENTATION) {
+                    System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos);
+                }
+                positionChanged(defer, absPos.getX(), absPos.getY());
             }
-            super.positionChanged(defer, absPos.getX(), absPos.getY());
+        } else if(DEBUG_IMPLEMENTATION) {
+            System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
         }
     }
     
@@ -312,55 +395,53 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
         } // else may need offscreen solution ? FIXME
     }
     
-    private final void emitKeyEvent(boolean send, boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
-        if( send ) {
-            super.sendKeyEvent(eventType, modifiers, keyCode, keyChar);
-        } else {
-            super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keyChar);
-        }
+    @Override
+    public final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+        throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
     }
-
-    private final void handleKeyEvent(boolean send, boolean wait, int eventType, int modifiers, int _keyCode, char keyChar) {
+    
+    @Override
+    public final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short _keyCode, short _keySym, char keyChar) {
+        throw new InternalError("XXX: Adapt Java Code to Native Code Changes");    
+    }
+    
+    protected final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short _keyCode, char keyChar, char keySymChar) {
         // Note that we send the key char for the key code on this
         // platform -- we do not get any useful key codes out of the system
-        final int keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar);
-        // final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
-        // System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", key 0x"+Integer.toHexString(_keyCode)+" -> 0x"+Integer.toHexString(keyCode)+", mods "+toHexString(modifiers)+", was: pressed "+isKeyPressed(keyCode)+", repeat "+isKeyInAutoRepeat(keyCode)+", isModifierKeyCode "+isModifierKeyCode);
+        final short keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar);
+        final short keySym;
+        {
+            short _keySym = KeyEvent.NULL_CHAR != keySymChar ? KeyEvent.utf16ToVKey(keySymChar) : KeyEvent.VK_UNDEFINED;
+            keySym = KeyEvent.VK_UNDEFINED != _keySym ? _keySym : keyCode;
+        }
+        /* {
+            final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
+            System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+
+                               ", keyCode 0x"+Integer.toHexString(_keyCode)+" -> 0x"+Integer.toHexString(keyCode)+
+                               ", keySymChar '"+keySymChar+"', 0x"+Integer.toHexString(keySymChar)+" -> 0x"+Integer.toHexString(keySym)+
+                               ", mods "+toHexString(modifiers)+
+                               ", was: pressed "+isKeyPressed(keyCode)+", isModifierKeyCode "+isModifierKeyCode);
+        } */
             
-        // 1:1 Order: OSX and NEWT delivery order is PRESSED, RELEASED and TYPED            
-        // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE and TYPED keys _before_ PRESSED
+        // OSX delivery order is PRESSED (t0), RELEASED (t1) and TYPED (t2) -> NEWT order: PRESSED (t0) and RELEASED (t1)
+        // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE key _before_ PRESSED
         switch(eventType) {
             case KeyEvent.EVENT_KEY_RELEASED:
                 if( isKeyCodeTracked(keyCode) ) {
-                    keyRepeatState.put(keyCode, false); // prev == true -> AR out
-                    keyPressedState.put(keyCode, false);
+                    setKeyPressed(keyCode, false);
                 }
                 break;
             case KeyEvent.EVENT_KEY_PRESSED:
                 if( isKeyCodeTracked(keyCode) ) {
-                    if( keyPressedState.put(keyCode, true) ) {
+                    if( setKeyPressed(keyCode, true) ) {
                         // key was already pressed
-                        keyRepeatState.put(keyCode, true); // prev == false ->  AR in
                         modifiers |= InputEvent.AUTOREPEAT_MASK;
-                        emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keyChar); // RELEASED
-                        emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, keyChar); // TYPED
+                        super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED
                     }
                 }
                 break;
-            case KeyEvent.EVENT_KEY_TYPED:
-                break;
         }
-        emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
-    }
-    
-    @Override
-    public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
-        handleKeyEvent(true, false, eventType, modifiers, keyCode, keyChar);
-    }
-    
-    @Override
-    public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
-        handleKeyEvent(false, wait, eventType, modifiers, keyCode, keyChar);
+        super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar);
     }
 
     //----------------------------------------------------------------------
@@ -369,65 +450,96 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
     
     private void createWindow(final boolean offscreenInstance, final boolean recreate, 
                               final PointImmutable pS, final int width, final int height, 
-                              final boolean fullscreen) {
+                              final boolean fullscreen, final boolean visible, final boolean alwaysOnTop) {
 
-        if(0!=getWindowHandle() && !recreate) {
-            return;
+        if(DEBUG_IMPLEMENTATION) {
+            System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+
+                               ": offscreen "+offscreenInstance+", recreate "+recreate+
+                               ", pS "+pS+", "+width+"x"+height+", fullscreen "+fullscreen+", visible "+visible+
+                               ", alwaysOnTop "+alwaysOnTop);
+            // Thread.dumpStack();
         }
 
         try {
-            if(0!=getWindowHandle()) {
-                // save the view .. close the window
-                surfaceHandle = changeContentView0(getParentWindowHandle(), getWindowHandle(), 0);
-                if(recreate && 0==surfaceHandle) {
-                    throw new NativeWindowException("Internal Error - recreate, window but no view");
-                }
-                close0(getWindowHandle());
+            final long parentWin = getParentWindowHandle();
+            if( 0 != getWindowHandle() ) {                
+                final long thisWin = getWindowHandle();
                 setWindowHandle(0);
+                
+                if( 0 == surfaceHandle ) {
+                    throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView");
+                }                
+                OSXUtil.RunOnMainThread(false, new Runnable() {
+                    public void run() {
+                        changeContentView0(parentWin, thisWin, 0);
+                        close0( thisWin );
+                    } } );
             } else {
-                surfaceHandle = 0;
-            }
-            setWindowHandle(createWindow0(getParentWindowHandle(),
-                                 pS.getX(), pS.getY(), width, height,
-                                 (getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance),
-                                 fullscreen,
-                                 ((isUndecorated() || offscreenInstance) ?
-                                   NSBorderlessWindowMask :
-                                   NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask),
-                                 NSBackingStoreBuffered, 
-                                 getScreen().getIndex(), surfaceHandle));
-            if (getWindowHandle() == 0) {
-                throw new NativeWindowException("Could create native window "+Thread.currentThread().getName()+" "+this);
+                if( 0 != surfaceHandle ) {
+                    throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView");
+                }                
+                surfaceHandle = createView0(pS.getX(), pS.getY(), width, height, fullscreen);
+                if( 0 == surfaceHandle ) {
+                    throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this);
+                }
             }
-            surfaceHandle = contentView0(getWindowHandle());
-            if( offscreenInstance ) {
-                orderOut0(0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle());
-            } else {
-                setTitle0(getWindowHandle(), getTitle());
+            
+            final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, fullscreen, 
+                                               ( isUndecorated() || offscreenInstance ) ? NSBorderlessWindowMask :
+                                               NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask,
+                                               NSBackingStoreBuffered, surfaceHandle);
+            if ( newWin == 0 ) {
+                throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this);
             }
+            setWindowHandle( newWin );
+            
+            final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance;
+            // Non blocking initialization on main-thread!                
+            OSXUtil.RunOnMainThread(false, new Runnable() {
+                public void run() {
+                    initWindow0( parentWin, newWin, pS.getX(), pS.getY(), width, height,
+                                 isOpaque, fullscreen, visible && !offscreenInstance, surfaceHandle);
+                    if( offscreenInstance ) {
+                        orderOut0(0!=parentWin ? parentWin : newWin);
+                    } else {
+                        setTitle0(newWin, getTitle());
+                        setAlwaysOnTop0(getWindowHandle(), alwaysOnTop);
+                    }
+                    visibleChanged(true, visible);
+                } } );
         } catch (Exception ie) {
             ie.printStackTrace();
         }
     }
     
     protected static native boolean initIDs0();
-    private native long createWindow0(long parentWindowHandle, int x, int y, int w, int h,
-                                     boolean opaque, boolean fullscreen, int windowStyle,
-                                     int backingStoreType,
-                                     int screen_idx, long view);
-    private native boolean lockSurface0(long window);
-    private native void unlockSurface0(long window);
+    private native long createView0(int x, int y, int w, int h, boolean fullscreen);
+    private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view);
+    /** Must be called on Main-Thread */
+    private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h,
+                                    boolean opaque, boolean fullscreen, boolean visible, long view);
+    private native boolean lockSurface0(long window, long view);
+    private native boolean unlockSurface0(long window, long view);
+    /** Must be called on Main-Thread */
     private native void requestFocus0(long window, boolean force);
+    /** Must be called on Main-Thread */
     private native void resignFocus0(long window);
-    /** in case of a child window, it actually only issues orderBack(..) */
+    /** Must be called on Main-Thread. In case this is a child window and parent is still visible, orderBack(..) is issued instead of orderOut(). */
     private native void orderOut0(long window);
+    /** Must be called on Main-Thread */
     private native void orderFront0(long window);
+    /** Must be called on Main-Thread */
     private native void close0(long window);
+    /** Must be called on Main-Thread */
     private native void setTitle0(long window, String title);
     private native long contentView0(long window);
-    private native long changeContentView0(long parentWindowOrViewHandle, long window, long view);
-    private native void setContentSize0(long window, int w, int h);
-    private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y);
+    /** Must be called on Main-Thread */
+    private native void changeContentView0(long parentWindowOrView, long window, long view);
+    /** Must be called on Main-Thread */
+    private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h, boolean display);
+    /** Must be called on Main-Thread */    
+    private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display);
+    /** Must be called on Main-Thread */
     private native void setAlwaysOnTop0(long window, boolean atop);
     private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y);
     private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible);
diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
index 615f9e6..1b9ec0f 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
@@ -51,16 +51,21 @@ public class DisplayDriver extends DisplayImpl {
     static {
         NEWTJNILibLoader.loadNEWT();
 
-        if (!WindowDriver.initIDs0()) {
+        sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowDriver.getNewtWndProc0());
+        
+        if (!WindowDriver.initIDs0(RegisteredClassFactory.getHInstance())) {
             throw new NativeWindowException("Failed to initialize WindowsWindow jmethodIDs");
         }        
-        sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowDriver.getNewtWndProc0());
     }
 
     public static void initSingleton() {
         // just exist to ensure static init has been run
     }
 
+    protected static long getHInstance() {
+        return RegisteredClassFactory.getHInstance();
+    }
+
     private RegisteredClass sharedClass;
 
     public DisplayDriver() {
@@ -80,10 +85,6 @@ public class DisplayDriver extends DisplayImpl {
         DispatchMessages0();
     }
 
-    protected long getHInstance() {
-        return sharedClass.getHandle();
-    }
-
     protected String getWindowClassName() {
         return sharedClass.getName();
     }
diff --git a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
index 948b294..3428296 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
@@ -34,91 +34,143 @@
 package jogamp.newt.driver.windows;
 
 import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
 
+import jogamp.newt.MonitorModeProps;
 import jogamp.newt.ScreenImpl;
 
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.Screen;
 
 public class ScreenDriver extends ScreenImpl {
 
     static {
         DisplayDriver.initSingleton();
+        if( Screen.DEBUG ) {
+            dumpMonitorInfo0();
+        }
     }
 
     public ScreenDriver() {
     }
 
+    @Override
     protected void createNativeImpl() {
         aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
     }
     
+    @Override
     protected void closeNativeImpl() {
     }
 
-    private int[] getScreenModeIdx(int idx) {
-        int[] modeProps = getScreenMode0(screen_idx, idx);
-        if (null == modeProps || 0 == modeProps.length) {
+    private final String getAdapterName(int crt_idx) {
+        return getAdapterName0(crt_idx);
+    }
+    private final String getActiveMonitorName(String adapterName, int monitor_idx) {
+        return getActiveMonitorName0(adapterName, monitor_idx);
+    }
+    
+    private final MonitorMode getMonitorModeImpl(MonitorModeProps.Cache cache, String adapterName, int crtModeIdx) {
+        if( null == adapterName ) {
             return null;
         }
-        if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) {
-            throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length);
+        final String activeMonitorName = getActiveMonitorName(adapterName, 0);
+        final int[] modeProps = null != activeMonitorName ? getMonitorMode0(adapterName, crtModeIdx) : null;
+        if ( null == modeProps || 0 >= modeProps.length) {
+            return null;
         }
-        return modeProps;
+        return MonitorModeProps.streamInMonitorMode(null, cache, modeProps, 0);
     }
 
-    private int nativeModeIdx;
-
-    protected int[] getScreenModeFirstImpl() {
-        nativeModeIdx = 0;
-        return getScreenModeNextImpl();
-    }
-
-    protected int[] getScreenModeNextImpl() {
-        int[] modeProps = getScreenModeIdx(nativeModeIdx);
-        if (null != modeProps && 0 < modeProps.length) {
-            nativeModeIdx++;
-            return modeProps;
+    @Override
+    protected void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+        int crtIdx = 0;
+        ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
+        String adapterName = getAdapterName(crtIdx);
+        while( null != adapterName ) {
+            int crtModeIdx = 0;
+            MonitorMode mode;
+            do {
+                mode = getMonitorModeImpl(cache, adapterName, crtModeIdx);
+                if( null != mode ) {
+                    supportedModes.getOrAdd(mode);
+                    // next mode on same monitor
+                    crtModeIdx++;
+                }
+            } while( null != mode);
+            if( 0 < crtModeIdx ) {
+                // has at least one mode -> add device
+                final MonitorMode currentMode = getMonitorModeImpl(cache, adapterName, -1);
+                if ( null != currentMode ) { // enabled
+                    final int[] monitorProps = getMonitorDevice0(adapterName, crtIdx);
+                    // merge monitor-props + supported modes
+                    MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, monitorProps, 0);
+                    
+                    // next monitor, 1st mode
+                    supportedModes= new ArrayHashSet<MonitorMode>();
+                }
+            }
+            crtIdx++;
+            adapterName = getAdapterName(crtIdx);
         }
-        return null;
     }
-
-    protected ScreenMode getCurrentScreenModeImpl() {
-        int[] modeProps = getScreenModeIdx(-1);
-        if (null != modeProps && 0 < modeProps.length) {
-            return ScreenModeUtil.streamIn(modeProps, 0);
+    
+    @Override
+    protected Rectangle getNativeMonitorDeviceViewportImpl(MonitorDevice monitor) {
+        final String adapterName = getAdapterName(monitor.getId());
+        if( null != adapterName ) {
+            final String activeMonitorName = getActiveMonitorName(adapterName, 0);
+            if( null != activeMonitorName ) {
+                final int[] monitorProps = getMonitorDevice0(adapterName, monitor.getId());
+                int offset = MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT;
+                return new Rectangle(monitorProps[offset++], monitorProps[offset++], monitorProps[offset++], monitorProps[offset++]);
+            }
         }
         return null;
     }
 
-    protected boolean setCurrentScreenModeImpl(ScreenMode sm) {
-        return setScreenMode0(screen_idx, 
-                              sm.getMonitorMode().getSurfaceSize().getResolution().getWidth(),
-                              sm.getMonitorMode().getSurfaceSize().getResolution().getHeight(),
-                              sm.getMonitorMode().getSurfaceSize().getBitsPerPixel(),
-                              sm.getMonitorMode().getRefreshRate(),
-                              sm.getRotation());
+    @Override
+    protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) {
+        return getMonitorModeImpl(null, getAdapterName(monitor.getId()), -1);
+    }
+    
+    @Override
+    protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode)  {
+        return setMonitorMode0(monitor.getId(),
+                               -1, -1, // no fixed position!
+                               mode.getSurfaceSize().getResolution().getWidth(),
+                               mode.getSurfaceSize().getResolution().getHeight(),
+                               mode.getSurfaceSize().getBitsPerPixel(),
+                               (int)mode.getRefreshRate(), // simply cut-off, orig is int
+                               mode.getFlags(),
+                               mode.getRotation());
     }
 
+    @Override
     protected int validateScreenIndex(int idx) {
-        return 0; // big-desktop, only one screen available 
+        return 0; // big-desktop w/ multiple monitor attached, only one screen available 
     }
         
-    protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
-        virtualOrigin.setX(getOriginX0(screen_idx));
-        virtualOrigin.setY(getOriginY0(screen_idx));
-        virtualSize.setWidth(getWidthImpl0(screen_idx));
-        virtualSize.setHeight(getHeightImpl0(screen_idx));
+    @Override
+    protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) {
+        vOriginSize.setX(getVirtualOriginX0());
+        vOriginSize.setY(getVirtualOriginY0());
+        vOriginSize.setWidth(getVirtualWidthImpl0());
+        vOriginSize.setHeight(getVirtualHeightImpl0());
     }
     
     // Native calls
-    private native int getOriginX0(int screen_idx);
-    private native int getOriginY0(int screen_idx);
-    private native int getWidthImpl0(int scrn_idx);
-    private native int getHeightImpl0(int scrn_idx);
+    private native int getVirtualOriginX0();
+    private native int getVirtualOriginY0();
+    private native int getVirtualWidthImpl0();
+    private native int getVirtualHeightImpl0();
 
-    private native int[] getScreenMode0(int screen_index, int mode_index);
-    private native boolean setScreenMode0(int screen_index, int width, int height, int bits, int freq, int rot);
+    private static native void dumpMonitorInfo0();
+    private native String getAdapterName0(int crt_index);
+    private native String getActiveMonitorName0(String adapterName, int crtModeIdx);
+    private native int[] getMonitorMode0(String adapterName, int crtModeIdx);
+    private native int[] getMonitorDevice0(String adapterName, int monitor_index);
+    private native boolean setMonitorMode0(int monitor_index, int x, int y, int width, int height, int bits, int freq, int flags, int rot);
 }
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
index 6aac861..7a8e683 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
@@ -46,7 +46,6 @@ import javax.media.nativewindow.util.Insets;
 import javax.media.nativewindow.util.InsetsImmutable;
 import javax.media.nativewindow.util.Point;
 
-import com.jogamp.common.util.IntIntHashMap;
 import com.jogamp.newt.event.InputEvent;
 import com.jogamp.newt.event.KeyEvent;
 import com.jogamp.newt.event.MouseAdapter;
@@ -71,13 +70,20 @@ public class WindowDriver extends WindowImpl {
         if (0 != hdc) {
             throw new InternalError("surface not released");
         }
-        hdc = GDI.GetDC(getWindowHandle());
-        hmon = MonitorFromWindow0(getWindowHandle());
+        final long hWnd = getWindowHandle();
+        hdc = GDI.GetDC(hWnd);
         
         // return ( 0 == hdc ) ? LOCK_SURFACE_NOT_READY : ( hdc_old != hdc ) ? LOCK_SURFACE_CHANGED : LOCK_SUCCESS ;
         if( 0 == hdc ) { 
             return LOCK_SURFACE_NOT_READY;
-        }
+        }        
+        hmon = MonitorFromWindow0(hWnd);
+        
+        // Let's not trigger on HDC change, GLDrawableImpl.'s destroy/create is a nop here anyways.
+        // FIXME: Validate against EGL surface creation: ANGLE uses HWND -> fine!
+        return LOCK_SUCCESS; 
+        
+        /**
         if( hdc_old == hdc ) {
             return LOCK_SUCCESS;
         }
@@ -85,7 +91,7 @@ public class WindowDriver extends WindowImpl {
             System.err.println("WindowsWindow: surface change "+toHexString(hdc_old)+" -> "+toHexString(hdc));
             // Thread.dumpStack();
         }
-        return LOCK_SURFACE_CHANGED;        
+        return LOCK_SURFACE_CHANGED; */        
     }
 
     @Override
@@ -130,27 +136,27 @@ public class WindowDriver extends WindowImpl {
         setGraphicsConfiguration(cfg);
         final int flags = getReconfigureFlags(0, true) & 
                           ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
-        setWindowHandle(CreateWindow0(display.getHInstance(), display.getWindowClassName(), display.getWindowClassName(),
-                                      getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags)); 
-        if (getWindowHandle() == 0) {
+        final long _windowHandle = CreateWindow0(DisplayDriver.getHInstance(), display.getWindowClassName(), display.getWindowClassName(),
+                                                 getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags); 
+        if ( 0 == _windowHandle ) {
             throw new NativeWindowException("Error creating window");
         }
-        windowHandleClose = getWindowHandle();
-        addMouseListener(new MouseTracker());
+        setWindowHandle(_windowHandle);
+        windowHandleClose = _windowHandle;
+        addMouseListener(mouseTracker);
         
         if(DEBUG_IMPLEMENTATION) {
             Exception e = new Exception("Info: Window new window handle "+Thread.currentThread().getName()+
                                         " (Parent HWND "+toHexString(getParentWindowHandle())+
-                                        ") : HWND "+toHexString(getWindowHandle())+", "+Thread.currentThread());
+                                        ") : HWND "+toHexString(_windowHandle)+", "+Thread.currentThread());
             e.printStackTrace();
         }
-    }
-    
-    class MouseTracker extends MouseAdapter {
+    }    
+    private MouseAdapter mouseTracker = new MouseAdapter() {
         public void mouseEntered(MouseEvent e) {
             WindowDriver.trackPointerLeave0(WindowDriver.this.getWindowHandle());
         }
-    }
+    };
 
     protected void closeNativeImpl() {
         if(windowHandleClose != 0) {
@@ -217,14 +223,14 @@ public class WindowDriver extends WindowImpl {
 
     @Override
     protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
-        final Boolean[] res = new Boolean[] { Boolean.FALSE };
+        final boolean[] res = new boolean[] { false };
         
         this.runOnEDTIfAvail(true, new Runnable() {
             public void run() {
-                res[0] = Boolean.valueOf(setPointerVisible0(getWindowHandle(), pointerVisible));
+                res[0] = setPointerVisible0(getWindowHandle(), pointerVisible);
             }
         });
-        return res[0].booleanValue();
+        return res[0];
     }
 
     @Override
@@ -260,80 +266,65 @@ public class WindowDriver extends WindowImpl {
         // nop - using event driven insetsChange(..)         
     }
     
-    private final void emitKeyEvent(boolean send, boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
-        if( send ) {
-            super.sendKeyEvent(eventType, modifiers, keyCode, keyChar);
-        } else {
-            super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keyChar);
-        }
+    private short repeatedKey = KeyEvent.VK_UNDEFINED;
+    
+    private final boolean handlePressTypedAutoRepeat(boolean isModifierKey, int modifiers, short keyCode, short keySym, char keyChar) {
+        if( setKeyPressed(keyCode, true) ) {
+            // AR: Key was already pressed: Either [enter | within] AR mode
+            final boolean withinAR = repeatedKey == keyCode;
+            repeatedKey = keyCode;
+            if( !isModifierKey ) {
+                // AR: Key was already pressed: Either [enter | within] AR mode
+                modifiers |= InputEvent.AUTOREPEAT_MASK;
+                if( withinAR ) {
+                    // AR: Within AR mode
+                    super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar);
+                } // else { AR: Enter AR mode - skip already send PRESSED ; or ALT }
+                super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar);
+            }
+            return true;
+        } 
+        return false;
     }
     
-    /** FIXME: We have to store the keyChar for typed events, since keyChar from pressed/released may be wrong (Uppercase: SHIFT-1, etc ..). */
-    private IntIntHashMap typedKeyCode2KeyChar = new IntIntHashMap(KeyEvent.VK_CONTEXT_MENU+1); 
-
-    private final void handleKeyEvent(boolean send, boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
-        final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
-        // System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar+">, mods "+toHexString(modifiers)+", was: pressed "+isKeyPressed(keyCode)+", repeat "+isKeyInAutoRepeat(keyCode)+", isModifierKeyCode "+isModifierKeyCode);
+    @Override
+    public final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+        final boolean isModifierKey = KeyEvent.isModifierKey(keySym);
+        // System.err.println("*** sendKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar+">, mods "+toHexString(modifiers)+
+        //                   ", isKeyCodeTracked "+isKeyCodeTracked(keyCode)+", was: pressed "+isKeyPressed(keyCode)+", repeat "+isKeyInAutoRepeat(keyCode)+", printableKey "+KeyEvent.isPrintableKey(keyCode)+" [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis());
         
-        // Reorder: WINDOWS delivery order is PRESSED, TYPED and RELEASED -> NEWT order: PRESSED, RELEASED and TYPED
-        // Auto-Repeat: WINDOWS delivers only PRESSED and TYPED.        
+        // Reorder: WINDOWS delivery order is PRESSED (t0), TYPED (t0) and RELEASED (t1) -> NEWT order: PRESSED (t0) and RELEASED (t1)
+        // Auto-Repeat: WINDOWS delivers only PRESSED (t0) and TYPED (t0).        
         switch(eventType) {
             case KeyEvent.EVENT_KEY_RELEASED:
                 if( isKeyCodeTracked(keyCode) ) {
-                    if( keyRepeatState.put(keyCode, false) && !isModifierKeyCode ) {
+                    if( repeatedKey == keyCode && !isModifierKey ) {
                         // AR out - send out missing PRESSED
-                        emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_PRESSED, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, keyChar);
+                        super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, keySym, keyChar);
                     }
-                    keyPressedState.put(keyCode, false);
+                    setKeyPressed(keyCode, false);
+                    repeatedKey = KeyEvent.VK_UNDEFINED;
                 }
-                final int keyCharTyped = typedKeyCode2KeyChar.put(keyCode, 0);
-                if( 0 != keyCharTyped ) {
-                    keyChar = (char)keyCharTyped;
-                }
-                emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
-                emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_TYPED, modifiers, keyCode, keyChar);
+                super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar);
                 break;
             case KeyEvent.EVENT_KEY_PRESSED:
-                if( isKeyCodeTracked(keyCode) ) {
-                    if( keyPressedState.put(keyCode, true) ) {
-                        // key was already pressed
-                        if( keyRepeatState.put(keyCode, true) && !isModifierKeyCode ) {
-                            emitKeyEvent(send, wait, eventType, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, keyChar);
-                        } // else AR in - skip already send PRESSED ; or ALT
-                    } else {
-                        emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
-                    }
-                } else {
-                    emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
-                }
-                break;
-            case KeyEvent.EVENT_KEY_TYPED:
-                if( 1 == isKeyInAutoRepeat(keyCode) ) {
-                    modifiers |= InputEvent.AUTOREPEAT_MASK;
-                    emitKeyEvent(send, wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keyChar);
-                    emitKeyEvent(send, wait, eventType, modifiers, keyCode, keyChar);
-                } else if( 0 != keyCode ) {
-                    typedKeyCode2KeyChar.put(keyCode, keyChar);
+                if( !handlePressTypedAutoRepeat(isModifierKey, modifiers, keyCode, keySym, keyChar) ) {
+                    super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar);
                 }
                 break;
         }
     }
     
     @Override
-    public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
-        handleKeyEvent(true, false, eventType, modifiers, keyCode, keyChar);
-    }
-    
-    @Override
-    public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
-        handleKeyEvent(false, wait, eventType, modifiers, keyCode, keyChar);
+    public final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+        throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
     }
     
     //----------------------------------------------------------------------
     // Internals only
     //
-    protected static native boolean initIDs0();
     protected static native long getNewtWndProc0();
+    protected static native boolean initIDs0(long hInstance);
 
     private native long CreateWindow0(long hInstance, String wndClassName, String wndName,
                                       long parentWindowHandle,
diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
index f3a548a..88d06f6 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
@@ -57,10 +57,8 @@ public class DisplayDriver extends DisplayImpl {
         }
     }
 
-    public static void initSingleton() {
-        // just exist to ensure static init has been run
-    }
-
+    /** Ensure static init has been run. */
+    /* pp */static void initSingleton() { }
 
     public DisplayDriver() {
     }
@@ -91,9 +89,10 @@ public class DisplayDriver extends DisplayImpl {
 
     @Override
     protected void closeNativeImpl() {
-        DisplayRelease0(aDevice.getHandle(), javaObjectAtom, windowDeleteAtom);
+        DisplayRelease0(aDevice.getHandle(), javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
         javaObjectAtom = 0;
         windowDeleteAtom = 0;
+        // kbdHandle = 0;
         aDevice.close(); // closes X11 display
     }
 
@@ -103,7 +102,7 @@ public class DisplayDriver extends DisplayImpl {
         try {
             final long handle = aDevice.getHandle();
             if(0 != handle) {
-                DispatchMessages0(handle, javaObjectAtom, windowDeleteAtom);
+                DispatchMessages0(handle, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
             }
         } finally {
             if(null != aDevice) { // could be pulled by destroy event
@@ -114,6 +113,7 @@ public class DisplayDriver extends DisplayImpl {
 
     protected long getJavaObjectAtom() { return javaObjectAtom; }
     protected long getWindowDeleteAtom() { return windowDeleteAtom; }
+    // protected long getKbdHandle() { return kbdHandle; } // XKB disabled for now
     
     /** Returns <code>null</code> if !{@link #isNativeValid()}, otherwise the Boolean value of {@link X11GraphicsDevice#isXineramaEnabled()}. */ 
     protected Boolean isXineramaEnabled() { return isNativeValid() ? Boolean.valueOf(((X11GraphicsDevice)aDevice).isXineramaEnabled()) : null; }
@@ -126,18 +126,22 @@ public class DisplayDriver extends DisplayImpl {
 
     private native void CompleteDisplay0(long handle);
 
-    private void displayCompleted(long javaObjectAtom, long windowDeleteAtom) {
+    private void displayCompleted(long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle */) {
         this.javaObjectAtom=javaObjectAtom;
         this.windowDeleteAtom=windowDeleteAtom;
+        // this.kbdHandle = kbdHandle; // XKB disabled for now
     }
-    private native void DisplayRelease0(long handle, long javaObjectAtom, long windowDeleteAtom);
+    private native void DisplayRelease0(long handle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle */); // XKB disabled for now
 
-    private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom);
+    private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom /* , long kbdHandle */); // XKB disabled for now
 
     /** X11 Window delete atom marker used on EDT */
     private long windowDeleteAtom;
     
     /** X11 Window java object property used on EDT */
     private long javaObjectAtom;    
+    
+    /** X11 Keyboard handle used on EDT */
+    // private long kbdHandle; // XKB disabled for now
 }
 
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR.java b/src/newt/classes/jogamp/newt/driver/x11/RandR.java
new file mode 100644
index 0000000..c569e5f
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR.java
@@ -0,0 +1,76 @@
+/**
+ * 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 jogamp.newt.driver.x11;
+
+import java.util.List;
+
+import jogamp.newt.MonitorModeProps;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+public interface RandR {
+
+    void dumpInfo(final long dpy, final int screen_idx);
+    
+    /**
+     * Encapsulate initial device query allowing caching of internal data structures. 
+     * Methods covered:
+     * <ul> 
+     *   <li>{@link #getMonitorDeviceCount(long, ScreenDriver)}</li>
+     *   <li>{@link #getAvailableRotations(long, ScreenDriver, int)}</li>
+     *   <li>{@link #getMonitorModeProps(long, ScreenDriver, int)}</li>
+     *   <li>{@link #getCurrentMonitorModeProps(long, ScreenDriver, int)</li>
+     *   <li>{@link #getMonitorDeviceProps(long, ScreenDriver, List, int, MonitorMode)}</li>
+     * </ul>
+     * <p>
+     * Above methods may be called w/o begin/end, in which case no 
+     * internal data structures can be cached:
+     * </p>
+     * @param dpy TODO
+     * @param screen TODO
+     * @return TODO
+     */
+    boolean beginInitialQuery(long dpy, ScreenDriver screen);
+    void endInitialQuery(long dpy, ScreenDriver screen);
+    
+    int getMonitorDeviceCount(final long dpy, final ScreenDriver screen);
+    int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx);
+    /**
+     * 
+     * @param dpy
+     * @param screen
+     * @param mode_idx w/o indexing rotation
+     * @return props w/o actual rotation
+     */
+    int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx);
+    int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_idx);
+    int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx);
+    int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx);
+    boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode);    
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
new file mode 100644
index 0000000..a938b40
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
@@ -0,0 +1,361 @@
+/**
+ * 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 jogamp.newt.driver.x11;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+public class RandR11 implements RandR {
+    private static final boolean DEBUG = ScreenDriver.DEBUG;
+    
+    public static VersionNumber version = new VersionNumber(1, 1, 0);
+    
+    public static RandR11 createInstance(VersionNumber rAndRVersion) {
+        if( rAndRVersion.compareTo(version) >= 0 ) {
+            return new RandR11();
+        }
+        return null;
+    }    
+    private RandR11() {        
+    }
+    
+    @Override
+    public void dumpInfo(final long dpy, final int screen_idx) {
+        // NOP
+    }
+    
+    private int widthMM=0, heightMM=0;
+    private int modeCount = 0;
+    private int resolutionCount = 0;
+    private int[][] nrates = null; // [nres_number][nrate_number]
+    private int[] idx_rate = null, idx_res = null;
+    
+    @Override
+    public boolean beginInitialQuery(long dpy, ScreenDriver screen) {
+        // initialize iterators and static data
+        final int screen_idx = screen.getIndex();
+        resolutionCount = getNumScreenResolutions0(dpy, screen_idx);
+        if(0==resolutionCount) {
+            endInitialQuery(dpy, screen);
+            return false;
+        }
+
+        nrates = new int[resolutionCount][];
+        for(int i=0; i<resolutionCount; i++) {
+            nrates[i] = getScreenRates0(dpy, screen_idx, i);
+            if(null==nrates[i] || 0==nrates[i].length) {
+                endInitialQuery(dpy, screen);
+                return false;
+            }
+        }
+        
+        for(int nresIdx=0; nresIdx < resolutionCount; nresIdx++) {
+            modeCount += nrates[nresIdx].length;
+        }
+        
+        idx_rate = new int[modeCount];
+        idx_res = new int[modeCount];
+
+        int modeIdx=0;
+        for(int nresIdx=0; nresIdx < resolutionCount; nresIdx++) {
+            for(int nrateIdx=0; nrateIdx < nrates[nresIdx].length; nrateIdx++) {
+                idx_rate[modeIdx] = nrateIdx;
+                idx_res[modeIdx] = nresIdx;
+                modeIdx++;
+            }
+        }
+        return true;
+    }
+    
+    @Override
+    public void endInitialQuery(long dpy, ScreenDriver screen) {
+        idx_rate=null;
+        idx_res=null;            
+        nrates=null;        
+    }
+    
+    @Override
+    public int getMonitorDeviceCount(final long dpy, final ScreenDriver screen) {
+        return 1;
+    }
+    
+    @Override
+    public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx) {
+        if( 0 < crt_idx ) {
+            // RandR11 only supports 1 CRT 
+            return null;
+        }
+        final int screen_idx = screen.getIndex();
+        final int[] availRotations = getAvailableScreenRotations0(dpy, screen_idx);
+        if(null==availRotations || 0==availRotations.length) {
+            return null;
+        }
+        return availRotations;
+    }
+    
+    @Override
+    public int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx) {
+        if( mode_idx >= modeCount ) {
+            return null;
+        }        
+        final int screen_idx = screen.getIndex();
+        
+        final int nres_index = idx_res[mode_idx];
+        final int nrate_index = idx_rate[mode_idx];
+        
+        final int[] res = getScreenResolution0(dpy, screen_idx, nres_index);
+        if(null==res || 0==res.length) {
+            return null;
+        }
+        if(0>=res[0] || 0>=res[1]) {
+            throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+resolutionCount);
+        }
+        if( res[2] > widthMM ) {
+            widthMM = res[2];
+        }
+        if( res[3] > heightMM ) {
+            heightMM = res[3];
+        }
+        
+        int rate = nrates[nres_index][nrate_index];
+        if(0>=rate) {
+            rate = ScreenImpl.default_sm_rate;
+            if(DEBUG) {
+                System.err.println("Invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length+", using default: "+ScreenImpl.default_sm_rate);
+            }
+        }
+
+        int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+        int i = 0;
+        props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+        props[i++] = res[0]; // width
+        props[i++] = res[1]; // height
+        props[i++] = ScreenImpl.default_sm_bpp; // bpp n/a in RandR11
+        props[i++] = rate*100;  // rate (Hz*100)
+        props[i++] = 0; // flags;
+        props[i++] = nres_index;
+        props[i++] = -1; // rotation placeholder;
+        if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) {
+            throw new InternalError("XX");
+        }
+        return props;        
+    }
+    
+    @Override
+    public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, final MonitorModeProps.Cache cache, final int crt_idx) {
+        if( 0 < crt_idx ) {
+            // RandR11 only supports 1 CRT 
+            return null;
+        }
+        final int[] currentModeProps = getCurrentMonitorModeProps(dpy, screen, crt_idx);
+        if( null == currentModeProps) { // disabled
+            return null;
+        }
+        final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, currentModeProps, 0);
+        final int allModesCount = cache.monitorModes.size();
+        final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 + allModesCount];
+        int i = 0;
+        props[i++] = props.length;
+        props[i++] = crt_idx;
+        props[i++] = widthMM;
+        props[i++] = heightMM;
+        props[i++] = 0; // rotated viewport x
+        props[i++] = 0; // rotated viewport y
+        props[i++] = currentMode.getRotatedWidth();  // rotated viewport width
+        props[i++] = currentMode.getRotatedHeight(); // rotated viewport height
+        props[i++] = currentMode.getId(); // current mode id
+        props[i++] = currentMode.getRotation();
+        for(int j=0; j<allModesCount; j++) {
+            props[i++] = cache.monitorModes.get(j).getId(); 
+        }
+        return props;
+    }
+    
+    @Override
+    public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx) {
+        if( 0 < crt_idx ) {
+            // RandR11 only supports 1 CRT 
+            return null;
+        }
+        final int screen_idx = screen.getIndex();
+        long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
+        if(0 == screenConfigHandle) {
+            return null;
+        }
+        int[] res;
+        final int nres_idx;
+        try {                
+            int resNumber = getNumScreenResolutions0(dpy, screen_idx);
+            if(0==resNumber) {
+                return null;
+            }
+
+            nres_idx = getCurrentScreenResolutionIndex0(screenConfigHandle);
+            if(0>nres_idx) {
+                return null;
+            }
+            if(nres_idx>=resNumber) {
+                throw new RuntimeException("Invalid resolution index: ! "+nres_idx+" < "+resNumber);
+            }
+            res = getScreenResolution0(dpy, screen_idx, nres_idx);
+            if(null==res || 0==res.length) {
+                return null;
+            }
+            if(0>=res[0] || 0>=res[1]) {
+                throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_idx+"/"+resNumber);
+            }
+        } finally {
+             freeScreenConfiguration0(screenConfigHandle);
+        }
+        int[] props = new int[4];
+        int i = 0;
+        props[i++] = 0;
+        props[i++] = 0;
+        props[i++] = res[0]; // width
+        props[i++] = res[1]; // height
+        return props;        
+    }
+    
+    @Override
+    public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx) {
+        if( 0 < crt_idx ) {
+            // RandR11 only supports 1 CRT 
+            return null;
+        }
+        final int screen_idx = screen.getIndex();
+        long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
+        if(0 == screenConfigHandle) {
+            return null;
+        }
+        int[] res;
+        int rate, rot;
+        final int nres_idx;
+        try {                
+            int resNumber = getNumScreenResolutions0(dpy, screen_idx);
+            if(0==resNumber) {
+                return null;
+            }
+
+            nres_idx = getCurrentScreenResolutionIndex0(screenConfigHandle);
+            if(0>nres_idx) {
+                return null;
+            }
+            if(nres_idx>=resNumber) {
+                throw new RuntimeException("Invalid resolution index: ! "+nres_idx+" < "+resNumber);
+            }
+            res = getScreenResolution0(dpy, screen_idx, nres_idx);
+            if(null==res || 0==res.length) {
+                return null;
+            }
+            if(0>=res[0] || 0>=res[1]) {
+                throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_idx+"/"+resNumber);
+            }
+            rate = getCurrentScreenRate0(screenConfigHandle);
+            if(0>rate) {
+                return null;
+            }
+            rot = getCurrentScreenRotation0(screenConfigHandle);
+            if(0>rot) {
+                return null;
+            }
+        } finally {
+             freeScreenConfiguration0(screenConfigHandle);
+        }
+        int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+        int i = 0;
+        props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+        props[i++] = res[0]; // width
+        props[i++] = res[1]; // height
+        props[i++] = ScreenImpl.default_sm_bpp;
+        props[i++] = rate*100;  // rate (Hz*100)
+        props[i++] = 0; // flags;
+        props[i++] = nres_idx; // mode_idx;
+        props[i++] = rot;
+        if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) {
+            throw new InternalError("XX");
+        }
+        return props;
+    }
+
+    @Override
+    public boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode) {
+        final long t0 = System.currentTimeMillis();
+        boolean done = false;
+        final int screen_idx = screen.getIndex();
+        long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
+        if(0 == screenConfigHandle) {
+            return Boolean.valueOf(done);
+        }
+        try {
+            final int resId = mode.getId();
+            if(0>resId || resId>=resolutionCount) {
+                throw new RuntimeException("Invalid resolution index: ! 0 < "+resId+" < "+resolutionCount+", "+monitor+", "+mode);
+            }    
+            final int f = (int)mode.getRefreshRate(); // simply cut-off, orig is int
+            final int r = mode.getRotation();
+
+            if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resId, f, r) ) {
+                while(!done && System.currentTimeMillis()-t0 < ScreenImpl.SCREEN_MODE_CHANGE_TIMEOUT) {
+                    done = setCurrentScreenModePollEnd0(dpy, screen_idx, resId, f, r);
+                    if(!done) {
+                        try { Thread.sleep(10); } catch (InterruptedException e) { }
+                    }
+                }
+            }
+        } finally {
+             freeScreenConfiguration0(screenConfigHandle);
+        }
+        return done;
+    }
+
+    /** @return int[] { rot1, .. } */
+    private static native int[] getAvailableScreenRotations0(long display, int screen_index);
+
+    private static native int getNumScreenResolutions0(long display, int screen_index);
+
+    /** @return int[] { width, height, widthmm, heightmm } */
+    private static native int[] getScreenResolution0(long display, int screen_index, int mode_index);
+
+    private static native int[] getScreenRates0(long display, int screen_index, int mode_index);
+
+    private static native long getScreenConfiguration0(long display, int screen_index);
+    private static native void freeScreenConfiguration0(long screenConfiguration);
+    
+    private static native int getCurrentScreenResolutionIndex0(long screenConfiguration);
+    private static native int getCurrentScreenRate0(long screenConfiguration);
+    private static native int getCurrentScreenRotation0(long screenConfiguration);
+
+    /** needs own Display connection for XRANDR event handling */
+    private static native boolean setCurrentScreenModeStart0(long display, int screen_index, long screenConfiguration, int mode_index, int freq, int rot);
+    private static native boolean setCurrentScreenModePollEnd0(long display, int screen_index, int mode_index, int freq, int rot);
+    
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
new file mode 100644
index 0000000..d105913
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
@@ -0,0 +1,309 @@
+/**
+ * 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 jogamp.newt.driver.x11;
+
+import java.util.Iterator;
+
+import jogamp.newt.MonitorModeProps;
+
+import com.jogamp.common.util.IntLongHashMap;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+/**
+ * Mapping details:
+ * <pre>
+ * MonitorMode.id   == XRR mode-id (not index)
+ * MonitorDevice.id == XRR monitor-idx (not id)
+ * </pre> 
+ */
+public class RandR13 implements RandR {
+    private static final boolean DEBUG = ScreenDriver.DEBUG;
+    
+    public static VersionNumber version = new VersionNumber(1, 3, 0);
+
+    public static RandR13 createInstance(VersionNumber rAndRVersion) {
+        if( rAndRVersion.compareTo(version) >= 0 ) {
+            return new RandR13();
+        }
+        return null;
+    }    
+    private RandR13() {        
+    }
+    
+    @Override
+    public void dumpInfo(final long dpy, final int screen_idx) {
+        long screenResources = getScreenResources0(dpy, screen_idx);
+        if(0 == screenResources) {
+            return;
+        }
+        try {
+            dumpInfo0(dpy, screen_idx, screenResources);
+        } finally {
+             freeScreenResources0(screenResources);
+        }        
+    }
+    
+    long sessionScreenResources = 0;
+    IntLongHashMap crtInfoHandleMap = null;
+    
+    @Override
+    public boolean beginInitialQuery(long dpy, ScreenDriver screen) {
+        final int screen_idx = screen.getIndex();
+        sessionScreenResources = getScreenResources0(dpy, screen_idx);
+        if( 0 != sessionScreenResources ) {
+            crtInfoHandleMap = new IntLongHashMap();
+            crtInfoHandleMap.setKeyNotFoundValue(0);
+            return true;
+        } else {
+            return false;
+        }
+    }
+    
+    @Override
+    public void endInitialQuery(long dpy, ScreenDriver screen) {
+        if( null != crtInfoHandleMap ) {
+            for(Iterator<IntLongHashMap.Entry> iter = crtInfoHandleMap.iterator(); iter.hasNext(); ) {
+                final IntLongHashMap.Entry entry = iter.next();
+                freeMonitorInfoHandle0(entry.value);
+            }
+            crtInfoHandleMap.clear();
+            crtInfoHandleMap = null;
+        }
+        if( 0 != sessionScreenResources ) {
+            freeScreenResources0( sessionScreenResources );
+            sessionScreenResources = 0;
+        }
+    }
+    
+    private final long getScreenResourceHandle(final long dpy, final int screen_idx) {
+        if( 0 != sessionScreenResources ) {
+            return sessionScreenResources;
+        }
+        return getScreenResources0(dpy, screen_idx);
+    }
+    private final void releaseScreenResourceHandle(final long screenResourceHandle) {
+        if( 0 == sessionScreenResources ) {
+            freeScreenResources0( screenResourceHandle );
+        }
+    }
+    
+    private final long getMonitorInfoHandle(final long dpy, final int screen_idx, long screenResources, final int monitor_idx) {
+        if( null != crtInfoHandleMap ) {
+            long h = crtInfoHandleMap.get(monitor_idx);
+            if( 0 == h ) {
+                h = getMonitorInfoHandle0(dpy, screen_idx, screenResources, monitor_idx);
+                crtInfoHandleMap.put(monitor_idx, h);
+            }
+            return h;
+        } else {
+            return getMonitorInfoHandle0(dpy, screen_idx, screenResources, monitor_idx);
+        }
+    }
+    private final void releaseMonitorInfoHandle(final long monitorInfoHandle) {
+        if( null == crtInfoHandleMap ) {
+            freeMonitorInfoHandle0(monitorInfoHandle);
+        }
+    }    
+    
+    @Override
+    public int getMonitorDeviceCount(final long dpy, final ScreenDriver screen) {
+        final int screen_idx = screen.getIndex();
+        final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+        try {
+            return getMonitorDeviceCount0(screenResources);
+        } finally {
+            releaseScreenResourceHandle(screenResources);
+        }
+    }
+    
+    @Override
+    public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx) {
+        final int screen_idx = screen.getIndex();
+        final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+        try {
+            final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+            try {
+                final int[] availRotations = getAvailableRotations0(monitorInfo);
+                if(null==availRotations || 0==availRotations.length) {
+                    return null;
+                }        
+                return availRotations;
+            } finally {
+                releaseMonitorInfoHandle(monitorInfo);
+            }
+        } finally {
+            releaseScreenResourceHandle(screenResources);
+        }
+    }
+    
+    @Override
+    public int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx) {
+        final int screen_idx = screen.getIndex();
+        final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+        try {
+            return getMonitorMode0(screenResources, mode_idx);
+        } finally {
+            releaseScreenResourceHandle(screenResources);
+        }
+    }
+    
+    @Override
+    public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_idx) {
+        final int screen_idx = screen.getIndex();
+        final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+        try {
+            final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+            try {
+                return getMonitorDevice0(dpy, screenResources, monitorInfo, crt_idx);
+            } finally {
+                releaseMonitorInfoHandle(monitorInfo);
+            }
+        } finally {
+            releaseScreenResourceHandle(screenResources);
+        }
+    }
+    
+    @Override
+    public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx) {        
+        final int screen_idx = screen.getIndex();
+        final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+        try {
+            final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+            try {
+                return getMonitorViewport0(monitorInfo);
+            } finally {
+                releaseMonitorInfoHandle(monitorInfo);
+            }
+        } finally {
+            releaseScreenResourceHandle(screenResources);
+        }
+    }
+    
+    @Override
+    public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx) {
+        final int screen_idx = screen.getIndex();
+        final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+        try {
+            final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+            try {
+                return getMonitorCurrentMode0(screenResources, monitorInfo);
+            } finally {
+                releaseMonitorInfoHandle(monitorInfo);
+            }
+        } finally {
+            releaseScreenResourceHandle(screenResources);
+        }
+    }
+    
+    @Override
+    public boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode) {
+        final int screen_idx = screen.getIndex();
+        final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+        final boolean res;
+        try {
+            final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, monitor.getId());
+            try {
+                res = setMonitorMode0(dpy, screenResources, monitorInfo, monitor.getId(), mode.getId(), mode.getRotation(), 
+                                      -1, -1); // no fixed position!
+            } finally {
+                releaseMonitorInfoHandle(monitorInfo);
+            }
+        } finally {
+            releaseScreenResourceHandle(screenResources);
+        }
+        /*** 
+         * TODO: Would need a complete re-layout of crt positions,
+         *       which is _not_ implicit by XRandR .. sadly.
+         *        
+        if( res ) {
+            updateScreenViewport(dpy, screen, monitor);
+        } */
+        return res;
+    }
+    
+    /** See above ..
+    private final void updateScreenViewport(final long dpy, final ScreenDriver screen, MonitorDevice monitor) {
+        final int screen_idx = screen.getIndex();
+        final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+        try {
+            RectangleImmutable newViewp = null;
+            final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, monitor.getId());
+            try {
+                final int[] vprops = getMonitorViewport0(monitorInfo);
+                if( null != vprops ) {
+                    newViewp = new Rectangle(vprops[0], vprops[1], vprops[2], vprops[3]);
+                }
+                System.err.println("XXX setScreenViewport: newVp "+newViewp);
+            } finally {
+                releaseMonitorInfoHandle(monitorInfo);
+            }
+            if( null != newViewp ) {
+                final List<MonitorDevice> monitors = screen.getMonitorDevices();
+                final ArrayList<RectangleImmutable> viewports = new ArrayList<RectangleImmutable>();
+                for(int i=0; i<monitors.size(); i++) {
+                    final MonitorDevice crt = monitors.get(i);
+                    if( crt.getId() != monitor.getId() ) {
+                        System.err.println("XXX setScreenViewport: add.pre["+i+"]: "+crt.getViewport());
+                        viewports.add( crt.getViewport() ) ;
+                    } else {
+                        System.err.println("XXX setScreenViewport: add.new["+i+"]: "+newViewp);
+                        viewports.add( newViewp );
+                    }
+                }
+                final RectangleImmutable newScrnViewp = new Rectangle().union(viewports);
+                System.err.println("XXX setScreenViewport: "+screen.getViewport()+" -> "+newScrnViewp);
+                setScreenViewport0(dpy, screen_idx, screenResources, newScrnViewp.getX(), newScrnViewp.getY(), newScrnViewp.getWidth(), newScrnViewp.getHeight()); 
+            }
+        } finally {
+            dumpInfo0(dpy, screen_idx, screenResources);
+            releaseScreenResourceHandle(screenResources);
+        }        
+    } */
+        
+    private static native long getScreenResources0(long display, int screen_index);
+    private static native void freeScreenResources0(long screenResources);
+    private static native void dumpInfo0(long display, int screen_index, long screenResources);
+    
+    private static native int getMonitorDeviceCount0(long screenResources);
+    
+    private static native long getMonitorInfoHandle0(long display, int screen_index, long screenResources, int monitor_index);
+    private static native void freeMonitorInfoHandle0(long monitorInfoHandle);
+    
+    private static native int[] getAvailableRotations0(long monitorInfo);
+    private static native int[] getMonitorViewport0(long monitorInfo);
+    private static native int[] getMonitorCurrentMode0(long monitorInfo);
+    
+    private static native int[] getMonitorMode0(long screenResources, int mode_index);
+    private static native int[] getMonitorCurrentMode0(long screenResources, long monitorInfo);
+    private static native int[] getMonitorDevice0(long display, long screenResources, long monitorInfo, int monitor_idx);
+    
+    private static native boolean setMonitorMode0(long display, long screenResources, long monitorInfo, int monitor_idx, int mode_id, int rotation, int x, int y);
+    private static native boolean setScreenViewport0(long display, int screen_index, long screenResources, int x, int y, int width, int height);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
index 7a3c718..e1373bb 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
@@ -33,245 +33,168 @@
  */
 package jogamp.newt.driver.x11;
 
+import java.util.ArrayList;
 import java.util.List;
 
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.util.Rectangle;
 
 import jogamp.nativewindow.x11.X11Util;
+import jogamp.newt.Debug;
 import jogamp.newt.DisplayImpl;
+import jogamp.newt.MonitorModeProps;
 import jogamp.newt.DisplayImpl.DisplayRunnable;
 import jogamp.newt.ScreenImpl;
 
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.VersionNumber;
 import com.jogamp.nativewindow.x11.X11GraphicsDevice;
 import com.jogamp.nativewindow.x11.X11GraphicsScreen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
-
-public class ScreenDriver extends ScreenImpl {
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
 
+public class ScreenDriver extends ScreenImpl {    
+    protected static final boolean DEBUG_TEST_RANDR13_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableRandR13", true);
+    
     static {
         DisplayDriver.initSingleton();
     }
 
+    /** Ensure static init has been run. */
+    /* pp */static void initSingleton() { }
+    
     public ScreenDriver() {
     }
 
+    @Override
     protected void createNativeImpl() {
         // validate screen index
         Long handle = runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Long>() {
             public Long run(long dpy) {        
                 return new Long(GetScreen0(dpy, screen_idx));
-            } } );        
+            } } );
         if (handle.longValue() == 0) {
             throw new RuntimeException("Error creating screen: " + screen_idx);
-        }        
-        aScreen = new X11GraphicsScreen((X11GraphicsDevice) getDisplay().getGraphicsDevice(), screen_idx);
+        }
+        final X11GraphicsDevice x11dev = (X11GraphicsDevice) getDisplay().getGraphicsDevice();        
+        final long dpy = x11dev.getHandle(); 
+        aScreen = new X11GraphicsScreen(x11dev, screen_idx);
+        {
+            int v[] = getRandRVersion0(dpy);
+            randrVersion = new VersionNumber(v[0], v[1], 0);
+        }
+        {
+            final RandR13 rAndR13 = DEBUG_TEST_RANDR13_DISABLED ? null : RandR13.createInstance(randrVersion);
+            if( null != rAndR13 ) {
+                rAndR = rAndR13;
+            } else {
+                rAndR = RandR11.createInstance(randrVersion);
+            }
+        }
+        if( DEBUG ) {
+            System.err.println("RandR "+randrVersion+", "+rAndR);
+            rAndR.dumpInfo(dpy, screen_idx);
+        }
     }
 
+    @Override
     protected void closeNativeImpl() {
     }
 
-    private int[] nrotations;
-    private int nrotation_index;
-    private int nres_number;
-    private int nres_index;
-    private int[] nrates;
-    private int nrate_index;
-    private int nmode_number;
-
-    protected int[] getScreenModeFirstImpl() {
-        return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<int[]>() {
-            public int[] run(long dpy) {
-                // initialize iterators and static data
-                nrotations = getAvailableScreenModeRotations0(dpy, screen_idx);
-                if(null==nrotations || 0==nrotations.length) {
-                    return null;
-                }
-                nrotation_index = 0;
-        
-                nres_number = getNumScreenModeResolutions0(dpy, screen_idx);
-                if(0==nres_number) {
-                    return null;
-                }
-                nres_index = 0;
-        
-                nrates = getScreenModeRates0(dpy, screen_idx, nres_index);
-                if(null==nrates || 0==nrates.length) {
-                    return null;
-                }
-                nrate_index = 0;
-        
-                nmode_number = 0;
-        
-                return getScreenModeNextImpl();
-            } } );
-    }
+    private VersionNumber randrVersion;
+    private RandR rAndR;
 
-    protected int[] getScreenModeNextImpl() {
-        // assemble: w x h x bpp x f x r        
-        return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<int[]>() {
-            public int[] run(long dpy) {
-                /**
-                System.err.println("******** mode: "+nmode_number);
-                System.err.println("rot  "+nrotation_index);
-                System.err.println("rate "+nrate_index);
-                System.err.println("res  "+nres_index); */
-        
-                int[] res = getScreenModeResolution0(dpy, screen_idx, nres_index);
-                if(null==res || 0==res.length) {
-                    return null;
-                }
-                if(0>=res[0] || 0>=res[1]) {
-                    throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+nres_number);
-                }
-                int rate = nrates[nrate_index];
-                if(0>=rate) {
-                    rate = default_sm_rate;
-                    if(DEBUG) {
-                        System.err.println("Invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length+", using default: "+default_sm_rate);
-                    }
-                }
-                int rotation = nrotations[nrotation_index];
-        
-                int[] props = new int[ 1 + ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL ];
-                int i = 0;
-                props[i++] = nres_index; // use resolution index, not unique for native -> ScreenMode
-                props[i++] = 0; // set later for verification of iterator
-                props[i++] = res[0]; // width
-                props[i++] = res[1]; // height
-                props[i++] = default_sm_bpp; // FIXME
-                props[i++] = res[2]; // widthmm
-                props[i++] = res[3]; // heightmm
-                props[i++] = rate;   // rate
-                props[i++] = rotation;
-                props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i - 1; // count without extra element
-        
-                nmode_number++;
-        
-                // iteration: r -> f -> bpp -> [w x h]
-                nrotation_index++;
-                if(nrotation_index == nrotations.length) {
-                    nrotation_index=0;
-                    nrate_index++;
-                    if(null == nrates || nrate_index == nrates.length){
-                        nres_index++;
-                        if(nres_index == nres_number) {
-                            // done
-                            nrates=null;
-                            nrotations=null;
-                            return null;
+    @Override
+    protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+        if( null == rAndR ) { return; }
+        final AbstractGraphicsDevice device = getDisplay().getGraphicsDevice();
+        device.lock();
+        try {
+            if( rAndR.beginInitialQuery(device.getHandle(), this) ) {
+                try {
+                    final int crtCount = rAndR.getMonitorDeviceCount(device.getHandle(), this);
+                    
+                    // Gather all available rotations
+                    final ArrayHashSet<Integer> availableRotations = new ArrayHashSet<Integer>();
+                    for(int i = 0; i < crtCount; i++) {
+                        final int[] rotations = rAndR.getAvailableRotations(device.getHandle(), this, i);
+                        if( null != rotations ) {
+                            final List<Integer> rotationList = new ArrayList<Integer>(rotations.length);
+                            for(int j=0; j<rotations.length; j++ ) { rotationList.add(rotations[j]); }
+                            availableRotations.addAll(rotationList);
                         }
-        
-                        nrates = getScreenModeRates0(dpy, screen_idx, nres_index);
-                        if(null==nrates || 0==nrates.length) {
-                            return null;
+                    }
+                    
+                    // collect all modes, while injecting all available rotations
+                    {
+                        int modeIdx = 0;
+                        int[] props;
+                        do {
+                            props = rAndR.getMonitorModeProps(device.getHandle(), this, modeIdx++);
+                            if( null != props ) {
+                                for(int i = 0; i < availableRotations.size(); i++) {
+                                    props[MonitorModeProps.IDX_MONITOR_MODE_ROT] = availableRotations.get(i);
+                                    MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+                                }
+                            }
+                        } while( null != props);
+                    }
+                    if( cache.monitorModes.size() > 0 ) {
+                        for(int i = 0; i < crtCount; i++) {
+                            final int[] monitorProps = rAndR.getMonitorDeviceProps(device.getHandle(), this, cache, i);
+                            if( null != monitorProps && 
+                                MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps[0] && // Enabled ? I.e. contains active modes ? 
+                                MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps.length ) {
+                                MonitorModeProps.streamInMonitorDevice(null, cache, this, monitorProps, 0);
+                            }
                         }
-                        nrate_index = 0;
                     }
+                } finally {
+                    rAndR.endInitialQuery(device.getHandle(), this);
                 }
-        
-                return props;
-            } } );
+            }
+        } finally {
+            device.unlock();
+        }
     }
 
-    protected ScreenMode getCurrentScreenModeImpl() {
-        return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<ScreenMode>() {
-            public ScreenMode run(long dpy) {
-                long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
-                if(0 == screenConfigHandle) {
-                    return null;
-                }
-                int[] res;
-                int rate, rot;
-                try {                
-                    int resNumber = getNumScreenModeResolutions0(dpy, screen_idx);
-                    if(0==resNumber) {
-                        return null;
-                    }
+    @Override
+    protected Rectangle getNativeMonitorDeviceViewportImpl(MonitorDevice monitor) {
+        final AbstractGraphicsDevice device = getDisplay().getGraphicsDevice();
+        device.lock();
+        try {
+            int[] viewportProps = rAndR.getMonitorDeviceViewport(device.getHandle(), this, monitor.getId());
+            return new Rectangle(viewportProps[0], viewportProps[1], viewportProps[2], viewportProps[3]);
+        } finally {
+            device.unlock();
+        }
+    }
     
-                    int resIdx = getCurrentScreenResolutionIndex0(screenConfigHandle);
-                    if(0>resIdx) {
-                        return null;
-                    }
-                    if(resIdx>=resNumber) {
-                        throw new RuntimeException("Invalid resolution index: ! "+resIdx+" < "+resNumber);
-                    }
-                    res = getScreenModeResolution0(dpy, screen_idx, resIdx);
-                    if(null==res || 0==res.length) {
-                        return null;
-                    }
-                    if(0>=res[0] || 0>=res[1]) {
-                        throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+resIdx+"/"+resNumber);
-                    }
-                    rate = getCurrentScreenRate0(screenConfigHandle);
-                    if(0>rate) {
-                        return null;
-                    }
-                    rot = getCurrentScreenRotation0(screenConfigHandle);
-                    if(0>rot) {
-                        return null;
-                    }
-                } finally {
-                     freeScreenConfiguration0(screenConfigHandle);
-                }
-                int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
-                int i = 0;
-                props[i++] = 0; // set later for verification of iterator
-                props[i++] = res[0]; // width
-                props[i++] = res[1]; // height
-                props[i++] = default_sm_bpp; // FIXME
-                props[i++] = res[2]; // widthmm
-                props[i++] = res[3]; // heightmm
-                props[i++] = rate;   // rate
-                props[i++] = rot;
-                props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count
-                return ScreenModeUtil.streamIn(props, 0);
+    @Override
+    protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+        if( null == rAndR ) { return null; }
+        
+        return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<MonitorMode>() {
+            public MonitorMode run(long dpy) {
+                final int[] currentModeProps = rAndR.getCurrentMonitorModeProps(dpy, ScreenDriver.this, monitor.getId());
+                return MonitorModeProps.streamInMonitorMode(null, null, currentModeProps, 0);
             } } );
     }
 
-    protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) {
-        final List<ScreenMode> screenModes = this.getScreenModesOrig();
-        final int screenModeIdx = screenModes.indexOf(screenMode);
-        if(0>screenModeIdx) {
-            throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode);
-        }
+    @Override
+    protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+        if( null == rAndR ) { return false; }
+        
         final long t0 = System.currentTimeMillis();
         boolean done = runWithTempDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
             public Boolean run(long dpy) {
-                boolean done = false;
-                long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
-                if(0 == screenConfigHandle) {
-                    return Boolean.valueOf(done);
-                }
-                try {
-                    int resNumber = getNumScreenModeResolutions0(dpy, screen_idx);
-                    int resIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx);
-                    if(0>resIdx || resIdx>=resNumber) {
-                        throw new RuntimeException("Invalid resolution index: ! 0 < "+resIdx+" < "+resNumber+", screenMode["+screenModeIdx+"] "+screenMode);
-                    }
-            
-                    final int f = screenMode.getMonitorMode().getRefreshRate();
-                    final int r = screenMode.getRotation();
-    
-                    if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resIdx, f, r) ) {
-                        while(!done && System.currentTimeMillis()-t0 < SCREEN_MODE_CHANGE_TIMEOUT) {
-                            done = setCurrentScreenModePollEnd0(dpy, screen_idx, resIdx, f, r);
-                            if(!done) {
-                                try { Thread.sleep(10); } catch (InterruptedException e) { }
-                            }
-                        }
-                    }
-                } finally {
-                     freeScreenConfiguration0(screenConfigHandle);
-                }
-                return Boolean.valueOf(done);
+                return Boolean.valueOf( rAndR.setCurrentMonitorMode(dpy, ScreenDriver.this, monitor, mode) );
             }            
         }).booleanValue();
         
         if(DEBUG || !done) {
-            System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+
-                               (System.currentTimeMillis()-t0)+"ms; Current: "+getCurrentScreenMode()+"; Desired: "+screenMode);
+            System.err.println("X11Screen.setCurrentMonitorModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+
+                               (System.currentTimeMillis()-t0)+"ms; "+monitor.getCurrentMode()+" -> "+mode);
         }
         return done;
     }
@@ -281,6 +204,7 @@ public class ScreenDriver extends ScreenImpl {
             return new Boolean(X11Util.XineramaIsEnabled(dpy)); 
         } };
     
+    @Override
     protected int validateScreenIndex(final int idx) {
         final DisplayDriver x11Display = (DisplayDriver) getDisplay();
         final Boolean r = x11Display.isXineramaEnabled();
@@ -291,13 +215,14 @@ public class ScreenDriver extends ScreenImpl {
         }
     }
         
-    protected void getVirtualScreenOriginAndSize(final Point virtualOrigin, final Dimension virtualSize) {
+    @Override
+    protected void calcVirtualScreenOriginAndSize(final Rectangle vOriginSize) {
         runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
             public Object run(long dpy) {
-                virtualOrigin.setX(0);
-                virtualOrigin.setY(0);
-                virtualSize.setWidth(getWidth0(dpy, screen_idx));
-                virtualSize.setHeight(getHeight0(dpy, screen_idx));
+                vOriginSize.setX(0);
+                vOriginSize.setY(0);
+                vOriginSize.setWidth(getWidth0(dpy, screen_idx));
+                vOriginSize.setHeight(getHeight0(dpy, screen_idx));
                 return null;
             } } );        
     }    
@@ -328,25 +253,6 @@ public class ScreenDriver extends ScreenImpl {
     private static native int getWidth0(long display, int scrn_idx);
 
     private static native int getHeight0(long display, int scrn_idx);
-
-    /** @return int[] { rot1, .. } */
-    private static native int[] getAvailableScreenModeRotations0(long display, int screen_index);
-
-    private static native int getNumScreenModeResolutions0(long display, int screen_index);
-
-    /** @return int[] { width, height, widthmm, heightmm } */
-    private static native int[] getScreenModeResolution0(long display, int screen_index, int mode_index);
-
-    private static native int[] getScreenModeRates0(long display, int screen_index, int mode_index);
-
-    private static native long getScreenConfiguration0(long display, int screen_index);
-    private static native void freeScreenConfiguration0(long screenConfiguration);
     
-    private static native int getCurrentScreenResolutionIndex0(long screenConfiguration);
-    private static native int getCurrentScreenRate0(long screenConfiguration);
-    private static native int getCurrentScreenRotation0(long screenConfiguration);
-
-    /** needs own Display connection for XRANDR event handling */
-    private static native boolean setCurrentScreenModeStart0(long display, int screen_index, long screenConfiguration, int mode_index, int freq, int rot);
-    private static native boolean setCurrentScreenModePollEnd0(long display, int screen_index, int mode_index, int freq, int rot);
+    private static native int[] getRandRVersion0(long display);
 }
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
index c21cb4b..786587d 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -47,6 +47,8 @@ import javax.media.nativewindow.util.Point;
 
 import com.jogamp.nativewindow.x11.X11GraphicsDevice;
 import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.KeyEvent;
 import com.jogamp.newt.event.MouseEvent;
 
 public class WindowDriver extends WindowImpl {
@@ -57,7 +59,7 @@ public class WindowDriver extends WindowImpl {
     private static final int X11_WHEEL_TWO_DOWN_BUTTON = 7;
     
     static {
-        DisplayDriver.initSingleton();
+        ScreenDriver.initSingleton();
     }
 
     public WindowDriver() {
@@ -71,7 +73,7 @@ public class WindowDriver extends WindowImpl {
         // Decoupled X11 Device/Screen allowing X11 display lock-free off-thread rendering 
         final long renderDeviceHandle = X11Util.openDisplay(edtDevice.getConnection());
         if( 0 == renderDeviceHandle ) {
-            throw new RuntimeException("Error creating display(EDT): "+edtDevice.getConnection());
+            throw new RuntimeException("Error creating display(GfxCfg/Render): "+edtDevice.getConnection());
         }
         renderDevice = new X11GraphicsDevice(renderDeviceHandle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
         final AbstractGraphicsScreen renderScreen = new X11GraphicsScreen(renderDevice, screen.getIndex());
@@ -114,7 +116,7 @@ public class WindowDriver extends WindowImpl {
             edtDevice.lock();
             try {
                 CloseWindow0(edtDevice.getHandle(), windowHandleClose, 
-                             display.getJavaObjectAtom(), display.getWindowDeleteAtom());
+                             display.getJavaObjectAtom(), display.getWindowDeleteAtom() /* , display.getKbdHandle() */); // XKB disabled for now
             } catch (Throwable t) {
                 if(DEBUG_IMPLEMENTATION) { 
                     Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
@@ -131,16 +133,9 @@ public class WindowDriver extends WindowImpl {
         }
     }
 
-    @Override
-    public long getDisplayHandle() {
-        // Actually: return getGraphicsConfiguration().getScreen().getDevice().getHandle();
-        return renderDevice.getHandle(); // shortcut
-    }
-    
     protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) { 
         if(DEBUG_IMPLEMENTATION) {
-            System.err.println("X11Window reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
-                               getReconfigureFlagsAsString(null, flags));
+            System.err.println("X11Window reconfig: "+x+"/"+y+" "+width+"x"+height+", "+ getReconfigureFlagsAsString(null, flags));
         }
         final int _x, _y;
         if(0 == ( FLAG_IS_UNDECORATED & flags)) {
@@ -231,8 +226,9 @@ public class WindowDriver extends WindowImpl {
         // nop - using event driven insetsChange(..)         
     }
     
-    protected void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers,
-                                int x, int y, int button, int rotation) {
+    @Override
+    protected final void doMouseEvent(boolean enqueue, boolean wait, short eventType, int modifiers,
+                                int x, int y, short button, float[] rotationXYZ, float rotationScale) {
         switch(eventType) {
             case MouseEvent.EVENT_MOUSE_PRESSED:
                 switch(button) {
@@ -245,33 +241,65 @@ public class WindowDriver extends WindowImpl {
                 }
                 break;
             case MouseEvent.EVENT_MOUSE_RELEASED:
+                final boolean shiftPressed = 0 != ( modifiers & InputEvent.SHIFT_MASK );
                 switch(button) {
-                    case X11_WHEEL_ONE_UP_BUTTON:
+                    case X11_WHEEL_ONE_UP_BUTTON: // vertical scroll up
                         eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
                         button = 1;
-                        rotation = 1;
+                        rotationXYZ[shiftPressed ? 0 : 1] = 1;
                         break;
-                    case X11_WHEEL_ONE_DOWN_BUTTON:
+                    case X11_WHEEL_ONE_DOWN_BUTTON: // vertical scroll down
                         eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
                         button = 1;
-                        rotation = -1;
+                        rotationXYZ[shiftPressed ? 0 : 1] = -1;
                         break;
-                    case X11_WHEEL_TWO_UP_BUTTON:
+                    case X11_WHEEL_TWO_UP_BUTTON: // horizontal scroll left
                         eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
-                        button = 2;
-                        rotation = 1;
+                        button = 1;
+                        rotationXYZ[0] = 1;
+                        modifiers |= InputEvent.SHIFT_MASK;
                         break;
-                    case X11_WHEEL_TWO_DOWN_BUTTON:
+                    case X11_WHEEL_TWO_DOWN_BUTTON: // horizontal scroll right
                         eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
-                        button = 2;
-                        rotation = -1;
+                        button = 1;
+                        rotationXYZ[0] = -1;
+                        modifiers |= InputEvent.SHIFT_MASK;
                         break;
                 }                
                 break;
         }
-        super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotation);        
+        super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
     }
     
+    protected final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar0, String keyString) {
+        // handleKeyEvent(true, false, eventType, modifiers, keyCode, keyChar);
+        final boolean isModifierKey = KeyEvent.isModifierKey(keyCode);
+        final boolean isAutoRepeat = 0 != ( KeyEvent.AUTOREPEAT_MASK & modifiers );
+        final char keyChar =  ( null != keyString ) ? keyString.charAt(0) : keyChar0;        
+        // System.err.println("*** sendKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar0+">/<"+keyChar+">, keyString "+keyString+", mods "+toHexString(modifiers)+
+        //                    ", isKeyCodeTracked "+isKeyCodeTracked(keyCode)+", was: pressed "+isKeyPressed(keyCode)+", repeat "+isAutoRepeat+", [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis());
+        
+        if( !isAutoRepeat || !isModifierKey ) { // ! (  isModifierKey && isAutoRepeat )
+            switch(eventType) {
+                case KeyEvent.EVENT_KEY_PRESSED:
+                    super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar);
+                    break;
+                    
+                case KeyEvent.EVENT_KEY_RELEASED:
+                    super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar);
+                    break;
+            }
+        }
+    }
+    
+    @Override
+    public final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+        throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+    }
+    @Override
+    public final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+        throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+    }
     
     //----------------------------------------------------------------------
     // Internals only
@@ -288,7 +316,7 @@ public class WindowDriver extends WindowImpl {
     private native long CreateWindow0(long parentWindowHandle, long display, int screen_index, 
                                       int visualID, long javaObjectAtom, long windowDeleteAtom, 
                                       int x, int y, int width, int height, boolean autoPosition, int flags); 
-    private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom);
+    private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle*/ ); // XKB disabled for now
     private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle,
                                            long windowDeleteAtom, int x, int y, int width, int height, int flags);    
     private native void requestFocus0(long display, long windowHandle, boolean force);
@@ -300,5 +328,5 @@ public class WindowDriver extends WindowImpl {
     private static native void warpPointer0(long display, long windowHandle, int x, int y);
     
     private long   windowHandleClose;
-    private X11GraphicsDevice renderDevice;    
+    private X11GraphicsDevice renderDevice;
 }
diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
similarity index 62%
rename from src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
rename to src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
index d4b83d8..77049a0 100644
--- a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
@@ -25,12 +25,13 @@
  * authors and should not be interpreted as representing official policies, either expressed
  * or implied, of JogAmp Community.
  */
-package com.jogamp.newt.swt;
+package jogamp.newt.swt;
 
-import java.awt.EventQueue;
+import javax.media.nativewindow.NativeWindowException;
 
 import jogamp.newt.Debug;
 
+import com.jogamp.common.util.RunnableTask;
 import com.jogamp.newt.util.EDTUtil;
 
 /**
@@ -80,7 +81,7 @@ public class SWTEDTUtil implements EDTUtil {
         synchronized(edtLock) { 
             waitUntilStopped();
             if(DEBUG) {
-                System.err.println(Thread.currentThread()+": EDT reset - edt: "+nedt);
+                System.err.println(Thread.currentThread()+": SWT-EDT reset - edt: "+nedt);
             }
             this.nedt = new NewtEventDispatchThread(threadGroup, name);
             this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
@@ -89,13 +90,13 @@ public class SWTEDTUtil implements EDTUtil {
 
     private final void startImpl() {
         if(nedt.isAlive()) {
-            throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt);
+            throw new RuntimeException("SWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt);
         }
         start_iter++;
         nedt.setName(name+start_iter);
         nedt.shouldStop = false;
         if(DEBUG) {
-            System.err.println(Thread.currentThread()+": EDT START - edt: "+nedt);
+            System.err.println(Thread.currentThread()+": SWT-EDT START - edt: "+nedt);
             // Thread.dumpStack();
         }
         nedt.start();
@@ -123,8 +124,8 @@ public class SWTEDTUtil implements EDTUtil {
     }
     
     @Override
-    public final void invokeStop(Runnable task) {
-        invokeImpl(true, task, true);
+    public final void invokeStop(boolean wait, Runnable task) {
+        invokeImpl(wait, task, true);
     }
 
     @Override
@@ -133,47 +134,76 @@ public class SWTEDTUtil implements EDTUtil {
     }
     
     private void invokeImpl(boolean wait, Runnable task, boolean stop) {
-        if(task == null) {
-            throw new RuntimeException("Null Runnable");
-        }
-        synchronized(edtLock) { // lock the EDT status
-            if( nedt.shouldStop ) {
-                // drop task ..
-                if(DEBUG) {
-                    System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+nedt);
-                    Thread.dumpStack();
+        Throwable throwable = null;
+        RunnableTask rTask = null;
+        Object rTaskLock = new Object();
+        synchronized(rTaskLock) { // lock the optional task execution
+            synchronized(edtLock) { // lock the EDT status
+                if( nedt.shouldStop ) {
+                    // drop task ..
+                    if(DEBUG) {
+                        System.err.println(Thread.currentThread()+": Warning: SWT-EDT about (1) to stop, won't enqueue new task: "+nedt);
+                        Thread.dumpStack();
+                    }
+                    return; 
                 }
-                return; 
-            }
-            // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
-            // Thread.dumpStack();
-            if(stop) {
-                nedt.shouldStop = true;
-                if(DEBUG) {
-                    System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt);
-                    // Thread.dumpStack();
+                // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
+                // Thread.dumpStack();
+                if(stop) {
+                    synchronized(nedt.sync) {
+                        nedt.shouldStop = true;
+                        nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
+                    }
+                    if(DEBUG) {
+                        System.err.println(Thread.currentThread()+": SWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt);
+                        // Thread.dumpStack();
+                    }
+                } else if( !nedt.isRunning() ) {
+                    // start if should not stop && not started yet
+                    startImpl();
+                }
+                if( null == task ) {
+                    wait = false;
+                } else if( isCurrentThreadEDT() ) {
+                    task.run();
+                    wait = false; // running in same thread (EDT) -> no wait
+                } else if( swtDisplay.isDisposed() ) {
+                    wait = false; // drop task, SWT disposed 
+                } else {
+                    rTask = new RunnableTask(task,
+                                             wait ? rTaskLock : null,
+                                             true /* always catch and report Exceptions, don't disturb EDT */, 
+                                             wait ? null : System.err);
+                    swtDisplay.asyncExec(rTask);
                 }
             }
-            
-            // start if should not stop && not started yet                    
-            if( !stop && !nedt.isRunning() ) {
-                startImpl();
+            if( wait ) {
+                try {
+                    rTaskLock.wait(); // free lock, allow execution of rTask
+                } catch (InterruptedException ie) {
+                    throwable = ie;
+                }
+                if(null==throwable) {
+                    throwable = rTask.getThrowable();
+                }
+                if(null!=throwable) {
+                    if(throwable instanceof NativeWindowException) {
+                        throw (NativeWindowException)throwable;
+                    }
+                    throw new RuntimeException(throwable);
+                }
             }
         }
-        if(wait) {
-            swtDisplay.syncExec(task);
-        } else {
-            swtDisplay.asyncExec(task);
-        }
     }    
 
     @Override
     final public void waitUntilIdle() {
-        final NewtEventDispatchThread _edt;
+        final NewtEventDispatchThread _nedt;
         synchronized(edtLock) {
-            _edt = nedt;
+            _nedt = nedt;
         }
-        if(!_edt.isRunning() || EventQueue.isDispatchThread()  || _edt == Thread.currentThread()) {
+        final Thread ct = Thread.currentThread();
+        if(!_nedt.isRunning() || _nedt == ct || swtDisplay.getThread() == ct) {
             return;
         }
         try {
@@ -186,7 +216,8 @@ public class SWTEDTUtil implements EDTUtil {
     @Override
     final public void waitUntilStopped() {
         synchronized(edtLock) {
-            if(nedt.isRunning() && nedt != Thread.currentThread() ) {
+            final Thread ct = Thread.currentThread();
+            if(nedt.isRunning() && nedt != ct && swtDisplay.getThread() != ct) {
                 while(nedt.isRunning()) {
                     try {
                         edtLock.wait();
@@ -224,19 +255,22 @@ public class SWTEDTUtil implements EDTUtil {
         @Override
         final public void run() {
             if(DEBUG) {
-                System.err.println(getName()+": EDT run() START "+ getName());
+                System.err.println(getName()+": SWT-EDT run() START "+ getName());
             }
             RuntimeException error = null;
             try {
                 do {
                     // event dispatch
                     if(!shouldStop) {
-                        // FIXME: Determine whether we require to run the 
-                        // delivery of events (dispatch) on AWT-EDT.
-                        // Since the WindowDriver itself delivers all Window related events,
-                        // this shall not be required.
-                        //   AWTEDTExecutor.singleton.invoke(true, dispatchMessages);
-                        dispatchMessages.run();
+                        // EDT invoke thread is SWT-EDT,
+                        // hence dispatching is required to run on SWT-EDT as well.
+                        // Otherwise a deadlock may happen due to dispatched event's
+                        // triggering a locking action.                        
+                        if ( !swtDisplay.isDisposed() ) {
+                            swtDisplay.syncExec(dispatchMessages);
+                        } else {
+                            dispatchMessages.run();
+                        }
                     }
                     // wait
                     synchronized(sync) {
@@ -255,11 +289,11 @@ public class SWTEDTUtil implements EDTUtil {
                 if(t instanceof RuntimeException) {
                     error = (RuntimeException) t;
                 } else {
-                    error = new RuntimeException("Within EDT", t);
+                    error = new RuntimeException("Within SWT-EDT", t);
                 }
             } finally {
                 if(DEBUG) {
-                    System.err.println(getName()+": EDT run() END "+ getName()+", "+error); 
+                    System.err.println(getName()+": SWT-EDT run() END "+ getName()+", "+error); 
                 }
                 synchronized(edtLock) {
                     isRunning = !shouldStop;
@@ -268,7 +302,7 @@ public class SWTEDTUtil implements EDTUtil {
                     }
                 }
                 if(DEBUG) {
-                    System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error);
+                    System.err.println(getName()+": SWT-EDT run() EXIT "+ getName()+", exception: "+error);
                 }
                 if(null!=error) {
                     throw error;
diff --git a/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java b/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
new file mode 100644
index 0000000..3782a11
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
@@ -0,0 +1,375 @@
+/**
+ * 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 jogamp.newt.swt.event;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.MouseEvent;
+
+/**
+ * SWT event translator to NEWT, inclusive dispatch listener.
+ * <p>
+ * <b>Disclaimer:</b> This code is merely tested and subject to change.
+ * </p>
+ */
+public class SWTNewtEventFactory {
+
+    public static final short eventTypeSWT2NEWT(int swtType) {
+        switch( swtType ) {
+            // case SWT.MouseXXX: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED;
+            case SWT.MouseDown: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED;
+            case SWT.MouseUp: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED;
+            case SWT.MouseMove: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED;
+            case SWT.MouseEnter: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED;
+            case SWT.MouseExit: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED;
+            // case SWT.MouseXXX: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED;
+            case SWT.MouseVerticalWheel: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+
+            case SWT.KeyDown: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
+            case SWT.KeyUp: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
+        }
+        return (short)0;
+    }
+
+    public static final int swtModifiers2Newt(int awtMods, boolean mouseHint) {
+        int newtMods = 0;
+        if ((awtMods & SWT.SHIFT) != 0)     newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+        if ((awtMods & SWT.CTRL) != 0)      newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK;
+        if ((awtMods & SWT.ALT) != 0)      newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
+        return newtMods;
+    }
+
+    public static short swtKeyCode2NewtKeyCode(final int swtKeyCode) {
+        final short defNEWTKeyCode = (short)swtKeyCode;
+        switch (swtKeyCode) {
+            case SWT.HOME          : return com.jogamp.newt.event.KeyEvent.VK_HOME;
+            case SWT.END           : return com.jogamp.newt.event.KeyEvent.VK_END;
+            case SWT.PRINT_SCREEN  : return com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN;
+            case SWT.BS            : return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
+            case SWT.TAB           : return com.jogamp.newt.event.KeyEvent.VK_TAB;
+            case SWT.LF            : return com.jogamp.newt.event.KeyEvent.VK_ENTER;
+            case SWT.PAGE_DOWN     : return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN;
+            case SWT.PAGE_UP       : return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP;
+            case SWT.CONTROL       : return com.jogamp.newt.event.KeyEvent.VK_CONTROL;
+            case SWT.CAPS_LOCK     : return com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK;
+            case SWT.PAUSE         : return com.jogamp.newt.event.KeyEvent.VK_PAUSE;
+            case SWT.SCROLL_LOCK   : return com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK;
+            case SWT.CANCEL        : return com.jogamp.newt.event.KeyEvent.VK_CANCEL;
+            case SWT.INSERT        : return com.jogamp.newt.event.KeyEvent.VK_INSERT;
+            case SWT.ESC           : return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
+            case SWT.SPACE         : return com.jogamp.newt.event.KeyEvent.VK_SPACE;
+            case SWT.F1            : return com.jogamp.newt.event.KeyEvent.VK_F1;
+            case SWT.F2            : return com.jogamp.newt.event.KeyEvent.VK_F2;
+            case SWT.F3            : return com.jogamp.newt.event.KeyEvent.VK_F3;
+            case SWT.F4            : return com.jogamp.newt.event.KeyEvent.VK_F4;
+            case SWT.F5            : return com.jogamp.newt.event.KeyEvent.VK_F5;
+            case SWT.F6            : return com.jogamp.newt.event.KeyEvent.VK_F6;
+            case SWT.F7            : return com.jogamp.newt.event.KeyEvent.VK_F7;
+            case SWT.F8            : return com.jogamp.newt.event.KeyEvent.VK_F8;
+            case SWT.F9            : return com.jogamp.newt.event.KeyEvent.VK_F9;
+            case SWT.F10           : return com.jogamp.newt.event.KeyEvent.VK_F10;
+            case SWT.F11           : return com.jogamp.newt.event.KeyEvent.VK_F11;
+            case SWT.F12           : return com.jogamp.newt.event.KeyEvent.VK_F12;
+            case SWT.F13           : return com.jogamp.newt.event.KeyEvent.VK_F13;
+            case SWT.F14           : return com.jogamp.newt.event.KeyEvent.VK_F14;
+            case SWT.F15           : return com.jogamp.newt.event.KeyEvent.VK_F15;
+            case SWT.F16           : return com.jogamp.newt.event.KeyEvent.VK_F16;
+            case SWT.F17           : return com.jogamp.newt.event.KeyEvent.VK_F17;
+            case SWT.F18           : return com.jogamp.newt.event.KeyEvent.VK_F18;
+            case SWT.F19           : return com.jogamp.newt.event.KeyEvent.VK_F19;
+            case SWT.F20           : return com.jogamp.newt.event.KeyEvent.VK_F20;
+            case SWT.DEL           : return com.jogamp.newt.event.KeyEvent.VK_DELETE;
+            case SWT.KEYPAD_0      : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD0;
+            case SWT.KEYPAD_1      : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD1;
+            case SWT.KEYPAD_2      : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD2;
+            case SWT.KEYPAD_3      : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD3;
+            case SWT.KEYPAD_4      : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD4;
+            case SWT.KEYPAD_5      : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD5;
+            case SWT.KEYPAD_6      : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD6;
+            case SWT.KEYPAD_7      : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD7;
+            case SWT.KEYPAD_8      : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD8;
+            case SWT.KEYPAD_9      : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD9;
+            case SWT.KEYPAD_DECIMAL: return com.jogamp.newt.event.KeyEvent.VK_DECIMAL;
+            case SWT.KEYPAD_ADD    : return com.jogamp.newt.event.KeyEvent.VK_ADD;
+            case SWT.KEYPAD_SUBTRACT: return com.jogamp.newt.event.KeyEvent.VK_SUBTRACT;
+            case SWT.KEYPAD_MULTIPLY: return com.jogamp.newt.event.KeyEvent.VK_MULTIPLY;
+            case SWT.KEYPAD_DIVIDE : return com.jogamp.newt.event.KeyEvent.VK_DIVIDE;
+            case SWT.NUM_LOCK      : return com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK;
+            case SWT.ARROW_LEFT    : return com.jogamp.newt.event.KeyEvent.VK_LEFT;
+            case SWT.ARROW_UP      : return com.jogamp.newt.event.KeyEvent.VK_UP;
+            case SWT.ARROW_RIGHT   : return com.jogamp.newt.event.KeyEvent.VK_RIGHT;
+            case SWT.ARROW_DOWN    : return com.jogamp.newt.event.KeyEvent.VK_DOWN;
+            case SWT.HELP          : return com.jogamp.newt.event.KeyEvent.VK_HELP;
+        }
+        return defNEWTKeyCode;
+    }
+
+    public static int newtKeyCode2SWTKeyCode(final short newtKeyCode) {
+        final int defSWTKeyCode = 0xFFFF & (int)newtKeyCode;
+        switch (newtKeyCode) {
+            case com.jogamp.newt.event.KeyEvent.VK_HOME          : return SWT.HOME;
+            case com.jogamp.newt.event.KeyEvent.VK_END           : return SWT.END;
+            case com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN   : return SWT.PRINT_SCREEN;
+            case com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE    : return SWT.BS;
+            case com.jogamp.newt.event.KeyEvent.VK_TAB           : return SWT.TAB;
+            case com.jogamp.newt.event.KeyEvent.VK_ENTER         : return SWT.LF;
+            case com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN     : return SWT.PAGE_DOWN;
+            case com.jogamp.newt.event.KeyEvent.VK_PAGE_UP       : return SWT.PAGE_UP;
+            case com.jogamp.newt.event.KeyEvent.VK_CONTROL       : return SWT.CONTROL;
+            case com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK     : return SWT.CAPS_LOCK;
+            case com.jogamp.newt.event.KeyEvent.VK_PAUSE         : return SWT.PAUSE;
+            case com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK   : return SWT.SCROLL_LOCK;
+            case com.jogamp.newt.event.KeyEvent.VK_CANCEL        : return SWT.CANCEL;
+            case com.jogamp.newt.event.KeyEvent.VK_INSERT        : return SWT.INSERT;
+            case com.jogamp.newt.event.KeyEvent.VK_ESCAPE        : return SWT.ESC;
+            case com.jogamp.newt.event.KeyEvent.VK_SPACE         : return SWT.SPACE;
+            case com.jogamp.newt.event.KeyEvent.VK_F1            : return SWT.F1;
+            case com.jogamp.newt.event.KeyEvent.VK_F2            : return SWT.F2;
+            case com.jogamp.newt.event.KeyEvent.VK_F3            : return SWT.F3;
+            case com.jogamp.newt.event.KeyEvent.VK_F4            : return SWT.F4;
+            case com.jogamp.newt.event.KeyEvent.VK_F5            : return SWT.F5;
+            case com.jogamp.newt.event.KeyEvent.VK_F6            : return SWT.F6;
+            case com.jogamp.newt.event.KeyEvent.VK_F7            : return SWT.F7;
+            case com.jogamp.newt.event.KeyEvent.VK_F8            : return SWT.F8;
+            case com.jogamp.newt.event.KeyEvent.VK_F9            : return SWT.F9;
+            case com.jogamp.newt.event.KeyEvent.VK_F10           : return SWT.F10;
+            case com.jogamp.newt.event.KeyEvent.VK_F11           : return SWT.F11;
+            case com.jogamp.newt.event.KeyEvent.VK_F12           : return SWT.F12;
+            case com.jogamp.newt.event.KeyEvent.VK_F13           : return SWT.F13;
+            case com.jogamp.newt.event.KeyEvent.VK_F14           : return SWT.F14;
+            case com.jogamp.newt.event.KeyEvent.VK_F15           : return SWT.F15;
+            case com.jogamp.newt.event.KeyEvent.VK_F16           : return SWT.F16;
+            case com.jogamp.newt.event.KeyEvent.VK_F17           : return SWT.F17;
+            case com.jogamp.newt.event.KeyEvent.VK_F18           : return SWT.F18;
+            case com.jogamp.newt.event.KeyEvent.VK_F19           : return SWT.F19;
+            case com.jogamp.newt.event.KeyEvent.VK_F20           : return SWT.F20;
+            case com.jogamp.newt.event.KeyEvent.VK_DELETE        : return SWT.DEL;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD0       : return SWT.KEYPAD_0;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD1       : return SWT.KEYPAD_1;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD2       : return SWT.KEYPAD_2;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD3       : return SWT.KEYPAD_3;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD4       : return SWT.KEYPAD_4;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD5       : return SWT.KEYPAD_5;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD6       : return SWT.KEYPAD_6;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD7       : return SWT.KEYPAD_7;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD8       : return SWT.KEYPAD_8;
+            case com.jogamp.newt.event.KeyEvent.VK_NUMPAD9       : return SWT.KEYPAD_9;
+            case com.jogamp.newt.event.KeyEvent.VK_DECIMAL       : return SWT.KEYPAD_DECIMAL;
+            case com.jogamp.newt.event.KeyEvent.VK_ADD           : return SWT.KEYPAD_ADD;
+            case com.jogamp.newt.event.KeyEvent.VK_SUBTRACT      : return SWT.KEYPAD_SUBTRACT;
+            case com.jogamp.newt.event.KeyEvent.VK_MULTIPLY      : return SWT.KEYPAD_MULTIPLY;
+            case com.jogamp.newt.event.KeyEvent.VK_DIVIDE        : return SWT.KEYPAD_DIVIDE;
+            case com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK      : return SWT.NUM_LOCK;
+            case com.jogamp.newt.event.KeyEvent.VK_LEFT          : return SWT.ARROW_LEFT;
+            case com.jogamp.newt.event.KeyEvent.VK_UP            : return SWT.ARROW_UP;
+            case com.jogamp.newt.event.KeyEvent.VK_RIGHT         : return SWT.ARROW_RIGHT;
+            case com.jogamp.newt.event.KeyEvent.VK_DOWN          : return SWT.ARROW_DOWN;
+            case com.jogamp.newt.event.KeyEvent.VK_HELP          : return SWT.HELP;
+        }
+        return defSWTKeyCode;
+    }
+
+
+    public static final com.jogamp.newt.event.InputEvent createInputEvent(org.eclipse.swt.widgets.Event event, Object source) {
+        com.jogamp.newt.event.InputEvent res = createMouseEvent(event, source);
+        if(null == res) {
+            res = createKeyEvent(event, source);
+        }
+        return res;
+    }
+    
+    public static final com.jogamp.newt.event.MouseEvent createMouseEvent(org.eclipse.swt.widgets.Event event, Object source) {
+        switch(event.type) {
+            case SWT.MouseDown:
+            case SWT.MouseUp:
+            case SWT.MouseMove:
+            case SWT.MouseEnter:
+            case SWT.MouseExit:
+            case SWT.MouseVerticalWheel:
+                break;
+            default:
+                return null;
+        }
+        final short type = eventTypeSWT2NEWT(event.type);
+        if( (short)0 != type ) {
+            float rotation = 0;
+            if (SWT.MouseVerticalWheel == event.type) {
+                // SWT/NEWT rotation is reversed - AWT +1 is down, NEWT +1 is up.
+                // rotation = -1 * (int) event.rotation;
+                rotation = (float) event.rotation;
+            }
+
+            int mods = swtModifiers2Newt(event.stateMask, true);
+            
+            if( source instanceof com.jogamp.newt.Window) {
+                final com.jogamp.newt.Window newtSource = (com.jogamp.newt.Window)source;
+                if(newtSource.isPointerConfined()) {
+                    mods |= InputEvent.CONFINED_MASK;
+                }
+                if(!newtSource.isPointerVisible()) {
+                    mods |= InputEvent.INVISIBLE_MASK;
+                }
+            }
+            
+            return new com.jogamp.newt.event.MouseEvent(
+                           type, (null==source)?(Object)event.data:source, (0xFFFFFFFFL & (long)event.time),
+                           mods, event.x, event.y, (short)event.count, (short)event.button, MouseEvent.getRotationXYZ(rotation, mods), 1f);
+        }
+        return null; // no mapping ..
+    }
+
+    public static final com.jogamp.newt.event.KeyEvent createKeyEvent(org.eclipse.swt.widgets.Event event, Object source) {
+        switch(event.type) {
+            case SWT.KeyDown:
+            case SWT.KeyUp:
+                break;
+            default:
+                return null;
+        }
+        final short type = eventTypeSWT2NEWT(event.type);
+        if( (short)0 != type ) {
+            final short newtKeyCode = swtKeyCode2NewtKeyCode( event.keyCode );
+            return com.jogamp.newt.event.KeyEvent.create(
+                           type, (null==source)?(Object)event.data:source, (0xFFFFFFFFL & (long)event.time),
+                           swtModifiers2Newt(event.stateMask, false), 
+                           newtKeyCode, newtKeyCode, event.character);
+        }
+        return null; // no mapping ..
+    }
+    
+    //
+    //
+    //
+    
+    short dragButtonDown = 0;
+    
+    public SWTNewtEventFactory() {
+        resetButtonsDown();
+    }
+    
+    final void resetButtonsDown() {
+        dragButtonDown = 0;
+    }
+    
+    public final boolean dispatchMouseEvent(org.eclipse.swt.widgets.Event event, Object source, com.jogamp.newt.event.MouseListener l) {
+        com.jogamp.newt.event.MouseEvent res = createMouseEvent(event, source);
+        if(null != res) {
+            if(null != l) {
+                switch(event.type) {
+                    case SWT.MouseDown:               
+                        dragButtonDown = (short) event.button;
+                        l.mousePressed(res); break;
+                    case SWT.MouseUp:
+                        dragButtonDown = 0;
+                        l.mouseReleased(res);
+                        {
+                            final com.jogamp.newt.event.MouseEvent res2 = new com.jogamp.newt.event.MouseEvent(
+                                           com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED, 
+                                           res.getSource(),
+                                           res.getWhen(), res.getModifiers(),
+                                           res.getX(), res.getY(), res.getClickCount(),
+                                           res.getButton(), res.getRotation(), res.getRotationScale());
+                            l.mouseClicked(res2);
+                        }
+                        break;
+                    case SWT.MouseMove:
+                        if( 0 < dragButtonDown ) {
+                            final com.jogamp.newt.event.MouseEvent res2 = new com.jogamp.newt.event.MouseEvent(
+                                           com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED, 
+                                           res.getSource(),
+                                           res.getWhen(), res.getModifiers(),
+                                           res.getX(), res.getY(), res.getClickCount(),
+                                           dragButtonDown, res.getRotation(), res.getRotationScale());
+                            l.mouseDragged( res2 );
+                        } else {
+                            l.mouseMoved(res);
+                        }
+                        break;
+                    case SWT.MouseEnter:
+                        l.mouseEntered(res); 
+                        break;
+                    case SWT.MouseExit:
+                        resetButtonsDown();
+                        l.mouseExited(res); 
+                        break;
+                    case SWT.MouseVerticalWheel:
+                        l.mouseWheelMoved(res); 
+                        break;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public final boolean dispatchKeyEvent(org.eclipse.swt.widgets.Event event, Object source, com.jogamp.newt.event.KeyListener l) {
+        com.jogamp.newt.event.KeyEvent res = createKeyEvent(event, source);
+        if(null != res) {
+            if(null != l) {
+                switch(event.type) {
+                    case SWT.KeyDown:
+                        l.keyPressed(res); 
+                        break;
+                    case SWT.KeyUp:
+                        l.keyReleased(res);
+                        break;
+                }
+            }
+            return true;
+        }
+        return false;
+    }  
+    
+    public final void attachDispatchListener(final org.eclipse.swt.widgets.Control ctrl, final Object source, 
+                                             final com.jogamp.newt.event.MouseListener ml,
+                                             final com.jogamp.newt.event.KeyListener kl) {
+      final Listener listener = new Listener () {
+          @Override
+          public void handleEvent (Event event) {
+              if( dispatchMouseEvent( event, source, ml ) ) {
+                  return;
+              }
+              if( dispatchKeyEvent( event, source, kl ) ) {
+                  return;
+              }
+          } };
+      ctrl.addListener(SWT.MouseDown, listener);
+      ctrl.addListener(SWT.MouseUp, listener);
+      ctrl.addListener(SWT.MouseMove, listener);
+      ctrl.addListener(SWT.MouseEnter, listener);
+      ctrl.addListener(SWT.MouseExit, listener);
+      ctrl.addListener(SWT.MouseVerticalWheel, listener);
+      ctrl.addListener(SWT.KeyDown, listener);
+      ctrl.addListener(SWT.KeyUp, listener);
+    }
+}
+
diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c
index f1d6aec..cfec60d 100644
--- a/src/newt/native/KDWindow.c
+++ b/src/newt/native/KDWindow.c
@@ -161,14 +161,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages
                     if(KD_INPUT_POINTER_SELECT==ptr->index) {
                         DBG_PRINT( "event mouse click: src: %p, s:%d, (%d,%d)\n", userData, ptr->select, ptr->x, ptr->y);
                         (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, 
-                                              (ptr->select==0) ? (jint) EVENT_MOUSE_RELEASED : (jint) EVENT_MOUSE_PRESSED, 
+                                              (ptr->select==0) ? (jshort) EVENT_MOUSE_RELEASED : (jshort) EVENT_MOUSE_PRESSED, 
                                               (jint) 0,
-                                              (jint) ptr->x, (jint) ptr->y, 1, 0);
+                                              (jint) ptr->x, (jint) ptr->y, (short)1, 0.0f);
                     } else {
                         DBG_PRINT( "event mouse: src: %d, s:%p, i:0x%X (%d,%d)\n", userData, ptr->select, ptr->index, ptr->x, ptr->y);
-                        (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, 
+                        (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, 
                                               0,
-                                              (jint) ptr->x, (jint) ptr->y, 0, 0);
+                                              (jint) ptr->x, (jint) ptr->y, (jshort)0, 0.0f);
                     }
                 }
                 break;
@@ -193,8 +193,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_WindowDriver_initIDs
     sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
     visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
     windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
-    sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
-    sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+    sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V");
+    sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V");
     if (windowCreatedID == NULL ||
         sizeChangedID == NULL ||
         visibleChangedID == NULL ||
diff --git a/src/newt/native/KeyEvent.h b/src/newt/native/KeyEvent.h
index 0f7b160..59977d5 100644
--- a/src/newt/native/KeyEvent.h
+++ b/src/newt/native/KeyEvent.h
@@ -31,197 +31,203 @@
 
 #define EVENT_KEY_PRESSED  300
 #define EVENT_KEY_RELEASED 301
-#define EVENT_KEY_TYPED 302
-
-#define J_CHAR_UNDEFINED 0xFFFF;
-#define J_VK_ENTER          '\n'
-#define J_VK_BACK_SPACE     '\b'
-#define J_VK_TAB            '\t'
-#define J_VK_CANCEL         0x03
-#define J_VK_CLEAR          0x0C
-#define J_VK_SHIFT          0x10
-#define J_VK_CONTROL        0x11
-#define J_VK_ALT            0x12
-#define J_VK_PAUSE          0x13
-#define J_VK_CAPS_LOCK      0x14
-#define J_VK_ESCAPE         0x1B
-#define J_VK_SPACE          0x20
-#define J_VK_PAGE_UP        0x21
-#define J_VK_PAGE_DOWN      0x22
-#define J_VK_END            0x23
-#define J_VK_HOME           0x24
-#define J_VK_LEFT           0x25
-#define J_VK_UP             0x26
-#define J_VK_RIGHT          0x27
-#define J_VK_DOWN           0x28
-#define J_VK_COMMA          0x2C
-#define J_VK_MINUS          0x2D
-#define J_VK_PERIOD         0x2E
-#define J_VK_SLASH          0x2F
-#define J_VK_0              0x30
-#define J_VK_1              0x31
-#define J_VK_2              0x32
-#define J_VK_3              0x33
-#define J_VK_4              0x34
-#define J_VK_5              0x35
-#define J_VK_6              0x36
-#define J_VK_7              0x37
-#define J_VK_8              0x38
-#define J_VK_9              0x39
-#define J_VK_SEMICOLON      0x3B
-#define J_VK_EQUALS         0x3D
-#define J_VK_A              0x41
-#define J_VK_B              0x42
-#define J_VK_C              0x43
-#define J_VK_D              0x44
-#define J_VK_E              0x45
-#define J_VK_F              0x46
-#define J_VK_G              0x47
-#define J_VK_H              0x48
-#define J_VK_I              0x49
-#define J_VK_J              0x4A
-#define J_VK_K              0x4B
-#define J_VK_L              0x4C
-#define J_VK_M              0x4D
-#define J_VK_N              0x4E
-#define J_VK_O              0x4F
-#define J_VK_P              0x50
-#define J_VK_Q              0x51
-#define J_VK_R              0x52
-#define J_VK_S              0x53
-#define J_VK_T              0x54
-#define J_VK_U              0x55
-#define J_VK_V              0x56
-#define J_VK_W              0x57
-#define J_VK_X              0x58
-#define J_VK_Y              0x59
-#define J_VK_Z              0x5A
-#define J_VK_OPEN_BRACKET   0x5B
-#define J_VK_BACK_SLASH     0x5C
-#define J_VK_CLOSE_BRACKET  0x5D
-#define J_VK_NUMPAD0        0x60
-#define J_VK_NUMPAD1        0x61
-#define J_VK_NUMPAD2        0x62
-#define J_VK_NUMPAD3        0x63
-#define J_VK_NUMPAD4        0x64
-#define J_VK_NUMPAD5        0x65
-#define J_VK_NUMPAD6        0x66
-#define J_VK_NUMPAD7        0x67
-#define J_VK_NUMPAD8        0x68
-#define J_VK_NUMPAD9        0x69
-#define J_VK_MULTIPLY       0x6A
-#define J_VK_ADD            0x6B
-#define J_VK_SEPARATOR      0x6C
-#define J_VK_SUBTRACT       0x6D
-#define J_VK_DECIMAL        0x6E
-#define J_VK_DIVIDE         0x6F
-#define J_VK_DELETE         0x7F /* ASCII DEL */
-#define J_VK_NUM_LOCK       0x90
-#define J_VK_SCROLL_LOCK    0x91
-#define J_VK_F1             0x70
-#define J_VK_F2             0x71
-#define J_VK_F3             0x72
-#define J_VK_F4             0x73
-#define J_VK_F5             0x74
-#define J_VK_F6             0x75
-#define J_VK_F7             0x76
-#define J_VK_F8             0x77
-#define J_VK_F9             0x78
-#define J_VK_F10            0x79
-#define J_VK_F11            0x7A
-#define J_VK_F12            0x7B
-#define J_VK_F13            0xF000
-#define J_VK_F14            0xF001
-#define J_VK_F15            0xF002
-#define J_VK_F16            0xF003
-#define J_VK_F17            0xF004
-#define J_VK_F18            0xF005
-#define J_VK_F19            0xF006
-#define J_VK_F20            0xF007
-#define J_VK_F21            0xF008
-#define J_VK_F22            0xF009
-#define J_VK_F23            0xF00A
-#define J_VK_F24            0xF00B
-#define J_VK_PRINTSCREEN    0x9A
-#define J_VK_INSERT         0x9B
-#define J_VK_HELP           0x9C
-#define J_VK_META           0x9D
-#define J_VK_BACK_QUOTE     0xC0
-#define J_VK_QUOTE          0xDE
-#define J_VK_KP_UP          0xE0
-#define J_VK_KP_DOWN        0xE1
-#define J_VK_KP_LEFT        0xE2
-#define J_VK_KP_RIGHT       0xE3
-#define J_VK_DEAD_GRAVE               0x80
-#define J_VK_DEAD_ACUTE               0x81
-#define J_VK_DEAD_CIRCUMFLEX          0x82
-#define J_VK_DEAD_TILDE               0x83
-#define J_VK_DEAD_MACRON              0x84
-#define J_VK_DEAD_BREVE               0x85
-#define J_VK_DEAD_ABOVEDOT            0x86
-#define J_VK_DEAD_DIAERESIS           0x87
-#define J_VK_DEAD_ABOVERING           0x88
-#define J_VK_DEAD_DOUBLEACUTE         0x89
-#define J_VK_DEAD_CARON               0x8a
-#define J_VK_DEAD_CEDILLA             0x8b
-#define J_VK_DEAD_OGONEK              0x8c
-#define J_VK_DEAD_IOTA                0x8d
-#define J_VK_DEAD_VOICED_SOUND        0x8e
-#define J_VK_DEAD_SEMIVOICED_SOUND    0x8f
-#define J_VK_AMPERSAND                0x96
-#define J_VK_ASTERISK                 0x97
-#define J_VK_QUOTEDBL                 0x98
-#define J_VK_LESS                     0x99
-#define J_VK_GREATER                  0xa0
-#define J_VK_BRACELEFT                0xa1
-#define J_VK_BRACERIGHT               0xa2
-#define J_VK_AT                       0x0200
-#define J_VK_COLON                    0x0201
-#define J_VK_CIRCUMFLEX               0x0202
-#define J_VK_DOLLAR                   0x0203
-#define J_VK_EURO_SIGN                0x0204
-#define J_VK_EXCLAMATION_MARK         0x0205
-#define J_VK_INVERTED_EXCLAMATION_MARK 0x0206
-#define J_VK_LEFT_PARENTHESIS         0x0207
-#define J_VK_NUMBER_SIGN              0x0208
-#define J_VK_PLUS                     0x0209
-#define J_VK_RIGHT_PARENTHESIS        0x020A
-#define J_VK_UNDERSCORE               0x020B
-#define J_VK_WINDOWS                  0x020C
-#define J_VK_CONTEXT_MENU             0x020D
-#define J_VK_FINAL                    0x0018
-#define J_VK_CONVERT                  0x001C
-#define J_VK_NONCONVERT               0x001D
-#define J_VK_ACCEPT                   0x001E
-#define J_VK_MODECHANGE               0x001F
-#define J_VK_KANA                     0x0015
-#define J_VK_KANJI                    0x0019
-#define J_VK_ALPHANUMERIC             0x00F0
-#define J_VK_KATAKANA                 0x00F1
-#define J_VK_HIRAGANA                 0x00F2
-#define J_VK_FULL_WIDTH               0x00F3
-#define J_VK_HALF_WIDTH               0x00F4
-#define J_VK_ROMAN_CHARACTERS         0x00F5
-#define J_VK_ALL_CANDIDATES           0x0100
-#define J_VK_PREVIOUS_CANDIDATE       0x0101
-#define J_VK_CODE_INPUT               0x0102
-#define J_VK_JAPANESE_KATAKANA        0x0103
-#define J_VK_JAPANESE_HIRAGANA        0x0104
-#define J_VK_JAPANESE_ROMAN           0x0105
-#define J_VK_KANA_LOCK                0x0106
-#define J_VK_INPUT_METHOD_ON_OFF      0x0107
-#define J_VK_CUT                      0xFFD1
-#define J_VK_COPY                     0xFFCD
-#define J_VK_PASTE                    0xFFCF
-#define J_VK_UNDO                     0xFFCB
-#define J_VK_AGAIN                    0xFFC9
-#define J_VK_FIND                     0xFFD0
-#define J_VK_PROPS                    0xFFCA
-#define J_VK_STOP                     0xFFC8
-#define J_VK_COMPOSE                  0xFF20
-#define J_VK_ALT_GRAPH                0xFF7E
-#define J_VK_BEGIN                    0xFF58
-#define J_VK_UNDEFINED      0x0
+
+#define J_VK_UNDEFINED      ( 0x0U )
+#define J_VK_HOME           ( 0x02U )
+#define J_VK_END            ( 0x03U )
+#define J_VK_FINAL          ( 0x04U )
+#define J_VK_PRINTSCREEN    ( 0x05U )
+#define J_VK_BACK_SPACE     ( 0x08U )
+#define J_VK_TAB            ( 0x09U )
+#define J_VK_ENTER          ( 0x0AU )
+#define J_VK_PAGE_DOWN      ( 0x0BU )
+#define J_VK_CLEAR          ( 0x0CU )
+#define J_VK_SHIFT          ( 0x0FU )
+#define J_VK_PAGE_UP        ( 0x10U )
+#define J_VK_CONTROL        ( 0x11U )
+#define J_VK_ALT            ( 0x12U )
+#define J_VK_ALT_GRAPH      ( 0x13U )
+#define J_VK_CAPS_LOCK      ( 0x14U )
+#define J_VK_PAUSE          ( 0x16U )
+#define J_VK_SCROLL_LOCK    ( 0x17U )
+#define J_VK_CANCEL         ( 0x18U )
+#define J_VK_INSERT         ( 0x1AU )
+#define J_VK_ESCAPE         ( 0x1BU )
+#define J_VK_CONVERT        ( 0x1CU )
+#define J_VK_NONCONVERT     ( 0x1DU )
+#define J_VK_ACCEPT         ( 0x1EU )
+#define J_VK_MODECHANGE     ( 0x1FU )
+
+//
+// Unicode: Printable [0x20 - 0x7E]
+//
+
+#define J_VK_SPACE          ( 0x20U )
+#define J_VK_EXCLAMATION_MARK ( 0x21U )
+#define J_VK_QUOTEDBL       ( 0x22U )
+#define J_VK_NUMBER_SIGN    ( 0x23U )
+#define J_VK_DOLLAR         ( 0x24U )
+#define J_VK_PERCENT        ( 0x25U )
+#define J_VK_AMPERSAND      ( 0x26U )
+#define J_VK_QUOTE          ( 0x27U )
+#define J_VK_LEFT_PARENTHESIS  ( 0x28U )
+#define J_VK_RIGHT_PARENTHESIS ( 0x29U )
+#define J_VK_ASTERISK       ( 0x2AU )
+#define J_VK_PLUS           ( 0x2BU )
+#define J_VK_COMMA          ( 0x2CU )
+#define J_VK_MINUS          ( 0x2DU )
+#define J_VK_PERIOD         ( 0x2EU )
+#define J_VK_SLASH          ( 0x2FU )
+#define J_VK_0              ( 0x30U )
+#define J_VK_1              ( 0x31U )
+#define J_VK_2              ( 0x32U )
+#define J_VK_3              ( 0x33U )
+#define J_VK_4              ( 0x34U )
+#define J_VK_5              ( 0x35U )
+#define J_VK_6              ( 0x36U )
+#define J_VK_7              ( 0x37U )
+#define J_VK_8              ( 0x38U )
+#define J_VK_9              ( 0x39U )
+#define J_VK_COLON          ( 0x3AU )
+#define J_VK_SEMICOLON      ( 0x3BU )
+#define J_VK_LESS           ( 0x3CU )
+#define J_VK_EQUALS         ( 0x3DU )
+#define J_VK_GREATER        ( 0x3EU )
+#define J_VK_QUESTIONMARK   ( 0x3FU )
+#define J_VK_AT             ( 0x40U )
+#define J_VK_A              ( 0x41U )
+#define J_VK_B              ( 0x42U )
+#define J_VK_C              ( 0x43U )
+#define J_VK_D              ( 0x44U )
+#define J_VK_E              ( 0x45U )
+#define J_VK_F              ( 0x46U )
+#define J_VK_G              ( 0x47U )
+#define J_VK_H              ( 0x48U )
+#define J_VK_I              ( 0x49U )
+#define J_VK_J              ( 0x4AU )
+#define J_VK_K              ( 0x4BU )
+#define J_VK_L              ( 0x4CU )
+#define J_VK_M              ( 0x4DU )
+#define J_VK_N              ( 0x4EU )
+#define J_VK_O              ( 0x4FU )
+#define J_VK_P              ( 0x50U )
+#define J_VK_Q              ( 0x51U )
+#define J_VK_R              ( 0x52U )
+#define J_VK_S              ( 0x53U )
+#define J_VK_T              ( 0x54U )
+#define J_VK_U              ( 0x55U )
+#define J_VK_V              ( 0x56U )
+#define J_VK_W              ( 0x57U )
+#define J_VK_X              ( 0x58U )
+#define J_VK_Y              ( 0x59U )
+#define J_VK_Z              ( 0x5AU )
+#define J_VK_OPEN_BRACKET   ( 0x5BU )
+#define J_VK_BACK_SLASH     ( 0x5CU )
+#define J_VK_CLOSE_BRACKET  ( 0x5DU )
+#define J_VK_CIRCUMFLEX     ( 0x5EU )
+#define J_VK_UNDERSCORE     ( 0x5FU )
+#define J_VK_BACK_QUOTE     ( 0x60U )
+#define J_VK_F1             ( 0x60U+ 1U )
+#define J_VK_F2             ( 0x60U+ 2U )
+#define J_VK_F3             ( 0x60U+ 3U )
+#define J_VK_F4             ( 0x60U+ 4U )
+#define J_VK_F5             ( 0x60U+ 5U )
+#define J_VK_F6             ( 0x60U+ 6U )
+#define J_VK_F7             ( 0x60U+ 7U )
+#define J_VK_F8             ( 0x60U+ 8U )
+#define J_VK_F9             ( 0x60U+ 9U )
+#define J_VK_F10            ( 0x60U+10U )
+#define J_VK_F11            ( 0x60U+11U )
+#define J_VK_F12            ( 0x60U+12U )
+#define J_VK_F13            ( 0x60U+13U )
+#define J_VK_F14            ( 0x60U+14U )
+#define J_VK_F15            ( 0x60U+15U )
+#define J_VK_F16            ( 0x60U+16U )
+#define J_VK_F17            ( 0x60U+17U )
+#define J_VK_F18            ( 0x60U+18U )
+#define J_VK_F19            ( 0x60U+19U )
+#define J_VK_F20            ( 0x60U+20U )
+#define J_VK_F21            ( 0x60U+21U )
+#define J_VK_F22            ( 0x60U+22U )
+#define J_VK_F23            ( 0x60U+23U )
+#define J_VK_F24            ( 0x60U+24U )
+#define J_VK_LEFT_BRACE     ( 0x7BU )
+#define J_VK_PIPE           ( 0x7CU )
+#define J_VK_RIGHT_BRACE    ( 0x7DU )
+#define J_VK_TILDE          ( 0x7EU )
+
+//
+// Unicode: Non printable controls: [0x7F - 0x9F]
+//
+
+#define J_VK_SEPARATOR      ( 0x7FU )
+#define J_VK_NUMPAD0        ( 0x80U )
+#define J_VK_NUMPAD1        ( 0x81U )
+#define J_VK_NUMPAD2        ( 0x82U )
+#define J_VK_NUMPAD3        ( 0x83U )
+#define J_VK_NUMPAD4        ( 0x84U )
+#define J_VK_NUMPAD5        ( 0x85U )
+#define J_VK_NUMPAD6        ( 0x86U )
+#define J_VK_NUMPAD7        ( 0x87U )
+#define J_VK_NUMPAD8        ( 0x88U )
+#define J_VK_NUMPAD9        ( 0x89U )
+#define J_VK_DECIMAL        ( 0x8AU )
+#define J_VK_ADD            ( 0x8BU )
+#define J_VK_SUBTRACT       ( 0x8CU )
+#define J_VK_MULTIPLY       ( 0x8DU )
+#define J_VK_DIVIDE         ( 0x8EU )
+
+#define J_VK_DELETE         ( 0x93U )
+#define J_VK_NUM_LOCK       ( 0x94U )
+#define J_VK_LEFT           ( 0x95U )
+#define J_VK_UP             ( 0x96U )
+#define J_VK_RIGHT          ( 0x97U )
+#define J_VK_DOWN           ( 0x98U )
+#define J_VK_CONTEXT_MENU   ( 0x99U )
+#define J_VK_WINDOWS        ( 0x9AU )
+#define J_VK_META           ( 0x9BU )
+#define J_VK_HELP           ( 0x9CU )
+#define J_VK_COMPOSE        ( 0x9DU )
+#define J_VK_BEGIN          ( 0x9EU )
+#define J_VK_STOP           ( 0x9FU )
+
+//
+// Unicode: Printable [0x00A0 - 0xDFFF]
+//
+
+#define J_VK_INVERTED_EXCLAMATION_MARK ( 0xA1U )
+#define J_VK_EURO_SIGN                ( 0x20ACU )
+
+//
+// Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
+//
+
+/* for Sun keyboards */
+#define J_VK_CUT            ( 0xF879U )
+#define J_VK_COPY           ( 0xF87AU )
+#define J_VK_PASTE          ( 0xF87BU )
+#define J_VK_UNDO           ( 0xF87CU )
+#define J_VK_AGAIN          ( 0xF87DU )
+#define J_VK_FIND           ( 0xF87EU )
+#define J_VK_PROPS          ( 0xF87FU )
+
+/* for input method support on Asian Keyboards */
+#define J_VK_INPUT_METHOD_ON_OFF ( 0xF890U )
+#define J_VK_CODE_INPUT ( 0xF891U )
+#define J_VK_ROMAN_CHARACTERS ( 0xF892U )
+#define J_VK_ALL_CANDIDATES ( 0xF893U )
+#define J_VK_PREVIOUS_CANDIDATE ( 0xF894U )
+#define J_VK_ALPHANUMERIC   ( 0xF895U )
+#define J_VK_KATAKANA       ( 0xF896U )
+#define J_VK_HIRAGANA       ( 0xF897U )
+#define J_VK_FULL_WIDTH     ( 0xF898U )
+#define J_VK_HALF_WIDTH     ( 0xF89AU )
+#define J_VK_JAPANESE_KATAKANA ( 0xF89BU )
+#define J_VK_JAPANESE_HIRAGANA ( 0xF89CU )
+#define J_VK_JAPANESE_ROMAN ( 0xF89DU )
+#define J_VK_KANA_LOCK ( 0xF89FU )
+
+#define J_VK_KEYBOARD_INVISIBLE ( 0xF8FFU )
 
 #endif
 
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index b9c3392..1c7064a 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -62,12 +62,36 @@ static NSString* jstringToNSString(JNIEnv* env, jstring jstr)
     return str;
 }
 
-static void setFrameTopLeftPoint(NSWindow* pWin, NewtMacWindow* mWin, jint x, jint y) {
-    NSPoint pS = [mWin newtScreenWinPos2OSXScreenPos: NSMakePoint(x, y)];
+static void setWindowClientTopLeftPoint(NewtMacWindow* mWin, jint x, jint y, BOOL doDisplay) {
+    DBG_PRINT( "setWindowClientTopLeftPoint.0 - window: %p %d/%d, display %d\n", mWin, (int)x, (int)y, (int)doDisplay);
+    NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)];
+    DBG_PRINT( "setWindowClientTopLeftPoint.1: %d/%d\n", (int)pS.x, (int)pS.y);
+
     [mWin setFrameOrigin: pS];
+    DBG_PRINT( "setWindowClientTopLeftPoint.X: %d/%d\n", (int)pS.x, (int)pS.y);
+
+    if( doDisplay ) {
+        NSView* mView = [mWin contentView];
+        [mWin invalidateCursorRectsForView: mView];
+    }
+}
 
-    NSView* mView = [mWin contentView];
-    [mWin invalidateCursorRectsForView: mView];
+static void setWindowClientTopLeftPointAndSize(NewtMacWindow* mWin, jint x, jint y, jint width, jint height, BOOL doDisplay) {
+    DBG_PRINT( "setWindowClientTopLeftPointAndSize.0 - window: %p %d/%d %dx%d, display %d\n", mWin, (int)x, (int)y, (int)width, (int)height, (int)doDisplay);
+    NSSize clientSZ = NSMakeSize(width, height);
+    NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y) size: clientSZ];
+    NSSize topSZ = [mWin newtClientSize2TLSize: clientSZ];
+    NSRect rect = { pS, topSZ };
+    DBG_PRINT( "setWindowClientTopLeftPointAndSize.1: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height);
+
+    [mWin setFrame: rect display:doDisplay];
+    DBG_PRINT( "setWindowClientTopLeftPointAndSize.X: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height);
+
+    // -> display:YES
+    // if( doDisplay ) {
+    //   NSView* mView = [mWin contentView];
+    //   [mWin invalidateCursorRectsForView: mView];
+    // }
 }
 
 #ifdef VERBOSE_ON
@@ -76,22 +100,50 @@ static int getRetainCount(NSObject * obj) {
 }
 #endif
 
-static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView) {
-    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtView *view, BOOL enable) {
+    DBG_PRINT( "setJavaWindowObject.0: View %p\n", view);
+    if( !enable) {
+        jobject globJavaWindowObject = [view getJavaWindowObject];
+        if( NULL != globJavaWindowObject ) {
+            DBG_PRINT( "setJavaWindowObject.1: View %p - Clear old javaWindowObject %p\n", view, globJavaWindowObject);
+            (*env)->DeleteGlobalRef(env, globJavaWindowObject);
+            [view setJavaWindowObject: NULL];
+        }
+    } else if( NULL != newJavaWindowObject ) {
+        DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject);
+        jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject);
+        [view setJavaWindowObject: globJavaWindowObject];
+        {
+            JavaVM *jvmHandle = NULL;
+            int jvmVersion = 0;
+
+            if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
+                jvmHandle = NULL;
+            } else {
+                jvmVersion = (*env)->GetVersion(env);
+            }
+            [view setJVMHandle: jvmHandle];
+            [view setJVMVersion: jvmVersion];
+        }
+    }
+    DBG_PRINT( "setJavaWindowObject.X: View %p\n", view);
+}
+
+static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView, BOOL setJavaWindow) {
     NSView* oldNSView = [win contentView];
-    NewtView* oldView = NULL;
+    NewtView* oldNewtView = NULL;
 #ifdef VERBOSE_ON
     int dbgIdx = 1;
 #endif
 
-    if( [oldNSView isMemberOfClass:[NewtView class]] ) {
-        oldView = (NewtView *) oldNSView;
+    if( [oldNSView isKindOfClass:[NewtView class]] ) {
+        oldNewtView = (NewtView *) oldNSView;
     }
 
     DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d), parent view %p\n", 
-        dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView), pview);
+        dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView), pview);
 
-    if(NULL!=oldNSView) {
+    if( NULL!=oldNSView ) {
 NS_DURING
         // Available >= 10.5 - Makes the menubar disapear
         BOOL iifs;
@@ -106,34 +158,21 @@ NS_DURING
 NS_HANDLER
 NS_ENDHANDLER
         DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d)\n", 
-            dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+            dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView));
 
-        if( NULL != oldView ) {
-            jobject globJavaWindowObject = [oldView getJavaWindowObject];
-            (*env)->DeleteGlobalRef(env, globJavaWindowObject);
-            [oldView setJavaWindowObject: NULL];
-            [oldView setDestroyNotifySent: false];
+        if( NULL != oldNewtView ) {
+            [oldNewtView setDestroyNotifySent: false];
+            setJavaWindowObject(env, NULL, oldNewtView, NO);
         }
         [oldNSView removeFromSuperviewWithoutNeedingDisplay];
     }
     DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n", 
         dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
 
-    if(NULL!=newView) {
-        jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject);
-        [newView setJavaWindowObject: globJavaWindowObject];
+    if( NULL!=newView ) {
         [newView setDestroyNotifySent: false];
-        {
-            JavaVM *jvmHandle = NULL;
-            int jvmVersion = 0;
-
-            if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
-                jvmHandle = NULL;
-            } else {
-                jvmVersion = (*env)->GetVersion(env);
-            }
-            [newView setJVMHandle: jvmHandle];
-            [newView setJVMVersion: jvmVersion];
+        if( setJavaWindow ) {
+            setJavaWindowObject(env, javaWindowObject, newView, YES);
         }
 
         DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d)\n", 
@@ -152,12 +191,10 @@ NS_ENDHANDLER
         dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
 
     // make sure the insets are updated in the java object
-    [win updateInsets: env];
+    [win updateInsets: env jwin:javaWindowObject];
 
     DBG_PRINT( "changeContentView.X win %p, view (%p,%d -> %p,%d)\n", 
         win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView));
-
-    [pool release];
 }
 
 /*
@@ -248,47 +285,32 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_stopNSApplic
     [pool release];
 }
 
-static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) {
+static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx, BOOL cap) {
     NSArray *screens = [NSScreen screens];
-    if(screen_idx<0) screen_idx=0;
-    if(screen_idx>=[screens count]) screen_idx=0;
+    if( screen_idx<0 || screen_idx>=[screens count] ) {
+        if( cap ) {
+            screen_idx=0;
+        } else {
+            return NULL;
+        }
+    }
     return (NSScreen *) [screens objectAtIndex: screen_idx];
 }
 
-/*
- * Class:     jogamp_newt_driver_macosx_ScreenDriver
- * Method:    getWidthImpl
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getWidthImpl0
-  (JNIEnv *env, jclass clazz, jint screen_idx)
-{
-    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
-    NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx);
-    NSRect rect = [screen frame];
-
-    [pool release];
-
-    return (jint) (rect.size.width);
-}
-
-/*
- * Class:     jogamp_newt_driver_macosx_ScreenDriver
- * Method:    getHeightImpl
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getHeightImpl0
-  (JNIEnv *env, jclass clazz, jint screen_idx)
-{
-    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
-    NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx);
-    NSRect rect = [screen frame];
-
-    [pool release];
-
-    return (jint) (rect.size.height);
+static NSScreen * NewtScreen_getNSScreenByCoord(int x, int y) {
+    NSArray *screens = [NSScreen screens];
+    int i;
+    for(i=[screens count]-1; i>=0; i--) {
+        NSScreen * screen = (NSScreen *) [screens objectAtIndex: i];
+        NSRect frame = [screen frame];
+        if( x >= frame.origin.x && 
+            y >= frame.origin.y &&
+            x <  frame.origin.x + frame.size.width &&
+            y <  frame.origin.y + frame.size.height ) {
+            return screen;
+        }
+    }
+    return (NSScreen *) [screens objectAtIndex: 0];
 }
 
 static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
@@ -325,11 +347,11 @@ static long GetDictionaryLong(CFDictionaryRef theDict, const void* key)
 
 /*
  * Class:     jogamp_newt_driver_macosx_ScreenDriver
- * Method:    getScreenSizeMM0
+ * Method:    getMonitorProps0
  * Signature: (I)[I
  */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScreenSizeMM0
-  (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorProps0
+  (JNIEnv *env, jobject obj, jint crt_idx)
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
@@ -339,33 +361,46 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
     timespec_now(&t0);
 #endif
 
-    NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
 #ifdef DBG_PERF
     timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
-    fprintf(stderr, "MacScreen_getScreenSizeMM0.1: %ld ms\n", td_ms); fflush(NULL);
+    fprintf(stderr, "MacScreen_getMonitorProps0.1: %ld ms\n", td_ms); fflush(NULL);
 #endif
-
+    NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+    if( NULL == screen ) {
+        [pool release];
+        return NULL;
+    }
     CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
 #ifdef DBG_PERF
     timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
-    fprintf(stderr, "MacScreen_getScreenSizeMM0.2: %ld ms\n", td_ms); fflush(NULL);
+    fprintf(stderr, "MacScreen_getMonitorProps0.2: %ld ms\n", td_ms); fflush(NULL);
 #endif
 
-    CGSize screenDim = CGDisplayScreenSize(display);
+    CGSize sizeMM = CGDisplayScreenSize(display);
 #ifdef DBG_PERF
     timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
-    fprintf(stderr, "MacScreen_getScreenSizeMM0.3: %ld ms\n", td_ms); fflush(NULL);
+    fprintf(stderr, "MacScreen_getMonitorProps0.3: %ld ms\n", td_ms); fflush(NULL);
 #endif
 
-    jint prop[ 2 ];
-    prop[0] = (jint) screenDim.width;
-    prop[1] = (jint) screenDim.height;
-
-    jintArray properties = (*env)->NewIntArray(env, 2);
+    CGRect bounds = CGDisplayBounds (display);
+    
+    jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES;
+    jint prop[ propCount ];
+    int offset = 0;
+    prop[offset++] = propCount;
+    prop[offset++] = crt_idx;
+    prop[offset++] = (jint) sizeMM.width;
+    prop[offset++] = (jint) sizeMM.height;
+    prop[offset++] = (jint) bounds.origin.x;    // rotated viewport x
+    prop[offset++] = (jint) bounds.origin.y;    // rotated viewport y
+    prop[offset++] = (jint) bounds.size.width;  // rotated viewport width
+    prop[offset++] = (jint) bounds.size.height; // rotated viewport height
+
+    jintArray properties = (*env)->NewIntArray(env, propCount);
     if (properties == NULL) {
-        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2");
+        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
     }
-    (*env)->SetIntArrayRegion(env, properties, 0, 2, prop);
+    (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
     
     [pool release];
 
@@ -374,16 +409,19 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
 
 /*
  * Class:     jogamp_newt_driver_macosx_ScreenDriver
- * Method:    getScreenMode0
- * Signature: (IIII)[I
+ * Method:    getMonitorMode0
+ * Signature: (II)[I
  */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScreenMode0
-  (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx, jint widthMM, jint heightMM)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorMode0
+  (JNIEnv *env, jobject obj, jint crt_idx, jint mode_idx)
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
-    int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL;
-    NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
+    NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+    if( NULL == screen ) {
+        [pool release];
+        return NULL;
+    }
     CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
 
     CFArrayRef availableModes = CGDisplayAvailableModes(display);
@@ -392,12 +430,13 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
     CFDictionaryRef mode = NULL;
     int currentCCWRot = (int)CGDisplayRotation(display);
     jint ccwRot = 0;
+    int nativeId = 0;
 
 #ifdef VERBOSE_ON
     if(0 >= mode_idx) {
         // only for current mode (-1) and first mode (scanning)
         DBG_PRINT( "getScreenMode0: scrn %d (%p, %p), mode %d, avail: %d/%d, current rot %d ccw\n",  
-            (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot);
+            (int)crt_idx, screen, (void*)(intptr_t)display, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot);
     }
 #endif
 
@@ -406,16 +445,18 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
         DBG_PRINT( "getScreenMode0: end of modes: mode %d, avail: %d/%d\n",
             (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
         [pool release];
-        return (*env)->NewIntArray(env, 0);
+        return NULL;
     } else if(-1 < mode_idx) {
         // only at initialization time, where index >= 0
-        prop_num++; // add 1st extra prop, mode_idx
-        mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE);
+        nativeId = mode_idx / ROTMODES_PER_REALMODE;
         ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90;
+        mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId);
     } else {
         // current mode
         mode = CGDisplayCurrentMode(display);
         ccwRot = currentCCWRot;
+        CFRange range = CFRangeMake (0, numberOfAvailableModes);
+        nativeId = CFArrayGetFirstIndexOfValue(availableModes, range, (CFDictionaryRef)mode);
     }
     // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
 
@@ -429,36 +470,30 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
         mHeight = tempWidth;
     }
 
-    jint prop[ prop_num ];
+    jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
     int propIndex = 0;
-    int propIndexRes = 0;
 
-    if( -1 < mode_idx ) {
-        prop[propIndex++] = mode_idx;
-    }
     int refreshRate = CGDDGetModeRefreshRate(mode);
     int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8)
-    prop[propIndex++] = 0; // set later for verification of iterator
-    propIndexRes = propIndex;
+    prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
     prop[propIndex++] = mWidth;
     prop[propIndex++] = mHeight;
     prop[propIndex++] = CGDDGetModeBitsPerPixel(mode);
-    prop[propIndex++] = widthMM;
-    prop[propIndex++] = heightMM;
-    prop[propIndex++] = fRefreshRate;
+    prop[propIndex++] = fRefreshRate * 100; // Hz*100
+    prop[propIndex++] = 0; // flags
+    prop[propIndex++] = nativeId;
     prop[propIndex++] = ccwRot;
-    prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL
 
-    DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d / %d Hz, rot %d ccw\n",
+    DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %d / %d Hz, nativeId %d, rot %d ccw\n",
         (int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes, 
-        (int)prop[propIndexRes+0], (int)prop[propIndexRes+1], (int)prop[propIndexRes+2], 
-        (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], refreshRate, (int)prop[propIndexRes+6]);
+        (int)prop[1], (int)prop[2], (int)prop[3],
+        (int)prop[4], refreshRate, (int)prop[6], (int)prop[7]);
 
-    jintArray properties = (*env)->NewIntArray(env, prop_num);
+    jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
     if (properties == NULL) {
-        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num);
+        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
     }
-    (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop);
+    (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
     
     // CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef
     [pool release];
@@ -468,36 +503,47 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree
 
 /*
  * Class:     jogamp_newt_driver_macosx_ScreenDriver
- * Method:    setScreenMode0
- * Signature: (II)Z
+ * Method:    setMonitorMode0
+ * Signature: (III)Z
  */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setScreenMode0
-  (JNIEnv *env, jobject object, jint scrn_idx, jint mode_idx)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setMonitorMode0
+  (JNIEnv *env, jobject object, jint crt_idx, jint nativeId, jint ccwRot)
 {
     jboolean res = JNI_TRUE;
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
-    NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
+    NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+    if( NULL == screen ) {
+        [pool release];
+        return JNI_FALSE;
+    }
     CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
 
     CFArrayRef availableModes = CGDisplayAvailableModes(display);
-#ifdef VERBOSE_ON
     CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes);
+#ifdef VERBOSE_ON
     CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes;
 #endif
-    CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE);
-    // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
 
-    int ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90;
-    DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), mode %d, rot %d ccw, avail: %d/%d\n",  
-        (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
+    DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), nativeID %d, rot %d ccw, avail: %d/%d\n",  
+        (int)crt_idx, screen, (void*)(intptr_t)display, (int)nativeId, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
+
+    CFDictionaryRef mode = NULL;
 
-    if(ccwRot!=0) {
+    if( 0 != ccwRot ) {
         // FIXME: How to rotate the display/screen on OSX programmatically ?
         DBG_PRINT( "setScreenMode0: Don't know how to rotate screen on OS X: rot %d ccw\n", ccwRot);
         res = JNI_FALSE;
+    } else {
+        if( numberOfAvailableModes <= nativeId ) {
+            res = JNI_FALSE;
+        } else {
+            mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId);
+            // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
+        }
     }
-    if(JNI_TRUE == res) {
+
+    if( NULL != mode ) {
         CGError err = CGDisplaySwitchToMode(display, mode);
         if(kCGErrorSuccess != err) {
             DBG_PRINT( "setScreenMode0: SetMode failed: %d\n", (int)err);
@@ -553,46 +599,123 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0
     return (jboolean) res;
 }
 
-/*
+/**
+ * Class:     jogamp_newt_driver_macosx_WindowDriver
+ * Method:    createView0
+ * Signature: (IIIIZ)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createView0
+  (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h, 
+   jboolean fullscreen)
+{
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+    DBG_PRINT( "createView0 - %p (this), %d/%d %dx%d, fs %d (START)\n",
+        (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen);
+
+    NSScreen *myScreen =  NewtScreen_getNSScreenByCoord(x, y);
+    NSRect rectWin;
+
+    if (fullscreen) {
+        rectWin = [myScreen frame];
+        x = 0;
+        y = 0;
+        w = (jint) (rectWin.size.width);
+        h = (jint) (rectWin.size.height);
+    } else {
+        rectWin = NSMakeRect(x, y, w, h);
+    }
+
+    NSRect rectView = NSMakeRect(0, 0, w, h);
+    NewtView *myView = [[NewtView alloc] initWithFrame: rectView] ;
+    DBG_PRINT( "createView0.X.%d - new view: %p\n", myView);
+
+    [pool release];
+
+    return (jlong) ((intptr_t) myView);
+}
+
+/**
+ * Method creates a deferred un-initialized Window, hence no special invocation required inside method.
+ *
  * Class:     jogamp_newt_driver_macosx_WindowDriver
  * Method:    createWindow0
- * Signature: (JIIIIZIIIJ)J
+ * Signature: (IIIIZIIJ)J
  */
 JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow0
-  (JNIEnv *env, jobject jthis, jlong parent, jint x, jint y, jint w, jint h, jboolean opaque, jboolean fullscreen, jint styleMask, 
-   jint bufferingType, jint screen_idx, jlong jview)
+  (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h, 
+   jboolean fullscreen, jint styleMask, jint bufferingType, jlong jview)
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
     NewtView* myView = (NewtView*) (intptr_t) jview ;
 
-    DBG_PRINT( "createWindow0 - %p (this), %p (parent), %d/%d %dx%d, opaque %d, fs %d, style %X, buffType %X, screenidx %d, view %p (START)\n",
-        (void*)(intptr_t)jthis, (void*)(intptr_t)parent, (int)x, (int)y, (int)w, (int)h, (int) opaque, (int)fullscreen, 
-        (int)styleMask, (int)bufferingType, (int)screen_idx, myView);
+    DBG_PRINT( "createWindow0 - %p (this), %d/%d %dx%d, fs %d, style %X, buffType %X, screenidx %d, view %p (START)\n",
+        (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen, 
+        (int)styleMask, (int)bufferingType, myView);
+    (void)myView;
 
-    NSArray *screens = [NSScreen screens];
-    if(screen_idx<0) screen_idx=0;
-    if(screen_idx>=[screens count]) screen_idx=0;
-    NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx];
-    NSRect rect;
+    NSScreen *myScreen =  NewtScreen_getNSScreenByCoord(x, y);
 
+    NSRect rectWin;
     if (fullscreen) {
         styleMask = NSBorderlessWindowMask;
-        rect = [myScreen frame];
+        rectWin = [myScreen frame];
         x = 0;
         y = 0;
-        w = (jint) (rect.size.width);
-        h = (jint) (rect.size.height);
+        w = (jint) (rectWin.size.width);
+        h = (jint) (rectWin.size.height);
     } else {
-        rect = NSMakeRect(x, y, w, h);
+        rectWin = NSMakeRect(x, y, w, h);
     }
 
     // Allocate the window
-    NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rect
+    NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rectWin
                                                styleMask: (NSUInteger) styleMask
                                                backing: (NSBackingStoreType) bufferingType
-                                               defer: NO
-                                               screen: myScreen
+                                               defer: YES
                                                isFullscreenWindow: fullscreen];
+
+    // DBG_PRINT( "createWindow0.1 - %p, isVisible %d\n", myWindow, [myWindow isVisible]);
+
+    DBG_PRINT( "createWindow0.X - %p, isVisible %d\n", myWindow, [myWindow isVisible]);
+
+    [pool release];
+
+    return (jlong) ((intptr_t) myWindow);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class:     jogamp_newt_driver_macosx_WindowDriver
+ * Method:    initWindow0
+ * Signature: (JJIIIIZZZJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0
+  (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, 
+   jboolean opaque, jboolean fullscreen, jboolean visible, jlong jview)
+{
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window);
+    NewtView* myView = (NewtView*) (intptr_t) jview ;
+
+    DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, opaque %d, fs %d, visible %d, view %p (START)\n",
+        (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, 
+        (int) opaque, (int)fullscreen, (int)visible, myView);
+
+    NSScreen *myScreen =  NewtScreen_getNSScreenByCoord(x, y);
+
+    NSRect rectWin;
+    if (fullscreen) {
+        rectWin = [myScreen frame];
+        x = 0;
+        y = 0;
+        w = (jint) (rectWin.size.width);
+        h = (jint) (rectWin.size.height);
+    } else {
+        rectWin = NSMakeRect(x, y, w, h);
+    }
+
     [myWindow setReleasedWhenClosed: YES]; // default
     [myWindow setPreservesContentDuringLiveResize: NO];
 
@@ -602,15 +725,15 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow
     if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) {
         parentWindow = (NSWindow*) nsParentObj;
         parentView = [parentWindow contentView];
-        DBG_PRINT( "createWindow0 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView);
+        DBG_PRINT( "initWindow0 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView);
     } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) {
         parentView = (NSView*) nsParentObj;
         parentWindow = [parentView window];
-        DBG_PRINT( "createWindow0 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow);
+        DBG_PRINT( "initWindow0 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow);
     } else {
-        DBG_PRINT( "createWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj);
+        DBG_PRINT( "initWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj);
     }
-    DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]);
+    DBG_PRINT( "initWindow0 - is visible.1: %d\n", [myWindow isVisible]);
 
     // Remove animations for child windows
     if(NULL != parentWindow) {
@@ -628,11 +751,11 @@ NS_ENDHANDLER
 #endif
     if(opaque) {
         [myWindow setOpaque: YES];
-        DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
+        DBG_PRINT( "initWindow0.%d\n", dbgIdx++);
         if (!fullscreen) {
             [myWindow setShowsResizeIndicator: YES];
         }
-        DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
+        DBG_PRINT( "initWindow0.%d\n", dbgIdx++);
     } else {
         [myWindow setOpaque: NO];
         [myWindow setBackgroundColor: [NSColor clearColor]];
@@ -640,35 +763,28 @@ NS_ENDHANDLER
 
     // specify we want mouse-moved events
     [myWindow setAcceptsMouseMovedEvents:YES];
-    DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
 
-    // Use given NewtView or allocate an NewtView if NULL
-    if(NULL == myView) {
-        myView = [[NewtView alloc] initWithFrame: rect] ;
-        DBG_PRINT( "createWindow0.%d - use new view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView));
-    } else {
-        DBG_PRINT( "createWindow0.%d - use given view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView));
-    }
-
-    DBG_PRINT( "createWindow0.%d - %p,%d view %p,%d, isVisible %d\n", 
+    DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", 
         dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
 
     // Set the content view
-    changeContentView(env, jthis, parentView, myWindow, myView);
+    changeContentView(env, jthis, parentView, myWindow, myView, NO);
 
-    DBG_PRINT( "createWindow0.%d - %p,%d view %p,%d, isVisible %d\n", 
+    DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", 
         dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
 
     if(NULL!=parentWindow) {
         [myWindow attachToParent: parentWindow];
     }
 
-    // Immediately re-position the window based on an upper-left coordinate system
-    setFrameTopLeftPoint(parentWindow, myWindow, x, y);
+    DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d, visible %d\n", 
+        dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible], visible);
 
-    // force surface creation
-    [myView lockFocus];
-    [myView unlockFocus];
+    // Immediately re-position this window based on an upper-left coordinate system
+    setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO);
+
+    DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", 
+        dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
 
 NS_DURING
     // concurrent view rendering
@@ -676,18 +792,34 @@ NS_DURING
     if ( [myWindow respondsToSelector:@selector(setAllowsConcurrentViewDrawing:)] ) {
         [myWindow setAllowsConcurrentViewDrawing: YES];
     }
+
+    DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", 
+        dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
+
     if ( [myView respondsToSelector:@selector(setCanDrawConcurrently:)] ) {
         [myView setCanDrawConcurrently: YES];
     }
 NS_HANDLER
 NS_ENDHANDLER
 
+    DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", 
+        dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
+
     // visible on front
-    [myWindow orderFront: myWindow];
+    if( visible ) {
+        [myWindow orderFront: myWindow];
+    }
+
+    DBG_PRINT( "initWindow0.%d - %p,%d view %p,%d, isVisible %d\n", 
+        dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
+
+    // force surface creation
+    // [myView lockFocus];
+    // [myView unlockFocus];
 
 NS_DURING
     // Available >= 10.5 - Makes the menubar disapear
-    if(fullscreen) {
+    if( fullscreen ) {
         if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) {
             [myView enterFullScreenMode: myScreen withOptions:NULL];
         }
@@ -699,26 +831,21 @@ NS_ENDHANDLER
     // right mouse button down events
     [myView setNextResponder: myWindow];
 
-    DBG_PRINT( "createWindow0 - %p (this), %p (parent): new window: %p, view %p,%d (END)\n",
+    DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p,%d\n",
         (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView, getRetainCount(myView));
 
-    [pool release];
+    [myView setDestroyNotifySent: false];
+    setJavaWindowObject(env, jthis, myView, YES);
 
-    return (jlong) ((intptr_t) myWindow);
-}
-// Footnote: Our view handling produces random 'Assertion failure' even w/o parenting:
-//
-// [NSThemeFrame lockFocus], /SourceCache/AppKit/AppKit-1138.23/AppKit.subproj/NSView.m:6053
-// [NSThemeFrame(0x7fe94bc72c80) lockFocus] failed with window=0x7fe94bc445a0, windowNumber=9425, [self isHiddenOrHasHiddenAncestor]=0
-//                       ..
-// AppKit                0x00007fff89621001 -[NSView lockFocus] + 250
-// AppKit                0x00007fff8961eafa -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 3780
-// AppKit                0x00007fff8961793e -[NSView displayIfNeeded] + 1676
-// AppKit                0x00007fff8961707d _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints + 648
-//                       
+    DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p,%d\n",
+        (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView, getRetainCount(myView));
 
+    [pool release];
+}
 
-/*
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
  * Class:     jogamp_newt_driver_macosx_WindowDriver
  * Method:    close0
  * Signature: (J)V
@@ -735,17 +862,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0
     DBG_PRINT( "windowClose.0 - %p,%d, destroyNotifySent %d, view %p,%d, parent %p\n", 
         mWin, getRetainCount(mWin), destroyNotifySent, mView, getRetainCount(mView), pWin);
 
-    [mWin setUnrealized];
+    [mWin setRealized: NO];
 
     if(NULL!=mView) {
         // cleanup view
-        jobject javaWindowObject = [mView getJavaWindowObject];
         [mView setDestroyNotifySent: true];
-        if(NULL!=javaWindowObject) {
-            DBG_PRINT( "windowClose.0: Clear global javaWindowObject reference (%p)\n", javaWindowObject);
-            (*env)->DeleteGlobalRef(env, javaWindowObject);
-            [mView setJavaWindowObject: NULL];
-        }
+        setJavaWindowObject(env, NULL, mView, NO);
     }
 
 NS_DURING
@@ -761,8 +883,6 @@ NS_DURING
             [mView exitFullScreenModeWithOptions: NULL];
         }
         // Note: mWin's release will also release it's mView!
-        // [mWin setContentView: nil];
-        // [mView release];
     }
 NS_HANDLER
 NS_ENDHANDLER
@@ -770,7 +890,7 @@ NS_ENDHANDLER
     if(NULL!=pWin) {
         [mWin detachFromParent: pWin];
     }
-    [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
+    [mWin orderOut: mWin];
 
     DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n", 
         mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin);
@@ -778,11 +898,10 @@ NS_ENDHANDLER
     // Only release window, if release is not yet in process.
     // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked.
     if(!destroyNotifySent) { 
-        [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
+        [mWin release];
     }
 
-    DBG_PRINT( "windowClose.X - %p,%d, released %d, view %p,%d, parent %p\n", 
-        mWin, getRetainCount(mWin), !destroyNotifySent, mView, getRetainCount(mView), pWin);
+    DBG_PRINT( "windowClose.Xp\n");
 
     [pool release];
 }
@@ -790,16 +909,16 @@ NS_ENDHANDLER
 /*
  * Class:     Java_jogamp_newt_driver_macosx_WindowDriver
  * Method:    lockSurface0
- * Signature: (J)Z
+ * Signature: (JJ)Z
  */
 JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurface0
-  (JNIEnv *env, jclass clazz, jlong window)
+  (JNIEnv *env, jclass clazz, jlong window, jlong view)
 {
     NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
     if(NO == [mWin isRealized]) {
         return JNI_FALSE;
     }
-    NewtView * mView = (NewtView *) [mWin contentView];
+    NewtView * mView = (NewtView *) ((intptr_t) view);
     return [mView softLock] == YES ? JNI_TRUE : JNI_FALSE;
     /** deadlocks, since we render independent of focus
     return [mView lockFocusIfCanDraw] == YES ? JNI_TRUE : JNI_FALSE; */
@@ -808,14 +927,15 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurfa
 /*
  * Class:     Java_jogamp_newt_driver_macosx_WindowDriver
  * Method:    unlockSurface0
- * Signature: (J)V
+ * Signature: (JJ)Z
  */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0
-  (JNIEnv *env, jclass clazz, jlong window)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0
+  (JNIEnv *env, jclass clazz, jlong window, jlong view)
 {
-    NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
-    NewtView * mView = (NewtView *) [mWin contentView];
-    [mView softUnlock];
+    // NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
+    (void) window;
+    NewtView * mView = (NewtView *) ((intptr_t) view);
+    return [mView softUnlock] == YES ? JNI_TRUE : JNI_FALSE;
     /** deadlocks, since we render independent of focus
     [mView unlockFocus]; */
 }
@@ -837,8 +957,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0
     DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus);
 
     [mWin makeFirstResponder: nil];
-    [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO];
-    [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO];
+    [mWin orderFrontRegardless];
+    [mWin makeKeyWindow];
 
     DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force);
 
@@ -861,10 +981,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0
     DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
     if( hasFocus ) {
         if(NULL != pWin) {
-            // [mWin performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:pWin waitUntilDone:NO];
-            [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO];
+            // [mWin makeFirstResponder: pWin];
+            [pWin makeKeyWindow];
         } else {
-            [mWin performSelectorOnMainThread:@selector(resignKeyWindow) withObject:nil waitUntilDone:NO];
+            [pWin resignKeyWindow];
         }
     }
     DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin);
@@ -885,7 +1005,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0
 
     DBG_PRINT( "orderFront0 - window: %p (START)\n", win);
 
-    [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO];
+    [win orderFrontRegardless];
 
     DBG_PRINT( "orderFront0 - window: %p (END)\n", win);
 
@@ -903,13 +1023,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
     NSWindow* mWin = (NSWindow*) ((intptr_t) window);
     NSWindow* pWin = [mWin parentWindow];
+    BOOL pWinVisible = NULL != pWin ? [pWin isVisible] : 0;
 
-    DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin);
+    DBG_PRINT( "orderOut0 - window: (parent %p visible %d) %p visible %d (START)\n", pWin, pWinVisible, mWin, [mWin isVisible]);
 
-    if(NULL == pWin) {
-        [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO];
+    if( NULL == pWin || !pWinVisible ) {
+        [mWin orderOut: mWin];
     } else {
-        [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:NO];
+        [mWin orderBack: mWin];
     }
 
     DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin);
@@ -941,7 +1062,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setTitle0
 
 /*
  * Class:     jogamp_newt_driver_macosx_WindowDriver
- * Method:    contentView
+ * Method:    contentView0
  * Signature: (J)J
  */
 JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0
@@ -949,38 +1070,38 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
     NSWindow* win = (NSWindow*) ((intptr_t) window);
+    NSView* nsView = [win contentView];
+    NewtView* newtView = NULL;
 
-    DBG_PRINT( "contentView0 - window: %p (START)\n", win);
+    if( [nsView isKindOfClass:[NewtView class]] ) {
+        newtView = (NewtView *) nsView;
+    }
 
-    jlong res = (jlong) ((intptr_t) [win contentView]);
+    DBG_PRINT( "contentView0 - window: %p, view: %p, newtView %p\n", win, nsView, newtView);
 
-    DBG_PRINT( "contentView0 - window: %p (END)\n", win);
+    jlong res = (jlong) ((intptr_t) nsView);
 
     [pool release];
     return res;
 }
 
-/*
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
  * Class:     jogamp_newt_driver_macosx_WindowDriver
  * Method:    changeContentView
- * Signature: (J)J
+ * Signature: (J)V
  */
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0
   (JNIEnv *env, jobject jthis, jlong parentWindowOrView, jlong window, jlong jview)
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
     NewtView* newView = (NewtView *) ((intptr_t) jview);
     NewtMacWindow* win = (NewtMacWindow*) ((intptr_t) window);
-    NSView* oldNSView = [win contentView];
-    NewtView* oldView = NULL;
 
-    if( [oldNSView isMemberOfClass:[NewtView class]] ) {
-        oldView = (NewtView *) oldNSView;
-    }
-
-    DBG_PRINT( "changeContentView0.0 -  win %p, view (%p,%d (%d) -> %p,%d)\n", 
-        win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+    DBG_PRINT( "changeContentView0.0 -  win %p, view (%p,%d)\n", 
+        win, newView, getRetainCount(newView));
 
     NSObject *nsParentObj = (NSObject*) ((intptr_t) parentWindowOrView);
     NSView* pView = NULL;
@@ -993,62 +1114,49 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeConten
         }
     }
 
-    changeContentView(env, jthis, pView, win, newView);
+    changeContentView(env, jthis, pView, win, newView, YES);
 
-    DBG_PRINT( "changeContentView0.X -  win %p, view (%p,%d (%d) -> %p,%d)\n", 
-        win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+    DBG_PRINT( "changeContentView0.X\n");
 
     [pool release];
-
-    return (jlong) ((intptr_t) oldView);
 }
 
 /*
  * Class:     jogamp_newt_driver_macosx_WindowDriver
- * Method:    setContentSize
- * Signature: (JII)V
+ * Method:    setWindowClientTopLeftPointAndSize0
+ * Signature: (JIIIIZ)V
  */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setContentSize0
-  (JNIEnv *env, jobject unused, jlong window, jint w, jint h)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0
+  (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display)
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-    NSWindow* win = (NSWindow*) ((intptr_t) window);
+    NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
 
-    DBG_PRINT( "setContentSize0 - window: %p (START)\n", win);
+    DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin);
 
-    NSSize sz = NSMakeSize(w, h);
-    [win setContentSize: sz];
+    setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display);
 
-    DBG_PRINT( "setContentSize0 - window: %p (END)\n", win);
+    DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin);
 
     [pool release];
 }
 
 /*
  * Class:     jogamp_newt_driver_macosx_WindowDriver
- * Method:    setFrameTopLeftPoint
- * Signature: (JJII)V
+ * Method:    setWindowClientTopLeftPoint0
+ * Signature: (JIIZ)V
  */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setFrameTopLeftPoint0
-  (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0
+  (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display)
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
     NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
 
-    NSObject *nsParentObj = (NSObject*) ((intptr_t) parent);
-    NSWindow* pWin = NULL;
-    if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) {
-        pWin = (NSWindow*) nsParentObj;
-    } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) {
-        NSView* pView = (NSView*) nsParentObj;
-        pWin = [pView window];
-    }
-
-    DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (START)\n", mWin, pWin);
+    DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin);
 
-    setFrameTopLeftPoint(pWin, mWin, x, y);
+    setWindowClientTopLeftPoint(mWin, x, y, display);
 
-    DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (END)\n", mWin, pWin);
+    DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin);
 
     [pool release];
 }
@@ -1134,6 +1242,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0
   (JNIEnv *env, jclass clazz, jlong window, jint x, jint y)
 {
     NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
-    [mWin setMousePosition: [mWin newtClientWinPos2OSXScreenPos: NSMakePoint(x, y)]];
+    [mWin setMousePosition: [mWin newtRelClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]];
 }
 
diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c
index 7f070e7..c294b6e 100644
--- a/src/newt/native/NewtCommon.c
+++ b/src/newt/native/NewtCommon.c
@@ -72,7 +72,7 @@ jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
     return strChars;
 }
 
-JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached) {
+JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) {
     JNIEnv* curEnv = NULL;
     JNIEnv* newEnv = NULL;
     int envRes;
@@ -81,7 +81,12 @@ JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int * shallBeDe
     envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
     if( JNI_EDETACHED == envRes ) {
         // detached thread - attach to JVM
-        if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) {
+        if( asDaemon ) {
+            envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL);
+        } else {
+            envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL);
+        }
+        if( JNI_OK != envRes ) {
             fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
             return NULL;
         }
diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h
index 9a4e5ac..9cc9e93 100644
--- a/src/newt/native/NewtCommon.h
+++ b/src/newt/native/NewtCommon.h
@@ -76,6 +76,6 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
         (*jvmHandle)->DetachCurrentThread(jvmHandle);
     }
  */
-JNIEnv* NewtCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached);
+JNIEnv* NewtCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached);
 
 #endif
diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h
index 29b646f..c9d53f5 100644
--- a/src/newt/native/NewtMacWindow.h
+++ b/src/newt/native/NewtMacWindow.h
@@ -47,6 +47,8 @@
     #define DBG_PRINT(...)
 #endif
 
+// #define DBG_LIFECYCLE 1
+
 @interface NewtView : NSView
 {
     jobject javaWindowObject;
@@ -56,16 +58,19 @@
     int jvmVersion;
 
     volatile BOOL destroyNotifySent;
-    volatile BOOL softLocked;
+    volatile int softLockCount;
     pthread_mutex_t softLockSync;
 
-    NSTrackingRectTag ptrTrackingTag;
+    volatile NSTrackingRectTag ptrTrackingTag;
     NSRect ptrRect;
     NSCursor * myCursor;
 }
 
 - (id)initWithFrame:(NSRect)frameRect;
+
+#ifdef DBG_LIFECYCLE
 - (void) release;
+#endif
 - (void) dealloc;
 
 /* Set during event dispatching cycle */
@@ -87,7 +92,7 @@
 - (BOOL) getDestroyNotifySent;
 
 - (BOOL) softLock;
-- (void) softUnlock;
+- (BOOL) softUnlock;
 
 - (BOOL) needsDisplay;
 - (void) displayIfNeeded;
@@ -123,19 +128,22 @@
        styleMask: (NSUInteger) windowStyle
        backing: (NSBackingStoreType) bufferingType
        defer: (BOOL) deferCreation
-       screen:(NSScreen *)screen
        isFullscreenWindow:(BOOL)isfs;
+#ifdef DBG_LIFECYCLE
 - (void) release;
+#endif
 - (void) dealloc;
-- (void) setUnrealized;
+- (void) setRealized: (BOOL)v;
 - (BOOL) isRealized;
 
-- (void) updateInsets: (JNIEnv*) env;
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin;
 - (void) attachToParent: (NSWindow*) parent;
 - (void) detachFromParent: (NSWindow*) parent;
 
-- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p;
-- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p;
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p;
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz;
+- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p;
+- (NSSize) newtClientSize2TLSize: (NSSize) nsz;
 - (NSPoint) getLocationOnScreen: (NSPoint) p;
 - (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p;
 
@@ -145,9 +153,9 @@
 - (void) setMouseConfined:(BOOL)v;
 - (void) setMousePosition:(NSPoint)p;
 
-- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType;
-- (void) sendKeyEvent: (jint) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jint) evType;
-- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType;
+- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType;
+- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType;
+- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType;
 - (void) focusChanged: (BOOL) gained;
 
 - (BOOL) becomeFirstResponder;
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
index b89b5c2..35d3ffb 100644
--- a/src/newt/native/NewtMacWindow.m
+++ b/src/newt/native/NewtMacWindow.m
@@ -36,42 +36,56 @@
 #import "KeyEvent.h"
 #import "MouseEvent.h"
 
-jint GetDeltaY(NSEvent *event, jint javaMods) {
-    CGFloat deltaY = 0.0;
+#include <CoreFoundation/CoreFoundation.h>
+#include <Carbon/Carbon.h> /* For kVK_ constants, and TIS functions. */
+
+#include <math.h>
+
+static jfloat GetDelta(NSEvent *event, jint javaMods[]) {
     CGEventRef cgEvent = [event CGEvent];
+    CGFloat deltaY = 0.0;
+    CGFloat deltaX = 0.0;
+    CGFloat delta = 0.0;
 
     if (CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous)) {
         // mouse pad case
-        deltaY =
-            CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
-        // fprintf(stderr, "WHEEL/PAD: %lf\n", (double)deltaY);
+        deltaX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
+        deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
+        // fprintf(stderr, "WHEEL/PAD: %lf/%lf - 0x%X\n", (double)deltaX, (double)deltaY, javaMods[0]);
+        if( fabsf(deltaX) > fabsf(deltaY) ) {
+            javaMods[0] |= EVENT_SHIFT_MASK;
+            delta = deltaX;
+        } else {
+            delta = deltaY;
+        }
     } else {
         // traditional mouse wheel case
+        deltaX = [event deltaX];
         deltaY = [event deltaY];
-        // fprintf(stderr, "WHEEL/TRAD: %lf\n", (double)deltaY);
-        if (deltaY == 0.0 && (javaMods & EVENT_SHIFT_MASK) != 0) {
+        // fprintf(stderr, "WHEEL/TRACK: %lf/%lf - 0x%X\n", (double)deltaX, (double)deltaY, javaMods[0]);
+        if (deltaY == 0.0 && (javaMods[0] & EVENT_SHIFT_MASK) != 0) {
             // shift+vertical wheel scroll produces horizontal scroll
             // we convert it to vertical
-            deltaY = [event deltaX];
+            delta = deltaX;
+        } else {
+            delta = deltaY;
         }
-        if (-1.0 < deltaY && deltaY < 1.0) {
-            deltaY *= 10.0;
+        if (-1.0 < delta && delta < 1.0) {
+            delta *= 10.0;
         } else {
-            if (deltaY < 0.0) {
-                deltaY = deltaY - 0.5f;
+            if (delta < 0.0) {
+                delta = delta - 0.5f;
             } else {
-                deltaY = deltaY + 0.5f;
+                delta = delta + 0.5f;
             }
         }
     }
-    // fprintf(stderr, "WHEEL/res: %d\n", (int)deltaY);
-    return (jint) deltaY;
+    // fprintf(stderr, "WHEEL/RES: %lf - 0x%X\n", (double)delta, javaMods[0]);
+    return (jfloat) delta;
 }
 
 static jmethodID enqueueMouseEventID = NULL;
-static jmethodID sendMouseEventID = NULL;
 static jmethodID enqueueKeyEventID = NULL;
-static jmethodID sendKeyEventID = NULL;
 static jmethodID requestFocusID = NULL;
 
 static jmethodID insetsChangedID   = NULL;
@@ -82,24 +96,23 @@ static jmethodID focusChangedID    = NULL;
 static jmethodID windowDestroyNotifyID = NULL;
 static jmethodID windowRepaintID = NULL;
 
-// Can't use USE_SENDIO_DIRECT, ie w/o enqueueing to EDT,
+// Need to enqueue all events to EDT,
 // since we may operate on AWT-AppKit (Main Thread)
 // and direct issuing 'requestFocus()' would deadlock:
 //     AWT-AppKit
 //     AWT-EventQueue-0
-//
-// #define USE_SENDIO_DIRECT 1
 
 @implementation NewtView
 
 - (id)initWithFrame:(NSRect)frameRect
 {
+    id res = [super initWithFrame:frameRect];
     javaWindowObject = NULL;
 
     jvmHandle = NULL;
     jvmVersion = 0;
     destroyNotifySent = NO;
-    softLocked = NO;
+    softLockCount = 0;
 
     pthread_mutexattr_t softLockSyncAttr;
     pthread_mutexattr_init(&softLockSyncAttr);
@@ -116,28 +129,34 @@ static jmethodID windowRepaintID = NULL;
     */
     myCursor = NULL;
 
-    return [super initWithFrame:frameRect];
+    DBG_PRINT("NewtView::create: %p (refcnt %d)\n", res, (int)[res retainCount]);
+    return res;
 }
 
+#ifdef DBG_LIFECYCLE
 - (void) release
 {
-#ifdef VERBOSE_ON
-    NSLog(@"NewtView::release\n");
-    NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
+    DBG_PRINT("NewtView::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
     [super release];
 }
+#endif
 
 - (void) dealloc
 {
-    if(softLocked) {
+    DBG_PRINT("NewtView::dealloc.0: %p (refcnt %d), ptrTrackingTag %d\n", self, (int)[self retainCount], (int)ptrTrackingTag);
+#ifdef DBG_LIFECYCLE
+    NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+    if( 0 < softLockCount ) {
         NSLog(@"NewtView::dealloc: softLock still hold @ dealloc!\n");
     }
+    if(0 != ptrTrackingTag) {
+        // [self removeCursorRect: ptrRect cursor: myCursor];
+        [self removeTrackingRect: ptrTrackingTag];
+        ptrTrackingTag = 0;
+    }
     pthread_mutex_destroy(&softLockSync);
-#ifdef VERBOSE_ON
-    NSLog(@"NewtView::dealloc\n");
-    NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
+    DBG_PRINT("NewtView::dealloc.X: %p\n", self);
     [super dealloc];
 }
 
@@ -185,6 +204,7 @@ static jmethodID windowRepaintID = NULL;
     if(0 != ptrTrackingTag) {
         // [self removeCursorRect: ptrRect cursor: myCursor];
         [self removeTrackingRect: ptrTrackingTag];
+        ptrTrackingTag = 0;
     }
     ptrRect = [self bounds]; 
     // [self addCursorRect: ptrRect cursor: myCursor];
@@ -209,18 +229,27 @@ static jmethodID windowRepaintID = NULL;
 - (BOOL) softLock
 {
     // DBG_PRINT("*************** softLock.0: %p\n", (void*)pthread_self());
-    // NSLog(@"NewtView::softLock: %@",[NSThread callStackSymbols]);
-    pthread_mutex_lock(&softLockSync);
-    softLocked = YES;
+    int err;
+    if( 0 != ( err = pthread_mutex_lock(&softLockSync) ) ) {
+        NSLog(@"NewtView::softLock failed: errCode %d - %@", err, [NSThread callStackSymbols]);
+        return NO;
+    }
+    softLockCount++;
     // DBG_PRINT("*************** softLock.X: %p\n", (void*)pthread_self());
-    return softLocked;
+    return 0 < softLockCount;
 }
 
-- (void) softUnlock
+- (BOOL) softUnlock
 {
     // DBG_PRINT("*************** softUnlock: %p\n", (void*)pthread_self());
-    softLocked = NO;
-    pthread_mutex_unlock(&softLockSync);
+    softLockCount--;
+    int err;
+    if( 0 != ( err = pthread_mutex_unlock(&softLockSync) ) ) {
+        softLockCount++;
+        NSLog(@"NewtView::softUnlock failed: Not locked by current thread - errCode %d -  %@", err, [NSThread callStackSymbols]);
+        return NO;
+    }
+    return YES;
 }
 
 - (BOOL) needsDisplay
@@ -256,7 +285,7 @@ static jmethodID windowRepaintID = NULL;
         return;
     }
     int shallBeDetached = 0;
-    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached);
     if(NULL==env) {
         DBG_PRINT("drawRect: null JNIEnv\n");
         return;
@@ -268,9 +297,9 @@ static jmethodID windowRepaintID = NULL;
         dirtyRect.origin.x, viewFrame.size.height - dirtyRect.origin.y, 
         dirtyRect.size.width, dirtyRect.size.height);
 
-    if (shallBeDetached) {
+    /* if (shallBeDetached) {
         (*jvmHandle)->DetachCurrentThread(jvmHandle);
-    }
+    } */
 }
 
 - (void) viewDidHide
@@ -280,7 +309,7 @@ static jmethodID windowRepaintID = NULL;
         return;
     }
     int shallBeDetached = 0;
-    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached);
     if(NULL==env) {
         DBG_PRINT("viewDidHide: null JNIEnv\n");
         return;
@@ -288,9 +317,9 @@ static jmethodID windowRepaintID = NULL;
 
     (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_FALSE);
 
-    if (shallBeDetached) {
+    /* if (shallBeDetached) {
         (*jvmHandle)->DetachCurrentThread(jvmHandle);
-    }
+    } */
 
     [super viewDidHide];
 }
@@ -302,7 +331,7 @@ static jmethodID windowRepaintID = NULL;
         return;
     }
     int shallBeDetached = 0;
-    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached);
     if(NULL==env) {
         DBG_PRINT("viewDidUnhide: null JNIEnv\n");
         return;
@@ -310,9 +339,9 @@ static jmethodID windowRepaintID = NULL;
 
     (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_TRUE);
 
-    if (shallBeDetached) {
+    /* if (shallBeDetached) {
         (*jvmHandle)->DetachCurrentThread(jvmHandle);
-    }
+    } */
 
     [super viewDidUnhide];
 }
@@ -324,25 +353,83 @@ static jmethodID windowRepaintID = NULL;
 
 @end
 
+static CFStringRef CKCH_CreateStringForKey(CGKeyCode keyCode, const UCKeyboardLayout *keyboardLayout) {
+    UInt32 keysDown = 0;
+    UniChar chars[4];
+    UniCharCount realLength;
+
+    UCKeyTranslate(keyboardLayout, keyCode,
+                   kUCKeyActionDisplay, 0,
+                   LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit,
+                   &keysDown, sizeof(chars) / sizeof(chars[0]), &realLength, chars);
+
+    return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1);
+}
+
+static CFMutableDictionaryRef CKCH_CreateCodeToCharDict(TISInputSourceRef keyboard) {
+    CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
+    const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
+
+    CFMutableDictionaryRef codeToCharDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 128, NULL, NULL);
+    if ( NULL != codeToCharDict ) {
+        intptr_t i;
+        for (i = 0; i < 128; ++i) {
+            CFStringRef string = CKCH_CreateStringForKey((CGKeyCode)i, keyboardLayout);
+            if( NULL != string ) {
+                CFIndex stringLen = CFStringGetLength (string);
+                if ( 0 < stringLen ) {
+                    UniChar character = CFStringGetCharacterAtIndex(string, 0);
+                    DBG_PRINT("CKCH: MAP 0x%X -> %c\n", (int)i, character);
+                    CFDictionaryAddValue(codeToCharDict, (const void *)i, (const void *)(intptr_t)character);
+                }
+                CFRelease(string);
+            }
+        }
+    }
+    return codeToCharDict;
+}
+
+static CFMutableDictionaryRef CKCH_USCodeToNNChar = NULL;
+
+static void CKCH_CreateDictionaries() {
+    TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
+    CKCH_USCodeToNNChar = CKCH_CreateCodeToCharDict(currentKeyboard);
+    CFRelease(currentKeyboard);
+}
+
+static UniChar CKCH_CharForKeyCode(jshort keyCode) {
+    UniChar rChar = 0;
+
+    if ( NULL != CKCH_USCodeToNNChar ) {
+        intptr_t code = (intptr_t) keyCode;
+        intptr_t character = 0;
+
+        if ( CFDictionaryGetValueIfPresent(CKCH_USCodeToNNChar, (void *)code, (const void **)&character) ) {
+            rChar = (UniChar) character;
+            DBG_PRINT("CKCH: OK 0x%X -> 0x%X\n", (int)keyCode, (int)rChar);
+        }
+    }
+    return rChar;
+}
+
 @implementation NewtMacWindow
 
 + (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz
 {
-    enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V");
-    sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
-    enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V");
-    sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+    enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V");
+    enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V");
     sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged",     "(ZIIZ)V");
     visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
     insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V");
-    positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V");
+    positionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V");
     focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
     windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
     windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
     requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
-    if (enqueueMouseEventID && sendMouseEventID && enqueueKeyEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID &&
+    if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID &&
         positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
     {
+        CKCH_CreateDictionaries();
         return YES;
     }
     return NO;
@@ -352,14 +439,12 @@ static jmethodID windowRepaintID = NULL;
        styleMask: (NSUInteger) windowStyle
        backing: (NSBackingStoreType) bufferingType
        defer: (BOOL) deferCreation
-       screen:(NSScreen *)screen
        isFullscreenWindow:(BOOL)isfs
 {
     id res = [super initWithContentRect: contentRect
                     styleMask: windowStyle
                     backing: bufferingType
-                    defer: deferCreation
-                    screen: screen];
+                    defer: deferCreation];
     isFullscreenWindow = isfs;
     // Why is this necessary? Without it we don't get any of the
     // delegate methods like resizing and window movement.
@@ -377,30 +462,37 @@ static jmethodID windowRepaintID = NULL;
     mouseInside = NO;
     cursorIsHidden = NO;
     realized = YES;
+    DBG_PRINT("NewtWindow::create: %p, realized %d (refcnt %d)\n", res, realized, (int)[res retainCount]);
     return res;
 }
 
+#ifdef DBG_LIFECYCLE
 - (void) release
 {
-#ifdef VERBOSE_ON
-    NSLog(@"NewtWindow::release\n");
-    NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
+    DBG_PRINT("NewtWindow::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+    // NSLog(@"%@",[NSThread callStackSymbols]);
     [super release];
 }
+#endif
 
 - (void) dealloc
 {
-#ifdef VERBOSE_ON
-    NSLog(@"NewtWindow::dealloc\n");
+    DBG_PRINT("NewtWindow::dealloc.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+#ifdef DBG_LIFECYCLE
     NSLog(@"%@",[NSThread callStackSymbols]);
 #endif
+
+    NewtView* mView = (NewtView *)[self contentView];
+    if( NULL != mView ) {
+        [mView release];
+    }
     [super dealloc];
+    DBG_PRINT("NewtWindow::dealloc.X: %p\n", self);
 }
 
-- (void) setUnrealized
+- (void) setRealized: (BOOL)v
 {
-    realized = NO;
+    realized = v;
 }
 
 - (BOOL) isRealized
@@ -408,18 +500,8 @@ static jmethodID windowRepaintID = NULL;
     return realized;
 }
 
-- (void) updateInsets: (JNIEnv*) env
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin
 {
-    NSView* nsview = [self contentView];
-    if( ! [nsview isMemberOfClass:[NewtView class]] ) {
-        return;
-    }
-    NewtView* view = (NewtView *) nsview;
-    jobject javaWindowObject = [view getJavaWindowObject];
-    if (env==NULL || javaWindowObject == NULL) {
-        return;
-    }
-    
     NSRect frameRect = [self frame];
     NSRect contentRect = [self contentRectForFrameRect: frameRect];
 
@@ -433,7 +515,9 @@ static jmethodID windowRepaintID = NULL;
 
     DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
 
-    (*env)->CallVoidMethod(env, javaWindowObject, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
+    if( NULL != env && NULL != javaWin ) {
+        (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
+    }
 }
 
 - (void) attachToParent: (NSWindow*) parent
@@ -457,27 +541,46 @@ static jmethodID windowRepaintID = NULL;
 }
 
 /**
- * p abs screen position w/ top-left origin
+ * p abs screen position of client-area pos w/ top-left origin, using contentView's client NSSize
  * returns: abs screen position w/ bottom-left origin
  */
-- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p
 {
     NSView* mView = [self contentView];
     NSRect mViewFrame = [mView frame]; 
-    int totalHeight = mViewFrame.size.height + cachedInsets[2] + cachedInsets[3]; // height + insets[top+bottom]
+    return [self newtAbsClientTLWinPos2AbsBLScreenPos: p size: mViewFrame.size];
+}
+
+/**
+ * p abs screen position of client-area pos w/ top-left origin, using given client NSSize
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz
+{
+    int totalHeight = nsz.height + cachedInsets[3]; // height + insets.bottom
+
+    DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: given %d/%d %dx%d, insets bottom %d -> totalHeight %d\n", 
+        (int)p.x, (int)p.y, (int)nsz.width, (int)nsz.height, cachedInsets[3], totalHeight);
 
     NSScreen* screen = [self screen];
     NSRect screenFrame = [screen frame];
 
-    return NSMakePoint(screenFrame.origin.x + p.x + cachedInsets[0],
-                       screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight);
+    DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: screen %d/%d %dx%d\n", 
+        (int)screenFrame.origin.x, (int)screenFrame.origin.y, (int)screenFrame.size.width, (int)screenFrame.size.height);
+
+    NSPoint r = NSMakePoint(screenFrame.origin.x + p.x,
+                            screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight);
+
+    DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: result %d/%d\n", (int)r.x, (int)r.y); 
+
+    return r;
 }
 
 /**
  * p rel client window position w/ top-left origin
  * returns: abs screen position w/ bottom-left origin
  */
-- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p
+- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p
 {
     NSRect winFrame = [self frame];
 
@@ -488,6 +591,12 @@ static jmethodID windowRepaintID = NULL;
                        winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view
 }
 
+- (NSSize) newtClientSize2TLSize: (NSSize) nsz
+{
+    NSSize topSZ = { nsz.width, nsz.height + cachedInsets[2] + cachedInsets[3] }; // height + insets.top + insets.bottom
+    return topSZ;
+}
+
 /**
  * y-flips input / output
  * p rel client window position w/ top-left origin
@@ -599,18 +708,18 @@ static jint mods2JavaMods(NSUInteger mods)
     return javaMods;
 }
 
-- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType
+- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType
 {
-    jint keyCode = (jint) [event keyCode];
+    jshort keyCode = (jshort) [event keyCode];
     NSString* chars = [event charactersIgnoringModifiers];
     NSUInteger mods = [event modifierFlags];
     [self sendKeyEvent: keyCode characters: chars modifiers: mods eventType: evType];
 }
 
-- (void) sendKeyEvent: (jint) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jint) evType
+- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType
 {
     NSView* nsview = [self contentView];
-    if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+    if( ! [nsview isKindOfClass:[NewtView class]] ) {
         return;
     }
     NewtView* view = (NewtView *) nsview;
@@ -621,7 +730,7 @@ static jint mods2JavaMods(NSUInteger mods)
     }
     int shallBeDetached = 0;
     JavaVM *jvmHandle = [view getJVMHandle];
-    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
     if(NULL==env) {
         DBG_PRINT("sendKeyEvent: null JNIEnv\n");
         return;
@@ -635,42 +744,33 @@ static jint mods2JavaMods(NSUInteger mods)
         // printable chars
         for (i = 0; i < len; i++) {
             // Note: the key code in the NSEvent does not map to anything we can use
-            jchar keyChar = (jchar) [chars characterAtIndex: i];
+            UniChar keyChar = (UniChar) [chars characterAtIndex: i];
+            UniChar keySymChar = CKCH_CharForKeyCode(keyCode);
 
-            DBG_PRINT("sendKeyEvent: %d/%d char 0x%X, code 0x%X\n", i, len, (int)keyChar, (int)keyCode);
+            DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar, (int)keySymChar);
 
-            #ifdef USE_SENDIO_DIRECT
-            (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID,
-                                   evType, javaMods, keyCode, keyChar);
-            #else
             (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
-                                   evType, javaMods, keyCode, keyChar);
-            #endif
+                                   evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar);
         }
     } else {
         // non-printable chars
-        jchar keyChar = (jchar) -1;
+        jchar keyChar = (jchar) 0;
 
         DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode);
 
-        #ifdef USE_SENDIO_DIRECT
-        (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID,
-                               evType, javaMods, keyCode, keyChar);
-        #else
         (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
-                               evType, javaMods, keyCode, keyChar);
-        #endif
+                               evType, javaMods, keyCode, keyChar, keyChar);
     }
 
-    if (shallBeDetached) {
+    /* if (shallBeDetached) {
         (*jvmHandle)->DetachCurrentThread(jvmHandle);
-    }
+    } */
 }
 
-- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType
+- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType
 {
     NSView* nsview = [self contentView];
-    if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+    if( ! [nsview isKindOfClass:[NewtView class]] ) {
         return;
     }
     NewtView* view = (NewtView *) nsview;
@@ -681,20 +781,21 @@ static jint mods2JavaMods(NSUInteger mods)
     }
     int shallBeDetached = 0;
     JavaVM *jvmHandle = [view getJVMHandle];
-    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
     if(NULL==env) {
         DBG_PRINT("sendMouseEvent: null JNIEnv\n");
         return;
     }
-    jint javaMods = mods2JavaMods([event modifierFlags]);
+    jint javaMods[] = { 0 } ;
+    javaMods[0] = mods2JavaMods([event modifierFlags]);
 
     // convert to 1-based button number (or use zero if no button is involved)
     // TODO: detect mouse button when mouse wheel scrolled  
-    jint javaButtonNum = 0;
-    jint scrollDeltaY = 0;
+    jshort javaButtonNum = 0;
+    jfloat scrollDeltaY = 0.0f;
     switch ([event type]) {
     case NSScrollWheel: {
-        scrollDeltaY = GetDeltaY(event, javaMods);
+        scrollDeltaY = GetDelta(event, javaMods);
         javaButtonNum = 1;
         break;
     }
@@ -725,28 +826,21 @@ static jint mods2JavaMods(NSUInteger mods)
 
     NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]];
 
-    #ifdef USE_SENDIO_DIRECT
-    (*env)->CallVoidMethod(env, javaWindowObject, sendMouseEventID,
-                           evType, javaMods,
-                           (jint) location.x, (jint) location.y,
-                           javaButtonNum, scrollDeltaY);
-    #else
     (*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE,
-                           evType, javaMods,
+                           evType, javaMods[0],
                            (jint) location.x, (jint) location.y,
                            javaButtonNum, scrollDeltaY);
-    #endif
 
-    if (shallBeDetached) {
+    /* if (shallBeDetached) {
         (*jvmHandle)->DetachCurrentThread(jvmHandle);
-    }
+    } */
 }
 
 - (void) focusChanged: (BOOL) gained
 {
     DBG_PRINT( "focusChanged: gained %d\n", gained);
     NSView* nsview = [self contentView];
-    if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+    if( ! [nsview isKindOfClass:[NewtView class]] ) {
         return;
     }
     NewtView* view = (NewtView *) nsview;
@@ -757,7 +851,7 @@ static jint mods2JavaMods(NSUInteger mods)
     }
     int shallBeDetached = 0;
     JavaVM *jvmHandle = [view getJVMHandle];
-    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
     if(NULL==env) {
         DBG_PRINT("focusChanged: null JNIEnv\n");
         return;
@@ -765,9 +859,9 @@ static jint mods2JavaMods(NSUInteger mods)
 
     (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
 
-    if (shallBeDetached) {
+    /* if (shallBeDetached) {
         (*jvmHandle)->DetachCurrentThread(jvmHandle);
-    }
+    } */
 }
 
 - (BOOL) becomeFirstResponder
@@ -822,13 +916,12 @@ static jint mods2JavaMods(NSUInteger mods)
 
 - (void) keyDown: (NSEvent*) theEvent
 {
-    [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED];
+    [self sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_PRESSED];
 }
 
 - (void) keyUp: (NSEvent*) theEvent
 {
-    [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED];
-    [self sendKeyEvent: theEvent eventType: EVENT_KEY_TYPED];
+    [self sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_RELEASED];
 }
 
 #define kVK_Shift     0x38
@@ -840,11 +933,10 @@ static jint mods2JavaMods(NSUInteger mods)
 {
     if ( NO == modsDown[keyIdx] && 0 != ( mods & keyMask ) )  {
         modsDown[keyIdx] = YES;
-        [self sendKeyEvent: keyCode characters: NULL modifiers: mods|keyMask eventType: EVENT_KEY_PRESSED];
+        [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_PRESSED];
     } else if ( YES == modsDown[keyIdx] && 0 == ( mods & keyMask ) )  {
         modsDown[keyIdx] = NO;
-        [self sendKeyEvent: keyCode characters: NULL modifiers: mods|keyMask eventType: EVENT_KEY_RELEASED];
-        [self sendKeyEvent: keyCode characters: NULL modifiers: mods|keyMask eventType: EVENT_KEY_TYPED];
+        [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_RELEASED];
     }
 }
 
@@ -946,43 +1038,42 @@ static jint mods2JavaMods(NSUInteger mods)
 
 - (void)windowDidResize: (NSNotification*) notification
 {
-    NSView* nsview = [self contentView];
-    if( ! [nsview isMemberOfClass:[NewtView class]] ) {
-        return;
-    }
-    NewtView* view = (NewtView *) nsview;
-    jobject javaWindowObject = [view getJavaWindowObject];
-    if (javaWindowObject == NULL) {
-        DBG_PRINT("windowDidResize: null javaWindowObject\n");
-        return;
-    }
+    JNIEnv* env = NULL;
+    jobject javaWindowObject = NULL;
     int shallBeDetached = 0;
-    JavaVM *jvmHandle = [view getJVMHandle];
-    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
-    if(NULL==env) {
-        DBG_PRINT("windowDidResize: null JNIEnv\n");
-        return;
+    JavaVM *jvmHandle = NULL;
+
+    NSView* nsview = [self contentView];
+    if( [nsview isKindOfClass:[NewtView class]] ) {
+        NewtView* view = (NewtView *) nsview;
+        javaWindowObject = [view getJavaWindowObject];
+        if (javaWindowObject != NULL) {
+            jvmHandle = [view getJVMHandle];
+            env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
+        }
     }
 
     // update insets on every window resize for lack of better hook place
-    [self updateInsets: env];
+    [self updateInsets: env jwin:javaWindowObject];
 
-    NSRect frameRect = [self frame];
-    NSRect contentRect = [self contentRectForFrameRect: frameRect];
+    if( NULL != env && NULL != javaWindowObject ) {
+        NSRect frameRect = [self frame];
+        NSRect contentRect = [self contentRectForFrameRect: frameRect];
 
-    (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE,
-                           (jint) contentRect.size.width,
-                           (jint) contentRect.size.height, JNI_FALSE);
+        (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE,
+                               (jint) contentRect.size.width,
+                               (jint) contentRect.size.height, JNI_FALSE);
 
-    if (shallBeDetached) {
-        (*jvmHandle)->DetachCurrentThread(jvmHandle);
+        /* if (shallBeDetached) {
+            (*jvmHandle)->DetachCurrentThread(jvmHandle);
+        } */
     }
 }
 
 - (void)windowDidMove: (NSNotification*) notification
 {
     NSView* nsview = [self contentView];
-    if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+    if( ! [nsview isKindOfClass:[NewtView class]] ) {
         return;
     }
     NewtView* view = (NewtView *) nsview;
@@ -993,7 +1084,7 @@ static jint mods2JavaMods(NSUInteger mods)
     }
     int shallBeDetached = 0;
     JavaVM *jvmHandle = [view getJVMHandle];
-    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+    JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
     if(NULL==env) {
         DBG_PRINT("windowDidMove: null JNIEnv\n");
         return;
@@ -1003,9 +1094,9 @@ static jint mods2JavaMods(NSUInteger mods)
     p0 = [self getLocationOnScreen: p0];
     (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_FALSE, (jint) p0.x, (jint) p0.y);
 
-    if (shallBeDetached) {
+    /* if (shallBeDetached) {
         (*jvmHandle)->DetachCurrentThread(jvmHandle);
-    }
+    } */
 }
 
 - (BOOL)windowShouldClose: (id) sender
@@ -1026,7 +1117,7 @@ static jint mods2JavaMods(NSUInteger mods)
     [self cursorHide: NO];
 
     NSView* nsview = [self contentView];
-    if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+    if( ! [nsview isKindOfClass:[NewtView class]] ) {
         return NO;
     }
     NewtView* view = (NewtView *) nsview;
@@ -1040,7 +1131,7 @@ static jint mods2JavaMods(NSUInteger mods)
         }
         int shallBeDetached = 0;
         JavaVM *jvmHandle = [view getJVMHandle];
-        JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+        JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
         if(NULL==env) {
             DBG_PRINT("windowWillClose: null JNIEnv\n");
             return NO;
@@ -1053,9 +1144,9 @@ static jint mods2JavaMods(NSUInteger mods)
             [view setDestroyNotifySent: false];
         }
 
-        if (shallBeDetached) {
+        /* if (shallBeDetached) {
             (*jvmHandle)->DetachCurrentThread(jvmHandle);
-        }
+        } */
         DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed);
     } else {
         DBG_PRINT( "*************** windowWillClose (skip)\n");
@@ -1065,3 +1156,4 @@ static jint mods2JavaMods(NSUInteger mods)
 }
 
 @end
+
diff --git a/src/newt/native/ScreenMode.h b/src/newt/native/ScreenMode.h
index bb78291..110f1c4 100644
--- a/src/newt/native/ScreenMode.h
+++ b/src/newt/native/ScreenMode.h
@@ -33,12 +33,17 @@
 #ifndef _SCREEN_MODE_H
 #define _SCREEN_MODE_H
 
-#define NUM_RESOLUTION_PROPERTIES   2   /* width, height */
-#define NUM_SURFACE_SIZE_PROPERTIES 1   /* bpp */
-#define NUM_MONITOR_MODE_PROPERTIES 3   /* ScreenSizeMM[width, height], refresh-rate */
-#define NUM_SCREEN_MODE_PROPERTIES  1   /* rotation */
+#define NUM_RESOLUTION_PROPERTIES     2   /* width, height */
+#define NUM_SURFACE_SIZE_PROPERTIES   1   /* bpp */
+#define NUM_SIZEANDRATE_PROPERTIES    2   /* refresh-rate, flags */
+#define NUM_MONITOR_MODE_PROPERTIES   2   /* id, rotation */
 
-#define NUM_SCREEN_MODE_PROPERTIES_ALL  8   /* count + the above */
+#define NUM_MONITOR_MODE_PROPERTIES_ALL  8  /* count + the above */
+
+#define MIN_MONITOR_DEVICE_PROPERTIES 11   /* count + id, ScreenSizeMM[width, height], rotated Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+ */
+
+#define FLAG_INTERLACE      ( 1 << 0 )
+#define FLAG_DOUBLESCAN     ( 1 << 1 )
 
 #endif
 
diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h
index 4755c4f..d9ee5fd 100644
--- a/src/newt/native/Window.h
+++ b/src/newt/native/Window.h
@@ -38,8 +38,9 @@
 #define FLAG_HAS_PARENT             ( 1 <<  8 )
 #define FLAG_IS_UNDECORATED         ( 1 <<  9 )
 #define FLAG_IS_FULLSCREEN          ( 1 << 10 )
-#define FLAG_IS_ALWAYSONTOP         ( 1 << 11 )
-#define FLAG_IS_VISIBLE             ( 1 << 12 )
+#define FLAG_IS_FULLSCREEN_SPAN     ( 1 << 11 )
+#define FLAG_IS_ALWAYSONTOP         ( 1 << 12 )
+#define FLAG_IS_VISIBLE             ( 1 << 13 )
 
 #define TST_FLAG_CHANGE_PARENTING(f)   ( 0 != ( (f) & FLAG_CHANGE_PARENTING ) ) 
 #define TST_FLAG_CHANGE_DECORATION(f)  ( 0 != ( (f) & FLAG_CHANGE_DECORATION ) ) 
@@ -47,11 +48,11 @@
 #define TST_FLAG_CHANGE_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_CHANGE_ALWAYSONTOP ) ) 
 #define TST_FLAG_CHANGE_VISIBILITY(f)  ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) ) 
 
-#define TST_FLAG_HAS_PARENT(f)        ( 0 != ( (f) & FLAG_HAS_PARENT ) ) 
-#define TST_FLAG_IS_UNDECORATED(f)    ( 0 != ( (f) & FLAG_IS_UNDECORATED ) ) 
-#define TST_FLAG_IS_FULLSCREEN(f)     ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) ) 
-#define TST_FLAG_IS_FULLSCREEN(f)     ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) ) 
-#define TST_FLAG_IS_ALWAYSONTOP(f)    ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) ) 
-#define TST_FLAG_IS_VISIBLE(f)        ( 0 != ( (f) & FLAG_IS_VISIBLE ) ) 
+#define TST_FLAG_HAS_PARENT(f)         ( 0 != ( (f) & FLAG_HAS_PARENT ) ) 
+#define TST_FLAG_IS_UNDECORATED(f)     ( 0 != ( (f) & FLAG_IS_UNDECORATED ) ) 
+#define TST_FLAG_IS_FULLSCREEN(f)      ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) ) 
+#define TST_FLAG_IS_FULLSCREEN_SPAN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN_SPAN ) ) 
+#define TST_FLAG_IS_ALWAYSONTOP(f)     ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) ) 
+#define TST_FLAG_IS_VISIBLE(f)         ( 0 != ( (f) & FLAG_IS_VISIBLE ) ) 
 
 #endif
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index e3d5cff..ac0ebf0 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -53,9 +53,13 @@
 #define WM_MOUSEWHEEL                   0x020A
 #endif //WM_MOUSEWHEEL
 
-#ifndef WHEEL_DELTA
-#define WHEEL_DELTA                     120
-#endif //WHEEL_DELTA
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL                  0x020E
+#endif //WM_MOUSEHWHEEL
+
+#ifndef WHEEL_DELTAf
+#define WHEEL_DELTAf                    (120.0f)
+#endif //WHEEL_DELTAf
 
 #ifndef WHEEL_PAGESCROLL
 #define WHEEL_PAGESCROLL                (UINT_MAX)
@@ -64,6 +68,23 @@
 #ifndef GET_WHEEL_DELTA_WPARAM  // defined for (_WIN32_WINNT >= 0x0500)
 #define GET_WHEEL_DELTA_WPARAM(wParam)  ((short)HIWORD(wParam))
 #endif
+#ifndef GET_KEYSTATE_WPARAM
+#define GET_KEYSTATE_WPARAM(wParam)  ((short)LOWORD(wParam))
+#endif
+
+#ifndef WM_HSCROLL
+#define WM_HSCROLL             0x0114
+#endif
+#ifndef WM_VSCROLL
+#define WM_VSCROLL             0x0115
+#endif
+
+#ifndef WH_MOUSE
+#define WH_MOUSE 7
+#endif
+#ifndef WH_MOUSE_LL
+#define WH_MOUSE_LL 14
+#endif
 
 #ifndef MONITOR_DEFAULTTONULL
 #define MONITOR_DEFAULTTONULL 0
@@ -80,6 +101,9 @@
 #ifndef DISPLAY_DEVICE_ACTIVE
 #define DISPLAY_DEVICE_ACTIVE 0x00000001
 #endif
+#ifndef DM_INTERLACED
+#define DM_INTERLACED       2
+#endif
 
 #include "jogamp_newt_driver_windows_DisplayDriver.h"
 #include "jogamp_newt_driver_windows_ScreenDriver.h"
@@ -111,9 +135,7 @@ static jmethodID focusChangedID = NULL;
 static jmethodID visibleChangedID = NULL;
 static jmethodID windowDestroyNotifyID = NULL;
 static jmethodID windowRepaintID = NULL;
-static jmethodID enqueueMouseEventID = NULL;
 static jmethodID sendMouseEventID = NULL;
-static jmethodID enqueueKeyEventID = NULL;
 static jmethodID sendKeyEventID = NULL;
 static jmethodID requestFocusID = NULL;
 
@@ -122,348 +144,307 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd);
 typedef struct {
     JNIEnv* jenv;
     jobject jinstance;
+    /** Tristate: -1 HIDE, 0 NOP, 1 SHOW */
+    int setPointerVisible;
 } WindowUserData;
     
 typedef struct {
-    UINT javaKey;
-    UINT windowsKey;
+    USHORT javaKey;
+    USHORT windowsKey;
+    USHORT windowsScanCodeUS;
 } KeyMapEntry;
 
 // Static table, arranged more or less spatially.
 static KeyMapEntry keyMapTable[] = {
     // Modifier keys
-    {J_VK_CAPS_LOCK,        VK_CAPITAL},
-    {J_VK_SHIFT,            VK_SHIFT},
-    {J_VK_CONTROL,          VK_CONTROL},
-    {J_VK_ALT,              VK_MENU},
-    {J_VK_NUM_LOCK,         VK_NUMLOCK},
+    {J_VK_CAPS_LOCK,        VK_CAPITAL, 0},
+    {J_VK_SHIFT,            VK_SHIFT, 0},
+    {J_VK_SHIFT,            VK_LSHIFT, 0},
+    {J_VK_SHIFT,            VK_RSHIFT, 0},
+    {J_VK_CONTROL,          VK_CONTROL, 0},
+    {J_VK_CONTROL,          VK_LCONTROL, 0},
+    {J_VK_CONTROL,          VK_RCONTROL, 0},
+    {J_VK_ALT,              VK_MENU, 0},
+    {J_VK_ALT,              VK_LMENU, 0},
+    {J_VK_ALT_GRAPH,        VK_RMENU, 0},
+    {J_VK_NUM_LOCK,         VK_NUMLOCK, 0},
 
     // Miscellaneous Windows keys
-    {J_VK_WINDOWS,          VK_LWIN},
-    {J_VK_WINDOWS,          VK_RWIN},
-    {J_VK_CONTEXT_MENU,     VK_APPS},
+    {J_VK_WINDOWS,          VK_LWIN, 0},
+    {J_VK_WINDOWS,          VK_RWIN, 0},
+    {J_VK_CONTEXT_MENU,     VK_APPS, 0},
 
     // Alphabet
-    {J_VK_A,                'A'},
-    {J_VK_B,                'B'},
-    {J_VK_C,                'C'},
-    {J_VK_D,                'D'},
-    {J_VK_E,                'E'},
-    {J_VK_F,                'F'},
-    {J_VK_G,                'G'},
-    {J_VK_H,                'H'},
-    {J_VK_I,                'I'},
-    {J_VK_J,                'J'},
-    {J_VK_K,                'K'},
-    {J_VK_L,                'L'},
-    {J_VK_M,                'M'},
-    {J_VK_N,                'N'},
-    {J_VK_O,                'O'},
-    {J_VK_P,                'P'},
-    {J_VK_Q,                'Q'},
-    {J_VK_R,                'R'},
-    {J_VK_S,                'S'},
-    {J_VK_T,                'T'},
-    {J_VK_U,                'U'},
-    {J_VK_V,                'V'},
-    {J_VK_W,                'W'},
-    {J_VK_X,                'X'},
-    {J_VK_Y,                'Y'},
-    {J_VK_Z,                'Z'},
-    {J_VK_0,                '0'},
-    {J_VK_1,                '1'},
-    {J_VK_2,                '2'},
-    {J_VK_3,                '3'},
-    {J_VK_4,                '4'},
-    {J_VK_5,                '5'},
-    {J_VK_6,                '6'},
-    {J_VK_7,                '7'},
-    {J_VK_8,                '8'},
-    {J_VK_9,                '9'},
-    {J_VK_ENTER,            VK_RETURN},
-    {J_VK_SPACE,            VK_SPACE},
-    {J_VK_BACK_SPACE,       VK_BACK},
-    {J_VK_TAB,              VK_TAB},
-    {J_VK_ESCAPE,           VK_ESCAPE},
-    {J_VK_INSERT,           VK_INSERT},
-    {J_VK_DELETE,           VK_DELETE},
-    {J_VK_HOME,             VK_HOME},
-    {J_VK_END,              VK_END},
-    {J_VK_PAGE_UP,          VK_PRIOR},
-    {J_VK_PAGE_DOWN,        VK_NEXT},
-    {J_VK_CLEAR,            VK_CLEAR}, // NumPad 5
+    {J_VK_A,                'A', 0},
+    {J_VK_B,                'B', 0},
+    {J_VK_C,                'C', 0},
+    {J_VK_D,                'D', 0},
+    {J_VK_E,                'E', 0},
+    {J_VK_F,                'F', 0},
+    {J_VK_G,                'G', 0},
+    {J_VK_H,                'H', 0},
+    {J_VK_I,                'I', 0},
+    {J_VK_J,                'J', 0},
+    {J_VK_K,                'K', 0},
+    {J_VK_L,                'L', 0},
+    {J_VK_M,                'M', 0},
+    {J_VK_N,                'N', 0},
+    {J_VK_O,                'O', 0},
+    {J_VK_P,                'P', 0},
+    {J_VK_Q,                'Q', 0},
+    {J_VK_R,                'R', 0},
+    {J_VK_S,                'S', 0},
+    {J_VK_T,                'T', 0},
+    {J_VK_U,                'U', 0},
+    {J_VK_V,                'V', 0},
+    {J_VK_W,                'W', 0},
+    {J_VK_X,                'X', 0},
+    {J_VK_Y,                'Y', 0},
+    {J_VK_Z,                'Z', 0},
+    {J_VK_0,                '0', 0},
+    {J_VK_1,                '1', 0},
+    {J_VK_2,                '2', 0},
+    {J_VK_3,                '3', 0},
+    {J_VK_4,                '4', 0},
+    {J_VK_5,                '5', 0},
+    {J_VK_6,                '6', 0},
+    {J_VK_7,                '7', 0},
+    {J_VK_8,                '8', 0},
+    {J_VK_9,                '9', 0},
+    {J_VK_ENTER,            VK_RETURN, 0},
+    {J_VK_SPACE,            VK_SPACE, 0},
+    {J_VK_BACK_SPACE,       VK_BACK, 0},
+    {J_VK_TAB,              VK_TAB, 0},
+    {J_VK_ESCAPE,           VK_ESCAPE, 0},
+    {J_VK_INSERT,           VK_INSERT, 0},
+    {J_VK_DELETE,           VK_DELETE, 0},
+    {J_VK_HOME,             VK_HOME, 0},
+    // {J_VK_BEGIN,            VK_BEGIN, 0}, // not mapped
+    {J_VK_END,              VK_END, 0},
+    {J_VK_PAGE_UP,          VK_PRIOR, 0},
+    {J_VK_PAGE_DOWN,        VK_NEXT, 0},
+    {J_VK_CLEAR,            VK_CLEAR, 0}, // NumPad 5
 
     // NumPad with NumLock off & extended arrows block (triangular)
-    {J_VK_LEFT,             VK_LEFT},
-    {J_VK_RIGHT,            VK_RIGHT},
-    {J_VK_UP,               VK_UP},
-    {J_VK_DOWN,             VK_DOWN},
+    {J_VK_LEFT,             VK_LEFT, 0},
+    {J_VK_RIGHT,            VK_RIGHT, 0},
+    {J_VK_UP,               VK_UP, 0},
+    {J_VK_DOWN,             VK_DOWN, 0},
 
     // NumPad with NumLock on: numbers
-    {J_VK_NUMPAD0,          VK_NUMPAD0},
-    {J_VK_NUMPAD1,          VK_NUMPAD1},
-    {J_VK_NUMPAD2,          VK_NUMPAD2},
-    {J_VK_NUMPAD3,          VK_NUMPAD3},
-    {J_VK_NUMPAD4,          VK_NUMPAD4},
-    {J_VK_NUMPAD5,          VK_NUMPAD5},
-    {J_VK_NUMPAD6,          VK_NUMPAD6},
-    {J_VK_NUMPAD7,          VK_NUMPAD7},
-    {J_VK_NUMPAD8,          VK_NUMPAD8},
-    {J_VK_NUMPAD9,          VK_NUMPAD9},
+    {J_VK_NUMPAD0,          VK_NUMPAD0, 0},
+    {J_VK_NUMPAD1,          VK_NUMPAD1, 0},
+    {J_VK_NUMPAD2,          VK_NUMPAD2, 0},
+    {J_VK_NUMPAD3,          VK_NUMPAD3, 0},
+    {J_VK_NUMPAD4,          VK_NUMPAD4, 0},
+    {J_VK_NUMPAD5,          VK_NUMPAD5, 0},
+    {J_VK_NUMPAD6,          VK_NUMPAD6, 0},
+    {J_VK_NUMPAD7,          VK_NUMPAD7, 0},
+    {J_VK_NUMPAD8,          VK_NUMPAD8, 0},
+    {J_VK_NUMPAD9,          VK_NUMPAD9, 0},
 
     // NumPad with NumLock on
-    {J_VK_MULTIPLY,         VK_MULTIPLY},
-    {J_VK_ADD,              VK_ADD},
-    {J_VK_SEPARATOR,        VK_SEPARATOR},
-    {J_VK_SUBTRACT,         VK_SUBTRACT},
-    {J_VK_DECIMAL,          VK_DECIMAL},
-    {J_VK_DIVIDE,           VK_DIVIDE},
+    {J_VK_MULTIPLY,         VK_MULTIPLY, 0},
+    {J_VK_ADD,              VK_ADD, 0},
+    {J_VK_SEPARATOR,        VK_SEPARATOR, 0},
+    {J_VK_SUBTRACT,         VK_SUBTRACT, 0},
+    {J_VK_DECIMAL,          VK_DECIMAL, 0},
+    {J_VK_DIVIDE,           VK_DIVIDE, 0},
 
     // Functional keys
-    {J_VK_F1,               VK_F1},
-    {J_VK_F2,               VK_F2},
-    {J_VK_F3,               VK_F3},
-    {J_VK_F4,               VK_F4},
-    {J_VK_F5,               VK_F5},
-    {J_VK_F6,               VK_F6},
-    {J_VK_F7,               VK_F7},
-    {J_VK_F8,               VK_F8},
-    {J_VK_F9,               VK_F9},
-    {J_VK_F10,              VK_F10},
-    {J_VK_F11,              VK_F11},
-    {J_VK_F12,              VK_F12},
-    {J_VK_F13,              VK_F13},
-    {J_VK_F14,              VK_F14},
-    {J_VK_F15,              VK_F15},
-    {J_VK_F16,              VK_F16},
-    {J_VK_F17,              VK_F17},
-    {J_VK_F18,              VK_F18},
-    {J_VK_F19,              VK_F19},
-    {J_VK_F20,              VK_F20},
-    {J_VK_F21,              VK_F21},
-    {J_VK_F22,              VK_F22},
-    {J_VK_F23,              VK_F23},
-    {J_VK_F24,              VK_F24},
-
-    {J_VK_PRINTSCREEN,      VK_SNAPSHOT},
-    {J_VK_SCROLL_LOCK,      VK_SCROLL},
-    {J_VK_PAUSE,            VK_PAUSE},
-    {J_VK_CANCEL,           VK_CANCEL},
-    {J_VK_HELP,             VK_HELP},
+    {J_VK_F1,               VK_F1, 0},
+    {J_VK_F2,               VK_F2, 0},
+    {J_VK_F3,               VK_F3, 0},
+    {J_VK_F4,               VK_F4, 0},
+    {J_VK_F5,               VK_F5, 0},
+    {J_VK_F6,               VK_F6, 0},
+    {J_VK_F7,               VK_F7, 0},
+    {J_VK_F8,               VK_F8, 0},
+    {J_VK_F9,               VK_F9, 0},
+    {J_VK_F10,              VK_F10, 0},
+    {J_VK_F11,              VK_F11, 0},
+    {J_VK_F12,              VK_F12, 0},
+    {J_VK_F13,              VK_F13, 0},
+    {J_VK_F14,              VK_F14, 0},
+    {J_VK_F15,              VK_F15, 0},
+    {J_VK_F16,              VK_F16, 0},
+    {J_VK_F17,              VK_F17, 0},
+    {J_VK_F18,              VK_F18, 0},
+    {J_VK_F19,              VK_F19, 0},
+    {J_VK_F20,              VK_F20, 0},
+    {J_VK_F21,              VK_F21, 0},
+    {J_VK_F22,              VK_F22, 0},
+    {J_VK_F23,              VK_F23, 0},
+    {J_VK_F24,              VK_F24, 0},
+
+    {J_VK_PRINTSCREEN,      VK_SNAPSHOT, 0},
+    {J_VK_SCROLL_LOCK,      VK_SCROLL, 0},
+    {J_VK_PAUSE,            VK_PAUSE, 0},
+    {J_VK_CANCEL,           VK_CANCEL, 0},
+    {J_VK_HELP,             VK_HELP, 0},
+
+    // Since we unify mappings via US kbd layout .. this is valid:
+    {J_VK_SEMICOLON,        VK_OEM_1, 0}, // US only ';:'
+    {J_VK_EQUALS,           VK_OEM_PLUS, 0}, // '=+'
+    {J_VK_COMMA,            VK_OEM_COMMA, 0}, // ',<'
+    {J_VK_MINUS,            VK_OEM_MINUS, 0}, // '-_'
+    {J_VK_PERIOD,           VK_OEM_PERIOD, 0}, // '.>'
+    {J_VK_SLASH,            VK_OEM_2, 0}, // US only '/?'
+    {J_VK_BACK_QUOTE,       VK_OEM_3, 0}, // US only '`~'
+    {J_VK_OPEN_BRACKET,     VK_OEM_4, 0}, // US only '[}'
+    {J_VK_BACK_SLASH,       VK_OEM_5, 0}, // US only '\|'
+    {J_VK_CLOSE_BRACKET,    VK_OEM_6, 0}, // US only ']}'
+    {J_VK_QUOTE,            VK_OEM_7, 0}, // US only ''"'
+    // {J_VK_????,       VK_OEM_8, 0}, // varies ..
+    // {J_VK_????,       VK_OEM_102, 0}, // angle-bracket or backslash key on RT 102-key kbd
 
     // Japanese
 /*
-    {J_VK_CONVERT,          VK_CONVERT},
-    {J_VK_NONCONVERT,       VK_NONCONVERT},
-    {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI},
-    {J_VK_ALPHANUMERIC,     VK_DBE_ALPHANUMERIC},
-    {J_VK_KATAKANA,         VK_DBE_KATAKANA},
-    {J_VK_HIRAGANA,         VK_DBE_HIRAGANA},
-    {J_VK_FULL_WIDTH,       VK_DBE_DBCSCHAR},
-    {J_VK_HALF_WIDTH,       VK_DBE_SBCSCHAR},
-    {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN},
+    {J_VK_CONVERT,          VK_CONVERT, 0},
+    {J_VK_NONCONVERT,       VK_NONCONVERT, 0},
+    {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI, 0},
+    {J_VK_ALPHANUMERIC,     VK_DBE_ALPHANUMERIC, 0},
+    {J_VK_KATAKANA,         VK_DBE_KATAKANA, 0},
+    {J_VK_HIRAGANA,         VK_DBE_HIRAGANA, 0},
+    {J_VK_FULL_WIDTH,       VK_DBE_DBCSCHAR, 0},
+    {J_VK_HALF_WIDTH,       VK_DBE_SBCSCHAR, 0},
+    {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN, 0},
 */
 
-    {J_VK_UNDEFINED,        0}
+    {J_VK_UNDEFINED,        0, 0}
 };
 
-/*
-Dynamic mapping table for OEM VK codes.  This table is refilled
-by BuildDynamicKeyMapTable when keyboard layout is switched.
-(see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values).
-*/
-typedef struct {
-    // OEM VK codes known in advance
-    UINT windowsKey;
-    // depends on input langauge (kbd layout)
-    UINT javaKey;
-} DynamicKeyMapEntry;
-
-static DynamicKeyMapEntry dynamicKeyMapTable[] = {
-    {0x00BA,  J_VK_UNDEFINED}, // VK_OEM_1
-    {0x00BB,  J_VK_UNDEFINED}, // VK_OEM_PLUS
-    {0x00BC,  J_VK_UNDEFINED}, // VK_OEM_COMMA
-    {0x00BD,  J_VK_UNDEFINED}, // VK_OEM_MINUS
-    {0x00BE,  J_VK_UNDEFINED}, // VK_OEM_PERIOD
-    {0x00BF,  J_VK_UNDEFINED}, // VK_OEM_2
-    {0x00C0,  J_VK_UNDEFINED}, // VK_OEM_3
-    {0x00DB,  J_VK_UNDEFINED}, // VK_OEM_4
-    {0x00DC,  J_VK_UNDEFINED}, // VK_OEM_5
-    {0x00DD,  J_VK_UNDEFINED}, // VK_OEM_6
-    {0x00DE,  J_VK_UNDEFINED}, // VK_OEM_7
-    {0x00DF,  J_VK_UNDEFINED}, // VK_OEM_8
-    {0x00E2,  J_VK_UNDEFINED}, // VK_OEM_102
-    {0, 0}
-};
-
-// Auxiliary tables used to fill the above dynamic table.  We first
-// find the character for the OEM VK code using ::MapVirtualKey and
-// then go through these auxiliary tables to map it to Java VK code.
+#ifndef KLF_ACTIVATE
+    #define KLF_ACTIVATE 0x00000001
+#endif
+#ifndef MAPVK_VK_TO_VSC
+    #define MAPVK_VK_TO_VSC 0
+#endif
+#ifndef MAPVK_VSC_TO_VK
+    #define MAPVK_VSC_TO_VK 1
+#endif
+#ifndef MAPVK_VK_TO_CHAR
+    #define MAPVK_VK_TO_CHAR 2
+#endif
+#ifndef MAPVK_VSC_TO_VK_EX
+    #define MAPVK_VSC_TO_VK_EX 3
+#endif
+#ifndef MAPVK_VK_TO_VSC_EX
+    #define MAPVK_VK_TO_VSC_EX 4
+#endif
 
-typedef struct {
-    WCHAR c;
-    UINT  javaKey;
-} CharToVKEntry;
-
-static const CharToVKEntry charToVKTable[] = {
-    {L'!',   J_VK_EXCLAMATION_MARK},
-    {L'"',   J_VK_QUOTEDBL},
-    {L'#',   J_VK_NUMBER_SIGN},
-    {L'$',   J_VK_DOLLAR},
-    {L'&',   J_VK_AMPERSAND},
-    {L'\'',  J_VK_QUOTE},
-    {L'(',   J_VK_LEFT_PARENTHESIS},
-    {L')',   J_VK_RIGHT_PARENTHESIS},
-    {L'*',   J_VK_ASTERISK},
-    {L'+',   J_VK_PLUS},
-    {L',',   J_VK_COMMA},
-    {L'-',   J_VK_MINUS},
-    {L'.',   J_VK_PERIOD},
-    {L'/',   J_VK_SLASH},
-    {L':',   J_VK_COLON},
-    {L';',   J_VK_SEMICOLON},
-    {L'<',   J_VK_LESS},
-    {L'=',   J_VK_EQUALS},
-    {L'>',   J_VK_GREATER},
-    {L'@',   J_VK_AT},
-    {L'[',   J_VK_OPEN_BRACKET},
-    {L'\\',  J_VK_BACK_SLASH},
-    {L']',   J_VK_CLOSE_BRACKET},
-    {L'^',   J_VK_CIRCUMFLEX},
-    {L'_',   J_VK_UNDERSCORE},
-    {L'`',   J_VK_BACK_QUOTE},
-    {L'{',   J_VK_BRACELEFT},
-    {L'}',   J_VK_BRACERIGHT},
-    {0x00A1, J_VK_INVERTED_EXCLAMATION_MARK},
-    {0x20A0, J_VK_EURO_SIGN}, // ????
-    {0,0}
-};
+#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b))
 
-// For dead accents some layouts return ASCII punctuation, while some
-// return spacing accent chars, so both should be listed.  NB: MS docs
-// say that conversion routings return spacing accent character, not
-// combining.
-static const CharToVKEntry charToDeadVKTable[] = {
-    {L'`',   J_VK_DEAD_GRAVE},
-    {L'\'',  J_VK_DEAD_ACUTE},
-    {0x00B4, J_VK_DEAD_ACUTE},
-    {L'^',   J_VK_DEAD_CIRCUMFLEX},
-    {L'~',   J_VK_DEAD_TILDE},
-    {0x02DC, J_VK_DEAD_TILDE},
-    {0x00AF, J_VK_DEAD_MACRON},
-    {0x02D8, J_VK_DEAD_BREVE},
-    {0x02D9, J_VK_DEAD_ABOVEDOT},
-    {L'"',   J_VK_DEAD_DIAERESIS},
-    {0x00A8, J_VK_DEAD_DIAERESIS},
-    {0x02DA, J_VK_DEAD_ABOVERING},
-    {0x02DD, J_VK_DEAD_DOUBLEACUTE},
-    {0x02C7, J_VK_DEAD_CARON},            // aka hacek
-    {L',',   J_VK_DEAD_CEDILLA},
-    {0x00B8, J_VK_DEAD_CEDILLA},
-    {0x02DB, J_VK_DEAD_OGONEK},
-    {0x037A, J_VK_DEAD_IOTA},             // ASCII ???
-    {0x309B, J_VK_DEAD_VOICED_SOUND},
-    {0x309C, J_VK_DEAD_SEMIVOICED_SOUND},
-    {0,0}
-};
+static HKL kbdLayoutUS = 0;
+static const LPCSTR US_LAYOUT_NAME = "00000409";
 
-// ANSI CP identifiers are no longer than this
-#define MAX_ACP_STR_LEN 7
+static BYTE kbdState[256];
+static USHORT spaceScanCode;
 
-static void BuildDynamicKeyMapTable()
-{
+static void InitKeyMapTableScanCode(JNIEnv *env) {
     HKL hkl = GetKeyboardLayout(0);
-    // Will need this to reset layout after dead keys.
-    UINT spaceScanCode = MapVirtualKeyEx(VK_SPACE, 0, hkl);
-    DynamicKeyMapEntry *dynamic;
-
-    LANGID idLang = LOWORD(GetKeyboardLayout(0));
-    UINT codePage;
-    TCHAR strCodePage[MAX_ACP_STR_LEN];
-    // use the LANGID to create a LCID
-    LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
-    // get the ANSI code page associated with this locale
-    if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE,
-    strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
-    {
-        codePage = _ttoi(strCodePage);
-    } else {
-        codePage = GetACP();
+    int i;
+
+    kbdLayoutUS = LoadKeyboardLayout( US_LAYOUT_NAME, 0 /* ? KLF_ACTIVATE ? */ );
+    if( 0 == kbdLayoutUS ) {
+        int lastError = (int) GetLastError();
+        kbdLayoutUS = hkl; // use prev. layout .. well
+        STD_PRINT("Warning: NEWT Windows: LoadKeyboardLayout(US, ..) failed: winErr 0x%X %d\n", lastError, lastError);
     }
+    ActivateKeyboardLayout(hkl, 0);
 
-    // Entries in dynamic table that maps between Java VK and Windows
-    // VK are built in three steps:
-    //   1. Map windows VK to ANSI character (cannot map to unicode
-    //      directly, since ::ToUnicode is not implemented on win9x)
-    //   2. Convert ANSI char to Unicode char
-    //   3. Map Unicode char to Java VK via two auxilary tables.
+    spaceScanCode = MapVirtualKeyEx(VK_SPACE, MAPVK_VK_TO_VSC, hkl);
 
-    for (dynamic = dynamicKeyMapTable; dynamic->windowsKey != 0; ++dynamic)
-    {
-        char cbuf[2] = { '\0', '\0'};
-        WCHAR ucbuf[2] = { L'\0', L'\0' };
-        int nchars;
-        UINT scancode;
-        const CharToVKEntry *charMap;
-        int nconverted;
-        WCHAR uc;
-        BYTE kbdState[256];
-
-        // Defaults to J_VK_UNDEFINED
-        dynamic->javaKey = J_VK_UNDEFINED;
-
-        GetKeyboardState(kbdState);
-
-        kbdState[dynamic->windowsKey] |=  0x80; // Press the key.
-
-        // Unpress modifiers, since they are most likely pressed as
-        // part of the keyboard switching shortcut.
-        kbdState[VK_CONTROL] &= ~0x80;
-        kbdState[VK_SHIFT]   &= ~0x80;
-        kbdState[VK_MENU]    &= ~0x80;
-
-        scancode = MapVirtualKeyEx(dynamic->windowsKey, 0, hkl);
-        nchars = ToAsciiEx(dynamic->windowsKey, scancode, kbdState,
-                                 (WORD*)cbuf, 0, hkl);
-
-        // Auxiliary table used to map Unicode character to Java VK.
-        // Will assign a different table for dead keys (below).
-        charMap = charToVKTable;
-
-        if (nchars < 0) { // Dead key
-            char junkbuf[2] = { '\0', '\0'};
-            // Use a different table for dead chars since different layouts
-            // return different characters for the same dead key.
-            charMap = charToDeadVKTable;
-
-            // We also need to reset layout so that next translation
-            // is unaffected by the dead status.  We do this by
-            // translating <SPACE> key.
-            kbdState[dynamic->windowsKey] &= ~0x80;
-            kbdState[VK_SPACE] |= 0x80;
-
-            ToAsciiEx(VK_SPACE, spaceScanCode, kbdState,
-                      (WORD*)junkbuf, 0, hkl);
+    // Setup keyMapTable's windowsScanCodeUS
+    for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+        USHORT scancode = (USHORT) MapVirtualKeyEx(keyMapTable[i].windowsKey, MAPVK_VK_TO_VSC_EX, kbdLayoutUS);
+        #ifdef DEBUG_KEYS
+        if( 0 == scancode ) {
+            int lastError = (int) GetLastError();
+            STD_PRINT("*** WindowsWindow: InitKeyMapTableScanCode: No ScanCode for windows vkey 0x%X (item %d), winErr 0x%X %d\n", 
+                keyMapTable[i].windowsKey, i, lastError, lastError);
         }
+        STD_PRINT("*** WindowsWindow: InitKeyMapTableScanCode: %3.3d windows vkey 0x%X -> scancode 0x%X\n", 
+            i, keyMapTable[i].windowsKey, scancode);
+        #endif
+        keyMapTable[i].windowsScanCodeUS = scancode;
+    }
+}
 
-        nconverted = MultiByteToWideChar(codePage, 0,
-                                         cbuf, 1, ucbuf, 2);
+static void ParseWmVKeyAndScanCode(USHORT winVKey, BYTE winScanCode, BYTE flags, USHORT *outJavaVKeyUS, USHORT *outJavaVKeyXX, USHORT *outUTF16Char) {
+    wchar_t uniChars[2] = { L'\0', L'\0' }; // uint16_t
+    USHORT winVKeyUS = 0;
+    int nUniChars, i, j;
+    USHORT javaVKeyUS = J_VK_UNDEFINED;
+    USHORT javaVKeyXX = J_VK_UNDEFINED;
 
-        uc = ucbuf[0];
-        {
-            const CharToVKEntry *map;
-            for (map = charMap;  map->c != 0;  ++map) {
-                if (uc == map->c) {
-                    dynamic->javaKey = map->javaKey;
-                    break;
-                }
+    HKL hkl = GetKeyboardLayout(0);
+
+    //
+    // winVKey, winScanCode -> UTF16 w/ current KeyboardLayout
+    //
+    GetKeyboardState(kbdState); 
+    kbdState[winVKey] |=  0x80;
+    nUniChars = ToUnicodeEx(winVKey, winScanCode, kbdState, uniChars, 2, 0, hkl);
+    kbdState[winVKey] &= ~0x80;
+
+    *outUTF16Char = (USHORT)(uniChars[0]); // Note: Even dead key are written in uniChar's ..
+
+    if ( 0 > nUniChars ) { // Dead key
+        char junkbuf[2] = { '\0', '\0'};
+
+        // We need to reset layout so that next translation
+        // is unaffected by the dead status.  We do this by
+        // translating <SPACE> key.
+        kbdState[VK_SPACE] |= 0x80;
+        ToAsciiEx(VK_SPACE, spaceScanCode, kbdState, (WORD*)junkbuf, 0, hkl);
+        kbdState[VK_SPACE] &= ~0x80;
+    }
+
+    //
+    // winVKey -> javaVKeyXX
+    //
+    for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+        if ( keyMapTable[i].windowsKey == winVKey ) {
+            javaVKeyXX = keyMapTable[i].javaKey;
+            break;
+        }
+    }
+    if( IS_WITHIN( winVKey, VK_NUMPAD0, VK_DIVIDE ) ) {
+        // Use modded keySym for keypad for US and NN
+        winVKeyUS = winVKey;
+        javaVKeyUS = javaVKeyXX;
+    } else {
+        // Assume extended scan code 0xE0 if extended flags is set (no 0xE1 from WM_KEYUP/WM_KEYDOWN)
+        USHORT winScanCodeExt = winScanCode;
+        if( 0 != ( 0x01 & flags ) ) {
+            winScanCodeExt |= 0xE000;
+        }
+
+        //
+        // winVKey, winScanCodeExt -> javaVKeyUS w/ US KeyboardLayout
+        //
+        for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+            if ( keyMapTable[i].windowsScanCodeUS == winScanCodeExt ) {
+                winVKeyUS = keyMapTable[i].windowsKey;
+                javaVKeyUS = keyMapTable[i].javaKey;
+                break;
             }
         }
+    }
+
+    *outJavaVKeyUS = javaVKeyUS;
+    *outJavaVKeyXX = javaVKeyXX;
 
-    } // for each VK_OEM_*
+#ifdef DEBUG_KEYS
+    STD_PRINT("*** WindowsWindow: ParseWmVKeyAndScanCode winVKey 0x%X, winScanCode 0x%X, winScanCodeExt 0x%X, flags 0x%X -> UTF(0x%X, %c, res %d, sizeof %d), vKeys( US(win 0x%X, java 0x%X), XX(win 0x%X, java 0x%X))\n", 
+        (int)winVKey, (int)winScanCode, winScanCodeExt, (int)flags,
+        *outUTF16Char, *outUTF16Char, nUniChars, sizeof(uniChars[0]),
+        winVKeyUS, javaVKeyUS, winVKey, javaVKeyXX);
+#endif
 }
 
-static jint GetModifiers(BOOL altKeyFlagged, UINT jkey) {
+static jint GetModifiers(USHORT jkey) {
     jint modifiers = 0;
     // have to do &0xFFFF to avoid runtime assert caused by compiling with
     // /RTCcsu
@@ -473,9 +454,12 @@ static jint GetModifiers(BOOL altKeyFlagged, UINT jkey) {
     if ( HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0 || J_VK_SHIFT == jkey ) {
         modifiers |= EVENT_SHIFT_MASK;
     }
-    if ( altKeyFlagged || HIBYTE((GetKeyState(VK_MENU) & 0xFFFF)) != 0 || J_VK_ALT == jkey ) {
+    if ( HIBYTE((GetKeyState(VK_LMENU) & 0xFFFF)) != 0 || J_VK_ALT == jkey ) {
         modifiers |= EVENT_ALT_MASK;
     }
+    if ( HIBYTE((GetKeyState(VK_RMENU) & 0xFFFF)) != 0 || (USHORT)J_VK_ALT_GRAPH == jkey ) {
+        modifiers |= EVENT_ALT_GRAPH_MASK;
+    }
     if ( HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0 ) {
         modifiers |= EVENT_BUTTON1_MASK;
     }
@@ -489,127 +473,45 @@ static jint GetModifiers(BOOL altKeyFlagged, UINT jkey) {
     return modifiers;
 }
 
+/**
 static BOOL IsAltKeyDown(BYTE flags, BOOL system) {
     // The Alt modifier is reported in the 29th bit of the lParam,
     // i.e., it is the 5th bit of `flags' (which is HIBYTE(HIWORD(lParam))).
     return system && ( flags & (1<<5) ) != 0;
-}
-
-UINT WindowsKeyToJavaKey(UINT windowsKey)
-{
-    int i, j, javaKey = J_VK_UNDEFINED;
-    // for the general case, use a bi-directional table
-    for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
-        if (keyMapTable[i].windowsKey == windowsKey) {
-            javaKey = keyMapTable[i].javaKey;
-        }
-    }
-    if( J_VK_UNDEFINED == javaKey ) {
-        for (j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
-            if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
-                if (dynamicKeyMapTable[j].javaKey != J_VK_UNDEFINED) {
-                    javaKey = dynamicKeyMapTable[j].javaKey;
-                } else {
-                    break;
-                }
-            }
-        }
-    }
-
-#ifdef DEBUG_KEYS
-    STD_PRINT("*** WindowsWindow: WindowsKeyToJavaKey 0x%X -> 0x%X\n", windowsKey, javaKey);
-#endif
-    return javaKey;
-}
-
-#ifndef MAPVK_VSC_TO_VK
-    #define MAPVK_VSC_TO_VK 1
-#endif
-#ifndef MAPVK_VK_TO_CHAR
-    #define MAPVK_VK_TO_CHAR 2
-#endif
+} */
 
-static UINT WmVKey2ShiftedChar(UINT wkey, UINT modifiers) {
-    UINT c = MapVirtualKey(wkey, MAPVK_VK_TO_CHAR);
-    if( 0 != ( modifiers & EVENT_SHIFT_MASK ) ) {
-        return islower(c) ? toupper(c) : c;
-    }
-    return isupper(c) ? tolower(c) : c;
-}
-
-static int WmChar(JNIEnv *env, jobject window, UINT character, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
-    UINT modifiers = 0, jkey = 0, wkey = 0;
-
-    wkey = MapVirtualKey(scanCode, MAPVK_VSC_TO_VK);
-    jkey = WindowsKeyToJavaKey(wkey);
-    modifiers = GetModifiers( IsAltKeyDown(flags, system), 0 );
-
-    if (character == VK_RETURN) {
-        character = J_VK_ENTER;
-    }
-
-    (*env)->CallVoidMethod(env, window, sendKeyEventID,
-                           (jint) EVENT_KEY_TYPED,
-                           modifiers,
-                           (jint) jkey,
-                           (jchar) character);
-    return 1;
-}
-
-static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
-    UINT modifiers = 0, jkey = 0, character = 0;
+static int WmKeyDown(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
+    UINT modifiers = 0;
+    USHORT javaVKeyUS=0, javaVKeyXX=0, utf16Char=0;
     if (wkey == VK_PROCESSKEY) {
         return 1;
     }
 
-    jkey = WindowsKeyToJavaKey(wkey);
-    modifiers = GetModifiers( IsAltKeyDown(flags, system), jkey );
-    character = WmVKey2ShiftedChar(wkey, modifiers);
+    ParseWmVKeyAndScanCode(wkey, scanCode, flags, &javaVKeyUS, &javaVKeyXX, &utf16Char);
 
-/*
-    character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
-*/
+    modifiers = GetModifiers( javaVKeyUS );
 
     (*env)->CallVoidMethod(env, window, sendKeyEventID,
-                           (jint) EVENT_KEY_PRESSED,
-                           modifiers,
-                           (jint) jkey,
-                           (jchar) character);
-
-    /* windows does not create a WM_CHAR for the Del key
-       for some reason, so we need to create the KEY_TYPED event on the
-       WM_KEYDOWN.
-     */
-    if (jkey == J_VK_DELETE) {
-        (*env)->CallVoidMethod(env, window, sendKeyEventID,
-                               (jint) EVENT_KEY_TYPED,
-                               modifiers,
-                               (jint) 0,
-                               (jchar) '\177');
-    }
+                           (jshort) EVENT_KEY_PRESSED,
+                           (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char);
 
     return 0;
 }
 
-static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
-    UINT modifiers = 0, jkey = 0, character = 0;
+static int WmKeyUp(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
+    UINT modifiers = 0;
+    USHORT javaVKeyUS=0, javaVKeyXX=0, utf16Char=0;
     if (wkey == VK_PROCESSKEY) {
         return 1;
     }
 
-    jkey = WindowsKeyToJavaKey(wkey);
-    modifiers = GetModifiers( IsAltKeyDown(flags, system), jkey );
-    character = WmVKey2ShiftedChar(wkey, modifiers);
+    ParseWmVKeyAndScanCode(wkey, scanCode, flags, &javaVKeyUS, &javaVKeyXX, &utf16Char);
 
-/*
-    character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
-*/
+    modifiers = GetModifiers( javaVKeyUS );
 
     (*env)->CallVoidMethod(env, window, sendKeyEventID,
-                           (jint) EVENT_KEY_RELEASED,
-                           modifiers,
-                           (jint) jkey,
-                           (jchar) character);
+                           (jshort) EVENT_KEY_RELEASED,
+                           (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char);
 
     return 0;
 }
@@ -639,14 +541,14 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jb
     DBG_PRINT("*** WindowsWindow: requestFocus.XX\n");
 }
 
-static void NewtWindows_trackPointerLeave(HWND hwnd) {
+static BOOL NewtWindows_trackPointerLeave(HWND hwnd) {
     TRACKMOUSEEVENT tme;
     memset(&tme, 0, sizeof(TRACKMOUSEEVENT));
     tme.cbSize = sizeof(TRACKMOUSEEVENT);
     tme.dwFlags = TME_LEAVE;
     tme.hwndTrack = hwnd;
     tme.dwHoverTime = 0; // we don't use TME_HOVER
-    TrackMouseEvent(&tme);
+    return TrackMouseEvent(&tme);
 }
 
 #if 0
@@ -737,7 +639,7 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd)
     {
         LONG style = GetWindowLong(hwnd, GWL_STYLE);
 
-        BOOL bIsUndecorated = (style & (WS_CHILD|WS_POPUP|WS_SYSMENU)) != 0;
+        BOOL bIsUndecorated = (style & (WS_CHILD|WS_POPUP)) != 0;
         if (!bIsUndecorated) {
             /* Get outer frame sizes. */
             if (style & WS_THICKFRAME) {
@@ -796,6 +698,97 @@ static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type)
     (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, w, h, JNI_FALSE);
 }
 
+#ifdef TEST_MOUSE_HOOKS
+
+static HHOOK hookLLMP;
+static HHOOK hookMP;
+
+static LRESULT CALLBACK HookLowLevelMouseProc (int code, WPARAM wParam, LPARAM lParam)
+{
+    // if (code == HC_ACTION)
+    {
+        const char *msg;
+        char msg_buff[128];
+        switch (wParam)
+        {
+            case WM_LBUTTONDOWN: msg = "WM_LBUTTONDOWN"; break;
+            case WM_LBUTTONUP: msg = "WM_LBUTTONUP"; break;
+            case WM_MOUSEMOVE: msg = "WM_MOUSEMOVE"; break;
+            case WM_MOUSEWHEEL: msg = "WM_MOUSEWHEEL"; break;
+            case WM_MOUSEHWHEEL: msg = "WM_MOUSEHWHEEL"; break;
+            case WM_RBUTTONDOWN: msg = "WM_RBUTTONDOWN"; break;
+            case WM_RBUTTONUP: msg = "WM_RBUTTONUP"; break;
+            default: 
+                sprintf(msg_buff, "Unknown msg: %u", wParam); 
+                msg = msg_buff;
+                break;
+        }//switch
+
+        const MSLLHOOKSTRUCT *p = (MSLLHOOKSTRUCT*)lParam;
+        DBG_PRINT("**** LLMP: Code: 0x%X: %s - %d/%d\n", code, msg, (int)p->pt.x, (int)p->pt.y);
+    //} else {
+    //    DBG_PRINT("**** LLMP: CODE: 0x%X\n", code);
+    }
+    return CallNextHookEx(hookLLMP, code, wParam, lParam); 
+}
+
+static LRESULT CALLBACK HookMouseProc (int code, WPARAM wParam, LPARAM lParam)
+{
+    // if (code == HC_ACTION)
+    {
+        const char *msg;
+        char msg_buff[128];
+        switch (wParam)
+        {
+            case WM_LBUTTONDOWN: msg = "WM_LBUTTONDOWN"; break;
+            case WM_LBUTTONUP: msg = "WM_LBUTTONUP"; break;
+            case WM_MOUSEMOVE: msg = "WM_MOUSEMOVE"; break;
+            case WM_MOUSEWHEEL: msg = "WM_MOUSEWHEEL"; break;
+            case WM_MOUSEHWHEEL: msg = "WM_MOUSEHWHEEL"; break;
+            case WM_RBUTTONDOWN: msg = "WM_RBUTTONDOWN"; break;
+            case WM_RBUTTONUP: msg = "WM_RBUTTONUP"; break;
+            default: 
+                sprintf(msg_buff, "Unknown msg: %u", wParam); 
+                msg = msg_buff;
+                break;
+        }//switch
+
+        const MOUSEHOOKSTRUCT *p = (MOUSEHOOKSTRUCT*)lParam;
+        DBG_PRINT("**** MP: Code: 0x%X: %s - hwnd %p, %d/%d\n", code, msg, p->hwnd, (int)p->pt.x, (int)p->pt.y);
+    //} else {
+    //    DBG_PRINT("**** MP: CODE: 0x%X\n", code);
+    }
+    return CallNextHookEx(hookMP, code, wParam, lParam); 
+}
+
+#endif
+
+static BOOL SafeShowCursor(BOOL show) {
+    int count, countPre;
+    BOOL b;
+
+    if( show ) {
+        count = ShowCursor(TRUE);
+        if(count < 0) {
+            do {
+                countPre = count;
+                count = ShowCursor(TRUE);
+            } while( count > countPre && count < 0 );
+        }
+        b = count>=0 ? TRUE : FALSE;
+    } else {
+        count = ShowCursor(FALSE);
+        if(count >= 0) {
+            do {
+                countPre = count;
+                count = ShowCursor(FALSE);
+            } while( count < countPre && count >= 0 );
+        }
+        b = count<0 ? TRUE : FALSE;
+    }
+    return b;
+}
+
 static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) {
     LRESULT res = 0;
     int useDefWindowProc = 0;
@@ -817,7 +810,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
     env = wud->jenv;
     window = wud->jinstance;
 
-    // DBG_PRINT("*** WindowsWindow: thread 0x%X - window %p -> %p, 0x%X %d/%d\n", (int)GetCurrentThreadId(), wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
+    // DBG_PRINT("*** WindowsWindow: thread 0x%X - window %p -> %p, msg 0x%X, %d/%d\n", (int)GetCurrentThreadId(), wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
 
     if (NULL==window || NULL==env) {
         return DefWindowProc(wnd, message, wParam, lParam);
@@ -846,46 +839,35 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
         break;
 
     case WM_SYSCHAR:
-        repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
-        repCnt = LOWORD(lParam);
-#ifdef DEBUG_KEYS
-        STD_PRINT("*** WindowsWindow: windProc WM_SYSCHAR sending window %p -> %p, char 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
-#endif
-        useDefWindowProc = WmChar(env, window, wParam, repCnt, scanCode, flags, TRUE);
+        useDefWindowProc = 1;
         break;
 
     case WM_SYSKEYDOWN:
         repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
         repCnt = LOWORD(lParam);
 #ifdef DEBUG_KEYS
-        STD_PRINT("*** WindowsWindow: windProc WM_SYSKEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+        DBG_PRINT("*** WindowsWindow: windProc WM_SYSKEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
 #endif
-        useDefWindowProc = WmKeyDown(env, window, wParam, repCnt, scanCode, flags, TRUE);
+        useDefWindowProc = WmKeyDown(env, window, (USHORT)wParam, repCnt, scanCode, flags, TRUE);
         break;
 
     case WM_SYSKEYUP:
         repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
         repCnt = LOWORD(lParam);
 #ifdef DEBUG_KEYS
-        STD_PRINT("*** WindowsWindow: windProc WM_SYSKEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+        DBG_PRINT("*** WindowsWindow: windProc WM_SYSKEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
 #endif
-        useDefWindowProc = WmKeyUp(env, window, wParam, repCnt, scanCode, flags, TRUE);
+        useDefWindowProc = WmKeyUp(env, window, (USHORT)wParam, repCnt, scanCode, flags, TRUE);
         break;
 
     case WM_CHAR:
-        repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
-        repCnt = LOWORD(lParam);
-#ifdef DEBUG_KEYS
-        STD_PRINT("*** WindowsWindow: windProc WM_CHAR sending window %p -> %p, char 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
-#endif
-        useDefWindowProc = WmChar(env, window, wParam, repCnt, scanCode, flags, FALSE);
+        useDefWindowProc = 1;
         break;
         
     case WM_KEYDOWN:
         repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
-        repCnt = LOWORD(lParam);
 #ifdef DEBUG_KEYS
-        STD_PRINT("*** WindowsWindow: windProc WM_KEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+        DBG_PRINT("*** WindowsWindow: windProc WM_KEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
 #endif
         useDefWindowProc = WmKeyDown(env, window, wParam, repCnt, scanCode, flags, FALSE);
         break;
@@ -894,7 +876,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
         repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
         repCnt = LOWORD(lParam);
 #ifdef DEBUG_KEYS
-        STD_PRINT("*** WindowsWindow: windProc WM_KEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+        DBG_PRINT("*** WindowsWindow: windProc WM_KEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
 #endif
         useDefWindowProc = WmKeyUp(env, window, wParam, repCnt, scanCode, flags, FALSE);
         break;
@@ -918,19 +900,19 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
         DBG_PRINT("*** WindowsWindow: LBUTTONDOWN\n");
         (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
         (*env)->CallVoidMethod(env, window, sendMouseEventID,
-                               (jint) EVENT_MOUSE_PRESSED,
-                               GetModifiers( FALSE, 0 ),
+                               (jshort) EVENT_MOUSE_PRESSED,
+                               GetModifiers( 0 ),
                                (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
-                               (jint) 1, (jint) 0);
+                               (jshort) 1, (jfloat) 0.0f);
         useDefWindowProc = 1;
         break;
 
     case WM_LBUTTONUP:
         (*env)->CallVoidMethod(env, window, sendMouseEventID,
-                               (jint) EVENT_MOUSE_RELEASED,
-                               GetModifiers( FALSE, 0 ),
+                               (jshort) EVENT_MOUSE_RELEASED,
+                               GetModifiers( 0 ),
                                (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
-                               (jint) 1, (jint) 0);
+                               (jshort) 1, (jfloat) 0.0f);
         useDefWindowProc = 1;
         break;
 
@@ -938,19 +920,19 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
         DBG_PRINT("*** WindowsWindow: MBUTTONDOWN\n");
         (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
         (*env)->CallVoidMethod(env, window, sendMouseEventID,
-                               (jint) EVENT_MOUSE_PRESSED,
-                               GetModifiers( FALSE, 0 ),
+                               (jshort) EVENT_MOUSE_PRESSED,
+                               GetModifiers( 0 ),
                                (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
-                               (jint) 2, (jint) 0);
+                               (jshort) 2, (jfloat) 0.0f);
         useDefWindowProc = 1;
         break;
 
     case WM_MBUTTONUP:
         (*env)->CallVoidMethod(env, window, sendMouseEventID,
-                               (jint) EVENT_MOUSE_RELEASED,
-                               GetModifiers( FALSE, 0 ),
+                               (jshort) EVENT_MOUSE_RELEASED,
+                               GetModifiers( 0 ),
                                (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
-                               (jint) 2, (jint) 0);
+                               (jshort) 2, (jfloat) 0.0f);
         useDefWindowProc = 1;
         break;
 
@@ -958,53 +940,95 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
         DBG_PRINT("*** WindowsWindow: RBUTTONDOWN\n");
         (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
         (*env)->CallVoidMethod(env, window, sendMouseEventID,
-                               (jint) EVENT_MOUSE_PRESSED,
-                               GetModifiers( FALSE, 0 ),
+                               (jshort) EVENT_MOUSE_PRESSED,
+                               GetModifiers( 0 ),
                                (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
-                               (jint) 3, (jint) 0);
+                               (jshort) 3, (jfloat) 0.0f);
         useDefWindowProc = 1;
         break;
 
     case WM_RBUTTONUP:
         (*env)->CallVoidMethod(env, window, sendMouseEventID,
-                               (jint) EVENT_MOUSE_RELEASED,
-                               GetModifiers( FALSE, 0 ),
+                               (jshort) EVENT_MOUSE_RELEASED,
+                               GetModifiers( 0 ),
                                (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
-                               (jint) 3,  (jint) 0);
+                               (jshort) 3,  (jfloat) 0.0f);
         useDefWindowProc = 1;
         break;
 
     case WM_MOUSEMOVE:
+        // DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d\n", (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam));
         (*env)->CallVoidMethod(env, window, sendMouseEventID,
-                               (jint) EVENT_MOUSE_MOVED,
-                               GetModifiers( FALSE, 0 ),
+                               (jshort) EVENT_MOUSE_MOVED,
+                               GetModifiers( 0 ),
                                (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
-                               (jint) 0,  (jint) 0);
+                               (jshort) 0,  (jfloat) 0.0f);
         useDefWindowProc = 1;
         break;
     case WM_MOUSELEAVE:
-        (*env)->CallVoidMethod(env, window, enqueueMouseEventID, JNI_FALSE,
-                               (jint) EVENT_MOUSE_EXITED,
+        DBG_PRINT("*** WindowsWindow: WM_MOUSELEAVE\n");
+        (*env)->CallVoidMethod(env, window, sendMouseEventID,
+                               (jshort) EVENT_MOUSE_EXITED,
                                0,
                                (jint) -1, (jint) -1, // fake
-                               (jint) 0,  (jint) 0);
+                               (jshort) 0,  (jfloat) 0.0f);
         useDefWindowProc = 1;
         break;
     // Java synthesizes EVENT_MOUSE_ENTERED
 
-    case WM_MOUSEWHEEL: {
+    case WM_HSCROLL: { // Only delivered if windows has WS_HSCROLL, hence dead code!
+            int sb = LOWORD(wParam);
+            int modifiers = GetModifiers( 0 ) | EVENT_SHIFT_MASK;
+            float rotation;
+            switch(sb) {
+                case SB_LINELEFT:
+                    rotation = 1.0f;
+                    break;
+                case SB_PAGELEFT:
+                    rotation = 2.0f;
+                    break;
+                case SB_LINERIGHT:
+                    rotation = -1.0f;
+                    break;
+                case SB_PAGERIGHT:
+                    rotation = -1.0f;
+                    break;
+            }
+            DBG_PRINT("*** WindowsWindow: WM_HSCROLL 0x%X, rotation %f, mods 0x%X\n", sb, rotation, modifiers);
+            (*env)->CallVoidMethod(env, window, sendMouseEventID,
+                                   (jshort) EVENT_MOUSE_WHEEL_MOVED,
+                                   modifiers,
+                                   (jint) 0, (jint) 0,
+                                   (jshort) 1,  (jfloat) rotation);
+            useDefWindowProc = 1;
+            break;
+        }
+    case WM_MOUSEHWHEEL: /* tilt */
+    case WM_MOUSEWHEEL: /* rotation */ {
         // need to convert the coordinates to component-relative
         int x = GET_X_LPARAM(lParam);
         int y = GET_Y_LPARAM(lParam);
+        int modifiers = GetModifiers( 0 );
+        float rotationOrTilt = (float)(GET_WHEEL_DELTA_WPARAM(wParam))/WHEEL_DELTAf;
+        int vKeys = GET_KEYSTATE_WPARAM(wParam);
         POINT eventPt;
         eventPt.x = x;
         eventPt.y = y;
         ScreenToClient(wnd, &eventPt);
+
+        if( WM_MOUSEHWHEEL == message ) {
+            modifiers |= EVENT_SHIFT_MASK;
+            DBG_PRINT("*** WindowsWindow: WM_MOUSEHWHEEL %d/%d, tilt %f, vKeys 0x%X, mods 0x%X\n", 
+                (int)eventPt.x, (int)eventPt.y, rotationOrTilt, vKeys, modifiers);
+        } else {
+            DBG_PRINT("*** WindowsWindow: WM_MOUSEWHEEL %d/%d, rotation %f, vKeys 0x%X, mods 0x%X\n", 
+                (int)eventPt.x, (int)eventPt.y, rotationOrTilt, vKeys, modifiers);
+        }
         (*env)->CallVoidMethod(env, window, sendMouseEventID,
-                               (jint) EVENT_MOUSE_WHEEL_MOVED,
-                               GetModifiers( FALSE, 0 ),
+                               (jshort) EVENT_MOUSE_WHEEL_MOVED,
+                               modifiers,
                                (jint) eventPt.x, (jint) eventPt.y,
-                               (jint) 1,  (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f));
+                               (jshort) 1,  (jfloat) rotationOrTilt);
         useDefWindowProc = 1;
         break;
     }
@@ -1034,32 +1058,46 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
     case WM_PAINT: {
         RECT r;
         useDefWindowProc = 0;
-        if (GetUpdateRect(wnd, &r, TRUE /* erase background */)) {
-            /*
-            jint width = r.right-r.left;
-            jint height = r.bottom-r.top;
-            if (width > 0 && height > 0) {
-                (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, r.left, r.top, width, height);
-            }
-            ValidateRect(wnd, &r);
-            */
+        if (GetUpdateRect(wnd, &r, FALSE /* do not erase background */)) {
+            // clear the whole client area and issue repaint for it, w/o looping through erase background
+            ValidateRect(wnd, NULL); // clear all!
+            (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
+        } else {
+            // shall not happen ?
+            ValidateRect(wnd, NULL); // clear all!
         }
+        // return 0 == done
         break;
     }
     case WM_ERASEBKGND:
         // ignore erase background
         (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
         useDefWindowProc = 0;
-        res = 1; // OpenGL, etc .. erases the background, hence we claim to have just done this
+        res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this
+        break;
+    case WM_SETCURSOR :
+        if (0 != wud->setPointerVisible) { // Tristate, -1, 0, 1
+            BOOL visibilityChangeSuccessful;
+            if (1 == wud->setPointerVisible) {
+                visibilityChangeSuccessful = SafeShowCursor(TRUE);
+            } else /* -1 == wud->setPointerVisible */ {
+                visibilityChangeSuccessful = SafeShowCursor(FALSE);
+            }
+            useDefWindowProc = visibilityChangeSuccessful ? 1 : 0;
+            DBG_PRINT("*** WindowsWindow: WM_SETCURSOR requested visibility: %d success: %d\n", wud->setPointerVisible, visibilityChangeSuccessful);
+            wud->setPointerVisible = 0;
+            useDefWindowProc = 0; // own signal, consumed
+        } else {
+            useDefWindowProc = 1; // NOP for us, allow parent to act
+        }
         break;
-
-
     default:
         useDefWindowProc = 1;
     }
 
-    if (useDefWindowProc)
+    if (useDefWindowProc) {
         return DefWindowProc(wnd, message, wParam, lParam);
+    }
     return res;
 }
 
@@ -1081,7 +1119,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_DispatchMes
         // DBG_PRINT("*** WindowsWindow.DispatchMessages0: thread 0x%X - gotOne %d\n", (int)GetCurrentThreadId(), (int)gotOne);
         if (gotOne) {
             ++i;
-            TranslateMessage(&msg);
+            // TranslateMessage(&msg); // No more needed: We translate V_KEY -> UTF Char manually in key up/down
             DispatchMessage(&msg);
         }
     } while (gotOne && i < 100);
@@ -1089,11 +1127,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_DispatchMes
 
 /*
  * Class:     jogamp_newt_driver_windows_ScreenDriver
- * Method:    getOriginX0
- * Signature: (I)I
+ * Method:    getVirtualOriginX0
+ * Signature: ()I
  */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginX0
-  (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualOriginX0
+  (JNIEnv *env, jobject obj)
 {
     if( GetSystemMetrics( SM_CMONITORS) > 1) {
         return (jint)GetSystemMetrics(SM_XVIRTUALSCREEN);
@@ -1104,11 +1142,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginX0
 
 /*
  * Class:     jogamp_newt_driver_windows_ScreenDriver
- * Method:    getOriginY0
- * Signature: (I)I
+ * Method:    getVirtualOriginY0
+ * Signature: ()I
  */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginY0
-  (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualOriginY0
+  (JNIEnv *env, jobject obj)
 {
     if( GetSystemMetrics( SM_CMONITORS ) > 1) {
         return (jint)GetSystemMetrics(SM_YVIRTUALSCREEN);
@@ -1119,11 +1157,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getOriginY0
 
 /*
  * Class:     jogamp_newt_driver_windows_ScreenDriver
- * Method:    getWidthImpl
- * Signature: (I)I
+ * Method:    getVirtualWidthImpl
+ * Signature: ()I
  */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getWidthImpl0
-  (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualWidthImpl0
+  (JNIEnv *env, jobject obj)
 {
     if( GetSystemMetrics( SM_CMONITORS) > 1) {
         return (jint)GetSystemMetrics(SM_CXVIRTUALSCREEN);
@@ -1134,11 +1172,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getWidthImpl
 
 /*
  * Class:     jogamp_newt_driver_windows_ScreenDriver
- * Method:    getHeightImpl
- * Signature: (I)I
+ * Method:    getVirtualHeightImpl
+ * Signature: ()I
  */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getHeightImpl0
-  (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualHeightImpl0
+  (JNIEnv *env, jobject obj)
 {
     if( GetSystemMetrics( SM_CMONITORS ) > 1) {
         return (jint)GetSystemMetrics(SM_CYVIRTUALSCREEN);
@@ -1190,65 +1228,137 @@ static int NewtScreen_RotationNewtCCW2NativeCCW(JNIEnv *env, jint newt) {
     return native;
 }
 
-/*
-static void NewtScreen_scanDisplayDevices() {
-    DISPLAY_DEVICE device;
-    int i = 0;
-    LPCTSTR name;
-    while(NULL != (name = NewtScreen_getDisplayDeviceName(&device, i))) {
-        fprintf(stderr, "*** [%d]: <%s> active %d\n", i, name, ( 0 != ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
-        i++;
+static LPCTSTR NewtScreen_getAdapterName(DISPLAY_DEVICE * device, int crt_idx) {
+    memset(device, 0, sizeof(DISPLAY_DEVICE)); 
+    device->cb = sizeof(DISPLAY_DEVICE);
+    if( FALSE == EnumDisplayDevices(NULL, crt_idx, device, 0) ) {
+        DBG_PRINT("*** WindowsWindow: getAdapterName.EnumDisplayDevices(crt_idx %d) -> FALSE\n", crt_idx);
+        return NULL;
     }
-}*/
 
-static LPCTSTR NewtScreen_getDisplayDeviceName(DISPLAY_DEVICE * device, int scrn_idx) {
-    device->cb = sizeof(DISPLAY_DEVICE);
-    if( FALSE == EnumDisplayDevices(NULL, scrn_idx, device, 0) ) {
-        DBG_PRINT("*** WindowsWindow: getDisplayDeviceName.EnumDisplayDevices(scrn_idx %d) -> FALSE\n", scrn_idx);
+    if( NULL == device->DeviceName || 0 == _tcslen(device->DeviceName) ) {
         return NULL;
     }
 
-    if( 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) {
-        DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(scrn_idx %d)\n", scrn_idx);
+    return device->DeviceName;
+}
+
+static LPCTSTR NewtScreen_getMonitorName(LPCTSTR adapterName, DISPLAY_DEVICE * device, int monitor_idx, BOOL onlyActive) {
+    memset(device, 0, sizeof(DISPLAY_DEVICE)); 
+    device->cb = sizeof(DISPLAY_DEVICE);
+    if( 0 == monitor_idx ) {
+        if( FALSE == EnumDisplayDevices(adapterName, monitor_idx, device, 0) ) {
+            DBG_PRINT("*** WindowsWindow: getDisplayName.EnumDisplayDevices(monitor_idx %d).adapter -> FALSE\n", monitor_idx);
+            return NULL;
+        }
+    }
+
+    if( onlyActive && 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) {
+        DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(monitor_idx %d).display\n", monitor_idx);
+        return NULL;
+    }
+    if( NULL == device->DeviceName || 0 == _tcslen(device->DeviceName) ) {
         return NULL;
     }
 
     return device->DeviceName;
 }
 
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_dumpMonitorInfo0
+  (JNIEnv *env, jclass clazz)
+{
+    DISPLAY_DEVICE aDevice, dDevice;
+    int i = 0, j;
+    LPCTSTR aName, dName;
+    while(NULL != (aName = NewtScreen_getAdapterName(&aDevice, i))) {
+        fprintf(stderr, "*** [%d]: <%s> flags 0x%X active %d\n", i, aName, aDevice.StateFlags, ( 0 != ( aDevice.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
+        j=0;
+        while(NULL != (dName = NewtScreen_getMonitorName(aName, &dDevice, j, FALSE))) {
+            fprintf(stderr, "*** [%d][%d]: <%s> flags 0x%X active %d\n", i, j, dName, dDevice.StateFlags, ( 0 != ( dDevice.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
+            j++;
+        }
+        i++;
+    }
+}
+
 static HDC NewtScreen_createDisplayDC(LPCTSTR displayDeviceName) {
     return CreateDC("DISPLAY", displayDeviceName, NULL, NULL);
 }
 
 /*
  * Class:     jogamp_newt_driver_windows_ScreenDriver
- * Method:    getScreenMode0
- * Signature: (II)[I
+ * Method:    getAdapterName0
+ * Signature: (I)Ljava/lang/String;
  */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScreenMode0
-  (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx)
+JNIEXPORT jstring JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getAdapterName0
+  (JNIEnv *env, jobject obj, jint crt_idx)
 {
     DISPLAY_DEVICE device;
-    int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL;
-    LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx);
-    if(NULL == deviceName) {
-        DBG_PRINT("*** WindowsWindow: getScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx);
-        return (*env)->NewIntArray(env, 0);
+    LPCTSTR adapterName = NewtScreen_getAdapterName(&device, crt_idx);
+    DBG_PRINT("*** WindowsWindow: getAdapterName(crt_idx %d) -> %s, active %d\n", crt_idx, 
+              (NULL==adapterName?"nil":adapterName), 0 == ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ));
+    if(NULL == adapterName) {
+        return NULL;
     }
+#ifdef UNICODE
+    return (*env)->NewString(env, adapterName, wcslen(adapterName));
+#else
+    return (*env)->NewStringUTF(env, adapterName);
+#endif
+}
 
+/*
+ * Class:     jogamp_newt_driver_windows_ScreenDriver
+ * Method:    getActiveMonitorName0
+ * Signature: (Ljava/lang/String;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getActiveMonitorName0
+  (JNIEnv *env, jobject obj, jstring jAdapterName, jint monitor_idx)
+{
+    DISPLAY_DEVICE device;
+    LPCTSTR monitorName;
+#ifdef UNICODE
+    LPCTSTR adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+    monitorName = NewtScreen_getMonitorName(adapterName, &device, monitor_idx, TRUE);
+    DBG_PRINT("*** WindowsWindow: getMonitorName(%s, monitor_idx %d) -> %s\n", adapterName, monitor_idx, (NULL==monitorName?"nil":monitorName));
+    free((void*) adapterName);
+#else
+    LPCTSTR adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+    monitorName = NewtScreen_getMonitorName(adapterName, &device, monitor_idx, TRUE);
+    DBG_PRINT("*** WindowsWindow: getMonitorName(%s, monitor_idx %d) -> %s\n", adapterName, monitor_idx, (NULL==monitorName?"nil":monitorName));
+    (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+    if(NULL == monitorName) {
+        return NULL;
+    }
+#ifdef UNICODE
+    return (*env)->NewString(env, monitorName, wcslen(monitorName));
+#else
+    return (*env)->NewStringUTF(env, monitorName);
+#endif
+}
+
+/*
+ * Class:     jogamp_newt_driver_windows_ScreenDriver
+ * Method:    getMonitorMode0
+ * Signature: (Ljava/lang/String;I)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getMonitorMode0
+  (JNIEnv *env, jobject obj, jstring jAdapterName, jint mode_idx)
+{
+    DISPLAY_DEVICE device;
+    LPCTSTR adapterName;
+    {
+#ifdef UNICODE
+        adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+#else
+        adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+#endif
+    }
     int devModeID;
-    int widthmm, heightmm;
     if(-1 < mode_idx) {
-        // only at initialization time, where index >= 0
-        HDC hdc = NewtScreen_createDisplayDC(deviceName);
-        widthmm = GetDeviceCaps(hdc, HORZSIZE);
-        heightmm = GetDeviceCaps(hdc, VERTSIZE);
-        DeleteDC(hdc);
         devModeID = (int) mode_idx;
-        prop_num++; // add 1st extra prop, mode_idx
     } else {
-        widthmm = 0;
-        heightmm = 0;
         devModeID = ENUM_CURRENT_SETTINGS;
     }
 
@@ -1256,11 +1366,18 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScre
     ZeroMemory(&dm, sizeof(dm));
     dm.dmSize = sizeof(dm);
     
-    if (0 == EnumDisplaySettingsEx(deviceName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE)) {
-        DBG_PRINT("*** WindowsWindow: getScreenMode.EnumDisplaySettingsEx(mode_idx %d/%d) -> NULL\n", mode_idx, devModeID);
+    int res = EnumDisplaySettingsEx(adapterName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE);
+    DBG_PRINT("*** WindowsWindow: getMonitorMode.EnumDisplaySettingsEx(%s, mode_idx %d/%d) -> %d\n", adapterName, mode_idx, devModeID, res);
+#ifdef UNICODE
+    free((void*) adapterName);
+#else
+    (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+
+    if (0 == res) {
         return (*env)->NewIntArray(env, 0);
     }
-    
+
     // swap width and height, since Windows reflects rotated dimension, we don't
     if (DMDO_90 == dm.dmDisplayOrientation || DMDO_270 == dm.dmDisplayOrientation) {
         int tempWidth = dm.dmPelsWidth;
@@ -1268,43 +1385,110 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getScre
         dm.dmPelsHeight = tempWidth;
     }
 
-    jint prop[ prop_num ];
+    int flags = 0;
+    if( 0 != ( dm.dmDisplayFlags & DM_INTERLACED ) ) {
+        flags |= FLAG_INTERLACE;
+    }
+
+    jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
     int propIndex = 0;
 
-    if( -1 < mode_idx ) {
-        prop[propIndex++] = mode_idx;
-    }
-    prop[propIndex++] = 0; // set later for verification of iterator
+    prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
     prop[propIndex++] = dm.dmPelsWidth;
     prop[propIndex++] = dm.dmPelsHeight;
     prop[propIndex++] = dm.dmBitsPerPel;
-    prop[propIndex++] = widthmm;
-    prop[propIndex++] = heightmm;
-    prop[propIndex++] = dm.dmDisplayFrequency;
+    prop[propIndex++] = dm.dmDisplayFrequency * 100; // Hz*100
+    prop[propIndex++] = flags;
+    prop[propIndex++] = 0; // not bound to id
     prop[propIndex++] = NewtScreen_RotationNativeCCW2NewtCCW(env, dm.dmDisplayOrientation);
-    prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL
 
-    jintArray properties = (*env)->NewIntArray(env, prop_num);
+    jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
     if (properties == NULL) {
-        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num);
+        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
     }
-    (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop);
+    (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
     
     return properties;
 }
 
 /*
  * Class:     jogamp_newt_driver_windows_ScreenDriver
- * Method:    setScreenMode0
- * Signature: (IIIIII)Z
+ * Method:    getMonitorDevice0
+ * Signature: (Ljava/lang/String;I)[I
  */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScreenMode0
-  (JNIEnv *env, jobject object, jint scrn_idx, jint width, jint height, jint bits, jint rate, jint rot)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getMonitorDevice0
+  (JNIEnv *env, jobject obj, jstring jAdapterName, jint monitor_idx)
 {
     DISPLAY_DEVICE device;
-    LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx);
-    if(NULL == deviceName) {
-        DBG_PRINT("*** WindowsWindow: setScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx);
+    LPCTSTR adapterName;
+    {
+#ifdef UNICODE
+        adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+#else
+        adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+#endif
+    }
+
+    HDC hdc = NewtScreen_createDisplayDC(adapterName);
+    int widthmm = GetDeviceCaps(hdc, HORZSIZE);
+    int heightmm = GetDeviceCaps(hdc, VERTSIZE);
+    DeleteDC(hdc);
+    int devModeID = ENUM_CURRENT_SETTINGS;
+
+    DEVMODE dm;
+    ZeroMemory(&dm, sizeof(dm));
+    dm.dmSize = sizeof(dm);
+    
+    int res = EnumDisplaySettingsEx(adapterName, devModeID, &dm, 0);
+    DBG_PRINT("*** WindowsWindow: getMonitorDevice.EnumDisplaySettingsEx(%s, devModeID %d) -> %d\n", adapterName, devModeID, res);
+#ifdef UNICODE
+    free((void*) adapterName);
+#else
+    (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+    if (0 == res) {
+        return (*env)->NewIntArray(env, 0);
+    }
+    
+    jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES;
+    jint prop[ propCount ];
+    int propIndex = 0;
+
+    prop[propIndex++] = propCount;
+    prop[propIndex++] = monitor_idx;
+    prop[propIndex++] = widthmm;
+    prop[propIndex++] = heightmm;
+    prop[propIndex++] = dm.dmPosition.x; // rotated viewport
+    prop[propIndex++] = dm.dmPosition.y; // rotated viewport
+    prop[propIndex++] = dm.dmPelsWidth;  // rotated viewport
+    prop[propIndex++] = dm.dmPelsHeight; // rotated viewport
+
+    jintArray properties = (*env)->NewIntArray(env, propCount);
+    if (properties == NULL) {
+        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+    }
+    (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+    
+    return properties;
+}
+
+/*
+ * Class:     jogamp_newt_driver_windows_ScreenDriver
+ * Method:    setMonitorMode0
+ * Signature: (IIIIIIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setMonitorMode0
+  (JNIEnv *env, jobject object, jint monitor_idx, jint x, jint y, jint width, jint height, jint bits, jint rate, jint flags, jint rot)
+{
+    DISPLAY_DEVICE adapterDevice, monitorDevice;
+    LPCTSTR adapterName = NewtScreen_getAdapterName(&adapterDevice, monitor_idx);
+    if(NULL == adapterName) {
+        DBG_PRINT("*** WindowsWindow: setMonitorMode.getAdapterName(monitor_idx %d) -> NULL\n", monitor_idx);
+        return JNI_FALSE;
+    }
+    LPCTSTR monitorName = NewtScreen_getMonitorName(adapterName, &monitorDevice, 0, TRUE);
+    if(NULL == monitorName) {
+        DBG_PRINT("*** WindowsWindow: setMonitorMode.getMonitorName(monitor_idx 0) -> NULL\n");
         return JNI_FALSE;
     }
 
@@ -1312,10 +1496,17 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree
     // initialize the DEVMODE structure
     ZeroMemory(&dm, sizeof(dm));
     dm.dmSize = sizeof(dm);
+    if( 0 <= x && 0 <= y ) {
+        dm.dmPosition.x = (int)x;
+        dm.dmPosition.y = (int)y;
+    }
     dm.dmPelsWidth = (int)width;
     dm.dmPelsHeight = (int)height;
     dm.dmBitsPerPel = (int)bits;
     dm.dmDisplayFrequency = (int)rate;
+    if( 0 != ( flags & FLAG_INTERLACE ) ) {
+        dm.dmDisplayFlags |= DM_INTERLACED;
+    }
     dm.dmDisplayOrientation = NewtScreen_RotationNewtCCW2NativeCCW(env, rot);
 
     // swap width and height, since Windows reflects rotated dimension, we don't
@@ -1325,9 +1516,12 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree
         dm.dmPelsHeight = tempWidth;
     }
 
-    dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+    dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
+    if( 0 <= x && 0 <= y ) {
+        dm.dmFields |= DM_POSITION;
+    }
     
-    return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, 0) ) ? JNI_TRUE : JNI_FALSE ;
+    return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(adapterName, &dm, NULL, 0, NULL) ) ? JNI_TRUE : JNI_FALSE ;
 }
 
 /*
@@ -1336,7 +1530,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setScree
  * Signature: ()Z
  */
 JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
-  (JNIEnv *env, jclass clazz)
+  (JNIEnv *env, jclass clazz, jlong hInstance)
 {
     NewtCommon_init(env);
 
@@ -1347,10 +1541,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
     visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
     windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
     windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
-    enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V");
-    sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
-    enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V");
-    sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+    sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V");
+    sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V");
     requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
 
     if (insetsChangedID == NULL ||
@@ -1360,14 +1552,13 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
         visibleChangedID == NULL ||
         windowDestroyNotifyID == NULL ||
         windowRepaintID == NULL ||
-        enqueueMouseEventID == NULL ||
         sendMouseEventID == NULL ||
-        enqueueKeyEventID == NULL ||
         sendKeyEventID == NULL ||
         requestFocusID == NULL) {
         return JNI_FALSE;
     }
-    BuildDynamicKeyMapTable();
+    InitKeyMapTableScanCode(env);
+
     return JNI_TRUE;
 }
 
@@ -1413,6 +1604,8 @@ static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible,
     UpdateWindow(hwnd);
 }
 
+#define WS_DEFAULT_STYLES (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP)
+
 /*
  * Class:     jogamp_newt_driver_windows_WindowDriver
  * Method:    CreateWindow
@@ -1426,7 +1619,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
     HWND parentWindow = (HWND) (intptr_t) parent;
     const TCHAR* wndClassName = NULL;
     const TCHAR* wndName = NULL;
-    DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_TABSTOP;
+    DWORD windowStyle = WS_DEFAULT_STYLES | WS_VISIBLE;
     int x=(int)jx, y=(int)jy;
     int width=(int)defaultWidth, height=(int)defaultHeight;
     HWND window = NULL;
@@ -1475,6 +1668,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
         WindowUserData * wud = (WindowUserData *) malloc(sizeof(WindowUserData));
         wud->jinstance = (*env)->NewGlobalRef(env, obj);
         wud->jenv = env;
+        wud->setPointerVisible = 0;
 #if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
         SetWindowLong(window, GWL_USERDATA, (intptr_t) wud);
 #else
@@ -1517,6 +1711,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
     (*env)->ReleaseStringUTFChars(env, jWndName, wndName);
 #endif
 
+#ifdef TEST_MOUSE_HOOKS
+    hookLLMP = SetWindowsHookEx(WH_MOUSE_LL, &HookLowLevelMouseProc, (HINSTANCE) (intptr_t) hInstance, 0);
+    hookMP = SetWindowsHookEx(WH_MOUSE_LL, &HookMouseProc, (HINSTANCE) (intptr_t) hInstance, 0);
+    DBG_PRINT("**** LLMP Hook %p, MP Hook %p\n", hookLLMP, hookMP);
+#endif
+
     return (jlong) (intptr_t) window;
 }
 
@@ -1564,7 +1764,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
 {
     HWND hwndP = (HWND) (intptr_t) parent;
     HWND hwnd = (HWND) (intptr_t) window;
-    DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
+    DWORD windowStyle = WS_DEFAULT_STYLES;
     BOOL styleChange = TST_FLAG_CHANGE_DECORATION(flags) || TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ;
 
     DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d\n",
@@ -1677,34 +1877,16 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_setPoint
   (JNIEnv *env, jclass clazz, jlong window, jboolean mouseVisible)
 {
     HWND hwnd = (HWND) (intptr_t) window;
-    int res, resOld, i;
-    jboolean b;
-
-    if(JNI_TRUE == mouseVisible) {
-        res = ShowCursor(TRUE);
-        if(res < 0) {
-            i=0;
-            do {
-                resOld = res;
-                res = ShowCursor(TRUE);
-            } while(res!=resOld && res<0 && ++i<10);
-        }
-        b = res>=0 ? JNI_TRUE : JNI_FALSE;
-    } else {
-        res = ShowCursor(FALSE);
-        if(res >= 0) {
-            i=0;
-            do {
-                resOld = res;
-                res = ShowCursor(FALSE);
-            } while(res!=resOld && res>=0 && ++i<10);
-        }
-        b = res<0 ? JNI_TRUE : JNI_FALSE;
-    }
-
-    DBG_PRINT( "*** WindowsWindow: setPointerVisible0: %d, res %d/%d\n", mouseVisible, res, b);
+    WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+    wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+    wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
+    wud->setPointerVisible = mouseVisible ? 1 : -1;
+    SendMessage(hwnd, WM_SETCURSOR, 0, 0);
 
-    return b;
+    return JNI_TRUE;
 }
 
 /*
@@ -1754,7 +1936,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_trackPointer
   (JNIEnv *env, jclass clazz, jlong window)
 {
     HWND hwnd = (HWND) (intptr_t) window;
-    DBG_PRINT( "*** WindowsWindow: trackMouseLeave0\n");
-    NewtWindows_trackPointerLeave(hwnd);
+    BOOL ok = NewtWindows_trackPointerLeave(hwnd);
+    DBG_PRINT( "*** WindowsWindow: trackMouseLeave0: %d\n", ok);
+    #ifdef VERBOSE_ON
+    if(!ok) {
+        int lastError = (int) GetLastError();
+        DBG_PRINT( "*** WindowsWindow: trackMouseLeave0: lastError 0x%X %d\n", lastError, lastError);
+    }
+    #endif
+    (void)ok;
 }
 
diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h
index 4d1a7b5..e58cdb7 100644
--- a/src/newt/native/X11Common.h
+++ b/src/newt/native/X11Common.h
@@ -45,8 +45,10 @@
 
 #include <X11/extensions/Xrandr.h>
 
-#include "jogamp_newt_driver_x11_ScreenDriver.h"
 #include "jogamp_newt_driver_x11_DisplayDriver.h"
+#include "jogamp_newt_driver_x11_ScreenDriver.h"
+#include "jogamp_newt_driver_x11_RandR11.h"
+#include "jogamp_newt_driver_x11_RandR13.h"
 #include "jogamp_newt_driver_x11_WindowDriver.h"
 
 #include "Window.h"
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 3f34a16..e2392a1 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -28,7 +28,7 @@
 
 #include "X11Common.h"
 
-#define USE_SENDIO_DIRECT 1
+// #include <X11/XKBlib.h> // XKB disabled for now
 
 jclass X11NewtWindowClazz = NULL;
 jmethodID insetsChangedID = NULL;
@@ -46,9 +46,7 @@ static jmethodID focusChangedID = NULL;
 static jmethodID reparentNotifyID = NULL;
 static jmethodID windowDestroyNotifyID = NULL;
 static jmethodID windowRepaintID = NULL;
-static jmethodID enqueueMouseEventID = NULL;
 static jmethodID sendMouseEventID = NULL;
-static jmethodID enqueueKeyEventID = NULL;
 static jmethodID sendKeyEventID = NULL;
 static jmethodID requestFocusID = NULL;
 
@@ -56,13 +54,27 @@ static jmethodID requestFocusID = NULL;
  * Keycode
  */
 
+// #define DEBUG_KEYS 1
+
 #define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b))
 
-static jint X11KeySym2NewtVKey(KeySym keySym) {
-    if(IS_WITHIN(keySym,XK_F1,XK_F12)) 
-        return (keySym-XK_F1)+J_VK_F1;
-    if(IS_WITHIN(keySym,XK_KP_0,XK_KP_9)) 
-        return (keySym-XK_KP_0)+J_VK_NUMPAD0;
+/**
+ * QT Reference:
+ *   <http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/kernel/qkeymapper_x11.cpp#line879>
+ */
+static short X11KeySym2NewtVKey(KeySym keySym) {
+    if( IS_WITHIN( keySym, XK_a, XK_z ) ) {
+        return ( keySym - XK_a ) + J_VK_A ;
+    }
+    if( IS_WITHIN( keySym, XK_0, XK_9 ) ) {
+        return ( keySym - XK_0 ) + J_VK_0 ;
+    }
+    if( IS_WITHIN( keySym, XK_KP_0, XK_KP_9 ) ) {
+        return ( keySym - XK_KP_0 ) + J_VK_NUMPAD0 ;
+    }
+    if( IS_WITHIN( keySym, XK_F1, XK_F12 ) ) {
+        return ( keySym - XK_F1 ) + J_VK_F1 ;
+    }
 
     switch(keySym) {
         case XK_Return:
@@ -76,8 +88,6 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
             return J_VK_TAB;
         case XK_Cancel:
             return J_VK_CANCEL;
-        case XK_Clear:
-            return J_VK_CLEAR;
         case XK_Shift_L:
         case XK_Shift_R:
             return J_VK_SHIFT;
@@ -85,8 +95,15 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
         case XK_Control_R:
             return J_VK_CONTROL;
         case XK_Alt_L:
-        case XK_Alt_R:
             return J_VK_ALT;
+        case XK_Alt_R:
+        case XK_ISO_Level3_Shift:
+            return J_VK_ALT_GRAPH;
+        case XK_Super_L:
+        case XK_Super_R:
+            return J_VK_WINDOWS;
+        case XK_Menu:
+            return J_VK_CONTEXT_MENU;
         case XK_Pause:
             return J_VK_PAUSE;
         case XK_Caps_Lock:
@@ -105,6 +122,10 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
         case XK_End:
         case XK_KP_End:
             return J_VK_END;
+        case XK_Begin:
+            return J_VK_BEGIN;
+        case XK_KP_Begin: // NumPad 5 - equal behavior w/ QT/Windows
+            return J_VK_CLEAR;
         case XK_Home:
         case XK_KP_Home:
             return J_VK_HOME;
@@ -132,6 +153,7 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
             return J_VK_DECIMAL;
         case XK_KP_Divide:
             return J_VK_DIVIDE;
+        case XK_Clear: // equal behavior w/ QT
         case XK_Delete:
         case XK_KP_Delete:
             return J_VK_DELETE;
@@ -154,16 +176,27 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
     return keySym;
 }
 
-static jint X11InputState2NewtModifiers(unsigned int xstate, KeySym keySym) {
+#define ShiftCtrlModMask ( ShiftMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask )
+
+static jboolean altGraphDown = JNI_FALSE;
+
+static jint X11InputState2NewtModifiers(unsigned int xstate, jshort javaVKey, jboolean keyDown) {
     jint modifiers = 0;
-    if ( (ControlMask & xstate) != 0 || J_VK_CONTROL == keySym ) {
+    if ( (ControlMask & xstate) != 0 || J_VK_CONTROL == javaVKey ) {
         modifiers |= EVENT_CTRL_MASK;
     }
-    if ( (ShiftMask & xstate) != 0 || J_VK_SHIFT == keySym ) {
+    if ( (ShiftMask & xstate) != 0 || J_VK_SHIFT == javaVKey ) {
         modifiers |= EVENT_SHIFT_MASK;
     }
-    if ( (Mod1Mask & xstate) != 0 || J_VK_ALT == keySym ) {
+    if ( J_VK_ALT == javaVKey ) {
+        altGraphDown = JNI_FALSE;
         modifiers |= EVENT_ALT_MASK;
+    } else if ( (short)J_VK_ALT_GRAPH == javaVKey ) {
+        altGraphDown = keyDown;
+        modifiers |= EVENT_ALT_GRAPH_MASK;
+    } else if ( (Mod1Mask & xstate) != 0 ) {
+        // XK_Alt_L or XK_Alt_R
+        modifiers |= altGraphDown ? EVENT_ALT_GRAPH_MASK : EVENT_ALT_MASK;
     }
     if ( (Button1Mask & xstate) != 0 ) {
         modifiers |= EVENT_BUTTON1_MASK;
@@ -207,6 +240,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
         }
     }
 
+    // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJ)V"); // Variant using XKB
     displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
     getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;");
     dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V");
@@ -218,10 +252,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
     reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V");
     windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z");
     windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V");
-    enqueueMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueMouseEvent", "(ZIIIIII)V");
-    sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(IIIIII)V");
-    enqueueKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueKeyEvent", "(ZIIIC)V");
-    sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(IIIC)V");
+    sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V");
+    sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V");
     requestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "requestFocus", "(Z)V");
 
     if (displayCompletedID == NULL ||
@@ -235,9 +267,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
         reparentNotifyID == NULL ||
         windowDestroyNotifyID == NULL ||
         windowRepaintID == NULL ||
-        enqueueMouseEventID == NULL ||
         sendMouseEventID == NULL ||
-        enqueueKeyEventID == NULL ||
         sendKeyEventID == NULL ||
         requestFocusID == NULL) {
         return JNI_FALSE;
@@ -258,6 +288,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
     Display * dpy = (Display *)(intptr_t)display;
     jlong javaObjectAtom;
     jlong windowDeleteAtom;
+    // jlong kbdHandle; // XKB disabled for now
 
     if(dpy==NULL) {
         NewtCommon_FatalError(env, "invalid display connection..");
@@ -276,10 +307,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
     }
 
     // XSetCloseDownMode(dpy, RetainTemporary); // Just a try ..
+    // kbdHandle = (jlong) (intptr_t) XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd); // XKB disabled for now
 
     DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy);
 
-    (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom);
+    (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom /*, kbdHandle*/); // XKB disabled for now
 }
 
 /*
@@ -288,11 +320,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay
  * Signature: (JJJ)V
  */
 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
-  (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom)
+  (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/)
 {
     Display * dpy = (Display *)(intptr_t)display;
     Atom wm_javaobject_atom = (Atom)javaObjectAtom;
     Atom wm_delete_atom = (Atom)windowDeleteAtom;
+    // XkbDescPtr kbdDesc = (XkbDescPtr)(intptr_t)kbdHandle; // XKB disabled for now
 
     if(dpy==NULL) {
         NewtCommon_FatalError(env, "invalid display connection..");
@@ -302,6 +335,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
     (void) wm_javaobject_atom;
     (void) wm_delete_atom;
 
+    // XkbFreeKeyboard(kbdDesc, XkbAllNamesMask, True); // XKB disabled for now
+
     XSync(dpy, True); // discard all pending events
     DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy);
 }
@@ -309,13 +344,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
 /*
  * Class:     jogamp_newt_driver_x11_DisplayDriver
  * Method:    DispatchMessages
- * Signature: (JIJJ)V
+ * Signature: (JJJ)V
  */
 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0
-  (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom)
+  (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/)
 {
     Display * dpy = (Display *) (intptr_t) display;
     Atom wm_delete_atom = (Atom)windowDeleteAtom;
+    // XkbDescPtr kbdDesc = (XkbDescPtr)(intptr_t)kbdHandle; // XKB disabled for now
     int num_events = 100;
     int autoRepeatModifiers = 0;
 
@@ -323,13 +359,23 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
         return;
     }
 
+    /** XKB disabled for now
+    if( NULL == kbdDesc) {
+        NewtCommon_throwNewRuntimeException(env, "NULL kbd handle, bail out!");
+        return;
+    } */
+
     // Periodically take a break
     while( num_events > 0 ) {
         jobject jwindow = NULL;
         XEvent evt;
         KeySym keySym = 0;
+        KeyCode keyCode = 0;
+        jshort javaVKeyUS = 0;
+        jshort javaVKeyNN = 0;
         jint modifiers = 0;
-        char keyChar = 0;
+        uint16_t keyChar = 0;
+        jstring keyString = NULL;
         char text[255];
 
         // XEventsQueued(dpy, X):
@@ -386,24 +432,69 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
                     autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
                 }
                 // fall through intended
-            case KeyPress:
-                if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
-                    KeySym lower_return = 0, upper_return = 0;
-                    keyChar=text[0];
-                    XConvertCase(keySym, &lower_return, &upper_return);
-                    // always return upper case, set modifier masks (SHIFT, ..)
-                    keySym = X11KeySym2NewtVKey(upper_return);
-                } else {
-                    keyChar=0;
-                    keySym = X11KeySym2NewtVKey(keySym);
+            case KeyPress: {
+                    KeySym shiftedKeySym; // layout depending keySym w/ SHIFT
+                    KeySym unShiftedKeySym; // layout depending keySym w/o SHIFT
+                    unsigned int xkey_state = evt.xkey.state;
+
+                    keyCode = evt.xkey.keycode;
+
+                    // Layout depending keySym w/o SHIFT,
+                    // using fixed group 0 (US default layout)
+                    //
+                    // unsigned int mods_rtrn = 0;
+                    // Bool res = XkbTranslateKeyCode (kbdDesc, keyCode, 0, &mods_rtrn, &keySym); // XKB disabled for now
+                    // if( !res ) {
+                        keySym = XkbKeycodeToKeysym(dpy, keyCode, 0 /* group */, 0 /* shift level */);
+                    // }
+
+                    text[0] = 0; text[1] = 0; text[2] = 0;
+                    int charCount = XLookupString(&evt.xkey, text, 2, &shiftedKeySym, NULL);
+                    if( 1 == charCount ) {
+                        keyChar = 0x00FF & (uint16_t) (text[0]);
+                    } else if( 2 == charCount ) {
+                        // Example: UTF-16: 00DF, UTF-8: c3 9f, LATIN SMALL LETTER SHARP S
+                        keyChar = ( 0x00FF & (uint16_t)(text[0]) ) << 8 | ( 0x00FF & (uint16_t)(text[1]) ); // UTF-16BE
+                        keyString = (*env)->NewStringUTF(env, text);
+                    }
+
+                    #ifdef DEBUG_KEYS
+                    fprintf(stderr, "NEWT X11 Key.0: keyCode 0x%X keySym 0x%X, (shifted: 0x%X)\n",
+                        (int)keyCode, (int)keySym, (int) shiftedKeySym);
+                    #endif
+                    if( IS_WITHIN( shiftedKeySym, XK_KP_Space, XK_KP_9 ) ) {
+                        // Use modded keySym for keypad for US and NN
+                        keySym = shiftedKeySym;
+                        unShiftedKeySym = shiftedKeySym;
+                    } else if( 0 == keyChar ) {
+                        // Use keyCode's keySym for dead-key (aka modifiers, etc)
+                        unShiftedKeySym = keySym;
+                    } else if( 0 == ( evt.xkey.state & ShiftCtrlModMask ) ) {
+                        // Use non modded keySym
+                        unShiftedKeySym = shiftedKeySym;
+                    } else {
+                        evt.xkey.state = evt.xkey.state & ~ShiftCtrlModMask; // clear shift, ctrl and Mod*
+                        XLookupString(&evt.xkey, text, 0, &unShiftedKeySym, NULL);
+                        // unShiftedKeySym = XLookupKeysym(&evt.xkey, 0 /* index ? */);
+                    }
+
+                    javaVKeyNN = X11KeySym2NewtVKey(unShiftedKeySym);
+                    javaVKeyUS = X11KeySym2NewtVKey(keySym);
+                    modifiers |= X11InputState2NewtModifiers(xkey_state, javaVKeyNN, evt.type == KeyPress) | autoRepeatModifiers;
+
+                    #ifdef DEBUG_KEYS
+                    fprintf(stderr, "NEWT X11 Key.X: keyCode 0x%X keySym 0x%X, (0x%X, shifted: 0x%X), keyChar '%c' 0x%X %d, javaVKey[US 0x%X, NN 0x%X], xstate 0x%X %u, jmods 0x%X\n",
+                        (int)keyCode, (int)keySym, (int) unShiftedKeySym, (int)shiftedKeySym, keyChar, keyChar, charCount,
+                        (int)javaVKeyUS, (int)javaVKeyNN,
+                        (int)xkey_state, (int)xkey_state, (int)modifiers);
+                    #endif
                 }
-                modifiers |= X11InputState2NewtModifiers(evt.xkey.state, keySym) | autoRepeatModifiers;
                 break;
 
             case ButtonPress:
             case ButtonRelease:
             case MotionNotify:
-                modifiers |= X11InputState2NewtModifiers(evt.xbutton.state, 0);
+                modifiers |= X11InputState2NewtModifiers(evt.xbutton.state, 0, JNI_FALSE);
                 break;
 
             default:
@@ -413,87 +504,43 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
         switch(evt.type) {
             case ButtonPress:
                 (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
-                #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, 
-                                      modifiers,
-                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
-                #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, 
+                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, 
                                       modifiers,
-                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
-                #endif
+                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/);
                 break;
             case ButtonRelease:
-                #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, 
+                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, 
                                       modifiers,
-                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
-                #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, 
-                                      modifiers,
-                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
-                #endif
+                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/);
                 break;
             case MotionNotify:
-                #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, 
-                                      modifiers,
-                                      (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); 
-                #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, 
+                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, 
                                       modifiers,
-                                      (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); 
-                #endif
+                                      (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jshort) 0, 0.0f /*rotation*/); 
                 break;
             case EnterNotify:
                 DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
-                #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED, 
-                                      modifiers,
-                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); 
-                #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED, 
+                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED, 
                                       modifiers,
-                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); 
-                #endif
+                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); 
                 break;
             case LeaveNotify:
                 DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
-                #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED, 
+                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED, 
                                       modifiers,
-                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); 
-                #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED, 
-                                      modifiers,
-                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); 
-                #endif
+                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); 
+                break;
+            case MappingNotify:
+                DBG_PRINT( "X11: event . MappingNotify call %p type %d\n", (void*)evt.xmapping.window, evt.xmapping.type);
+                XRefreshKeyboardMapping(&evt.xmapping);
                 break;
             case KeyPress:
-                #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, 
-                                      modifiers, keySym, (jchar) keyChar);
-                #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, 
-                                      modifiers, keySym, (jchar) keyChar);
-                #endif
-
+                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, 
+                                      modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString);
                 break;
             case KeyRelease:
-                #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, 
-                                      modifiers, keySym, (jchar) keyChar);
-
-                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED, 
-                                      modifiers, keySym, (jchar) keyChar);
-                #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, 
-                                      modifiers, keySym, (jchar) keyChar);
-
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED, 
-                                      modifiers, keySym, (jchar) keyChar);
-                #endif
-
+                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, 
+                                      modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString);
                 break;
             case DestroyNotify:
                 DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n", 
diff --git a/src/newt/native/X11Event.c b/src/newt/native/X11Event.c
index 0792034..32a55c6 100644
--- a/src/newt/native/X11Event.c
+++ b/src/newt/native/X11Event.c
@@ -103,33 +103,33 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                 #ifdef USE_SENDIO_DIRECT
                 (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, 
                                       modifiers,
-                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
                 #else
                 (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, 
                                       modifiers,
-                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
                 #endif
                 break;
             case ButtonRelease:
                 #ifdef USE_SENDIO_DIRECT
                 (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, 
                                       modifiers,
-                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
                 #else
                 (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, 
                                       modifiers,
-                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
+                                      (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
                 #endif
                 break;
             case MotionNotify:
                 #ifdef USE_SENDIO_DIRECT
                 (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, 
                                       modifiers,
-                                      (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); 
+                                      (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/); 
                 #else
                 (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, 
                                       modifiers,
-                                      (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); 
+                                      (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/); 
                 #endif
                 break;
             case EnterNotify:
@@ -137,11 +137,11 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                 #ifdef USE_SENDIO_DIRECT
                 (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED, 
                                       modifiers,
-                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); 
+                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); 
                 #else
                 (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED, 
                                       modifiers,
-                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); 
+                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); 
                 #endif
                 break;
             case LeaveNotify:
@@ -149,11 +149,11 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                 #ifdef USE_SENDIO_DIRECT
                 (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED, 
                                       modifiers,
-                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); 
+                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); 
                 #else
                 (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED, 
                                       modifiers,
-                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); 
+                                      (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); 
                 #endif
                 break;
             case KeyPress:
@@ -170,15 +170,9 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                 #ifdef USE_SENDIO_DIRECT
                 (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, 
                                       modifiers, keySym, (jchar) -1);
-
-                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED, 
-                                      modifiers, keySym, (jchar) keyChar);
                 #else
                 (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, 
                                       modifiers, keySym, (jchar) -1);
-
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED, 
-                                      modifiers, keySym, (jchar) keyChar);
                 #endif
 
                 break;
diff --git a/src/newt/native/X11ScreenRandR11.c b/src/newt/native/X11RandR11.c
similarity index 60%
rename from src/newt/native/X11ScreenRandR11.c
rename to src/newt/native/X11RandR11.c
index bc7d91d..81a6726 100644
--- a/src/newt/native/X11ScreenRandR11.c
+++ b/src/newt/native/X11RandR11.c
@@ -26,9 +26,14 @@
  * or implied, of JogAmp Community.
  */
 
-#include "X11Common.h"
+#include "X11Screen.h"
 
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getAvailableScreenModeRotations0_RandR11
+/*
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    getAvailableScreenRotations0
+ * Signature: (JI)I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getAvailableScreenRotations0
   (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
 {
     Display *dpy = (Display *) (intptr_t) display;
@@ -38,11 +43,6 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getAvailabl
     int rotations[4];
     int major, minor;
 
-    if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) {
-        fprintf(stderr, "RANDR not available\n");
-        return (*env)->NewIntArray(env, 0);
-    }
-
     rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
 
     if(0 != (rotations_supported & RR_Rotate_0)) {
@@ -73,26 +73,45 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getAvailabl
     return properties;
 }
 
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0_RandR11
+/*
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    getNumScreenResolution0
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getNumScreenResolutions0
   (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
 {
     Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_idx);
+#ifdef DBG_PERF
+    struct timespec t0, t1, td;
+    long td_ms;
+    timespec_now(&t0);
+#endif
     
+#ifdef DBG_PERF
+    timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+    fprintf(stderr, "X11Screen_getNumScreenResolution0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
     int num_sizes;   
     XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
     
-    DBG_PRINT("getNumScreenModeResolutions0: %d\n", num_sizes);
+#ifdef DBG_PERF
+    timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+    fprintf(stderr, "X11Screen_getNumScreenResolution0.2 (XRRSizes): %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+    DBG_PRINT("getNumScreenResolutions0: %p:%d -> %d\n", dpy, (int)scrn_idx, num_sizes);
 
     return num_sizes;
 }
 
 /*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getScreenModeResolutions0_RandR11
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    getScreenResolutions0
  * Signature: (JII)[I
  */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0_RandR11
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenResolution0
   (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
 {
     Display *dpy = (Display *) (intptr_t) display;
@@ -125,11 +144,11 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenMo
 }
 
 /*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getScreenModeRates0_RandR11
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    getScreenRates0
  * Signature: (JII)[I
  */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0_RandR11
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenRates0
   (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
 {
     Display *dpy = (Display *) (intptr_t) display;
@@ -163,123 +182,138 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenMo
 }
 
 /*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getCurrentScreenRate0_RandR11
- * Signature: (JI)I
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    getScreenConfiguration0
+ * Signature: (JI)J
  */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRate0_RandR11
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) 
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenConfiguration0
+  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx) 
 {
     Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_idx);
-    
+    Window root = RootWindow(dpy, (int)screen_idx);
+#ifdef DBG_PERF
+    struct timespec t0, t1, td;
+    long td_ms;
+    timespec_now(&t0);
+#endif
+
+#ifdef DBG_PERF
+    timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+    fprintf(stderr, "X11Screen_getScreenConfiguration0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
     // get current resolutions and frequencies
     XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
-    short original_rate = XRRConfigCurrentRate(conf);
+#ifdef DBG_PERF
+    timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+    fprintf(stderr, "X11Screen_getScreenConfiguration0.2 (XRRGetScreenInfo): %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+    return (jlong) (intptr_t) conf;
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    freeScreenConfiguration0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR11_freeScreenConfiguration0
+  (JNIEnv *env, jclass clazz, jlong screenConfiguration) 
+{
+    XRRFreeScreenConfigInfo( (XRRScreenConfiguration *) (intptr_t) screenConfiguration );
+}
 
-    //free
-    XRRFreeScreenConfigInfo(conf);
+/*
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    getCurrentScreenRate0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenRate0
+  (JNIEnv *env, jclass clazz, jlong screenConfiguration) 
+{
+    XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
     
+    short original_rate = XRRConfigCurrentRate(conf);
     DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate);
 
     return (jint) original_rate;
 }
 
 /*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getCurrentScreenRotation0_RandR11
- * Signature: (JI)I
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    getCurrentScreenRotation0
+ * Signature: (J)I
  */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRotation0_RandR11
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenRotation0
+  (JNIEnv *env, jclass clazz, jlong screenConfiguration)
 {
-    Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_idx);
-    
-    //get current resolutions and frequencies
-    XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
-    
+    XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
     Rotation rotation;
+
     XRRConfigCurrentConfiguration(conf, &rotation);
 
-    //free
-    XRRFreeScreenConfigInfo(conf);
-    
     return NewtScreen_XRotation2Degree(env, rotation);
 }
 
 
 /*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getCurrentScreenResolutionIndex0_RandR11
- * Signature: (JI)I
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    getCurrentScreenResolutionIndex0
+ * Signature: (J)I
  */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenResolutionIndex0_RandR11
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenResolutionIndex0
+  (JNIEnv *env, jclass clazz, jlong screenConfiguration)
 {
-   Display *dpy = (Display *) (intptr_t) display;
-   Window root = RootWindow(dpy, (int)scrn_idx);
+   XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
   
-   // get current resolutions and frequency configuration
-   XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
    short original_rate = XRRConfigCurrentRate(conf);
    
    Rotation original_rotation;
    SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
    
-   //free
-   XRRFreeScreenConfigInfo(conf);
-   
    DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id);
-   return (jint)original_size_id;   
+   return (jint)original_size_id; 
 }
 
 /*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    setCurrentScreenModeStart0_RandR11
- * Signature: (JIIII)Z
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    setCurrentScreenModeStart0
+ * Signature: (JIJIII)Z
  */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModeStart0_RandR11
-  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenModeStart0
+  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenConfiguration, jint resMode_idx, jint freq, jint rotation)
 {
     Display *dpy = (Display *) (intptr_t) display;
+    XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
     Window root = RootWindow(dpy, (int)screen_idx);
 
     int num_sizes;   
     XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
-    XRRScreenConfiguration *conf;
-    int rot;
     
     if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
         NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
     }
 
-    conf = XRRGetScreenInfo(dpy, root);
-   
-    rot = int NewtScreen_Degree2XRotation(env, rotation);
-    
     DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n", 
         resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
 
+    int xrot = NewtScreen_Degree2XRotation(env, rotation);
+    
     XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
 
     XSync(dpy, False);
-    XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime);   
-    XSync(dpy, False);
-
-    //free
-    XRRFreeScreenConfigInfo(conf);
+    XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, xrot, (short)freq, CurrentTime);   
     XSync(dpy, False);
 
     return JNI_TRUE;
 }
 
 /*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    setCurrentScreenModePollEnd0_RandR11
+ * Class:     jogamp_newt_driver_x11_RandR11
+ * Method:    setCurrentScreenModePollEnd0
  * Signature: (J)Z
  */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0_RandR11
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenModePollEnd0
   (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
 {
     Display *dpy = (Display *) (intptr_t) display;
@@ -307,15 +341,22 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentSc
 
         switch (evt.type - randr_event_base) {
             case RRScreenChangeNotify:
-                rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
-                DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n", 
-                            (void*)scn_event->window, (void*)scn_event->root, 
-                            (int)scn_event->size_index, rot, 
-                            scn_event->width, scn_event->height);
-                // done = scn_event->size_index == resMode_idx; // not reliable ..
-                done = rot == rotation && 
-                       scn_event->width == xrrs[resMode_idx].width && 
-                       scn_event->height == xrrs[resMode_idx].height;
+                if(0 < scn_event->rotation ) {
+                    rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
+                    DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(1) %p (root %p) resIdx %d rot %d %dx%d\n", 
+                                (void*)scn_event->window, (void*)scn_event->root, 
+                                (int)scn_event->size_index, rot, 
+                                scn_event->width, scn_event->height);
+                    // done = scn_event->size_index == resMode_idx; // not reliable ..
+                    done = rot == rotation && 
+                           scn_event->width == xrrs[resMode_idx].width && 
+                           scn_event->height == xrrs[resMode_idx].height;
+                } else {
+                    DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(0) %p (root %p) resIdx %d %dx%d\n", 
+                                (void*)scn_event->window, (void*)scn_event->root, 
+                                (int)scn_event->size_index,
+                                scn_event->width, scn_event->height);
+                }
                 break;
             default:
                 DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
diff --git a/src/newt/native/X11RandR13.c b/src/newt/native/X11RandR13.c
new file mode 100644
index 0000000..92c20e8
--- /dev/null
+++ b/src/newt/native/X11RandR13.c
@@ -0,0 +1,515 @@
+/**
+ * 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.
+ */
+
+#include "X11Common.h"
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    getScreenResources0
+ * Signature: (JI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenResources0
+  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx) 
+{
+    Display *dpy = (Display *) (intptr_t) display;
+    Window root = RootWindow(dpy, (int)screen_idx);
+
+    XRRScreenResources *res = XRRGetScreenResourcesCurrent( dpy, root); // 1.3
+    // XRRScreenResources *res = XRRGetScreenResources( dpy, root); // 1.2
+
+    return (jlong) (intptr_t) res;
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    freeScreenResources0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeScreenResources0
+  (JNIEnv *env, jclass clazz, jlong screenResources) 
+{
+    XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+    if( NULL != resources ) {
+        XRRFreeScreenResources( resources );
+    }
+}
+
+#define SAFE_STRING(s) (NULL==s?"":s)
+
+static void dumpOutputs(const char *prefix, Display *dpy, XRRScreenResources *resources, int noutput, RROutput * outputs) {
+    int i, j;
+    fprintf(stderr, "%s %p: Output count %d\n", prefix, resources, noutput);
+    for(i=0; i<noutput; i++) {
+        RROutput output = outputs[i];
+        XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
+        fprintf(stderr, "  Output[%d]: id %#lx, crtx 0x%X, name %s (%d), %lux%lu, ncrtc %d, .., nmode %d (preferred %d)\n", 
+            i, output, xrrOutputInfo->crtc, SAFE_STRING(xrrOutputInfo->name), xrrOutputInfo->nameLen, xrrOutputInfo->mm_width, xrrOutputInfo->mm_height,
+            xrrOutputInfo->ncrtc, xrrOutputInfo->nmode, xrrOutputInfo->npreferred);
+        for(j=0; j<xrrOutputInfo->nmode; j++) {
+            fprintf(stderr, "    Output[%d].Mode[%d].id %#lx\n", i, j, xrrOutputInfo->modes[j]);
+        }
+        XRRFreeOutputInfo (xrrOutputInfo);
+    }
+}
+
+/** Returns vertical refresh rate in hertz */
+static float getVRefresh(XRRModeInfo *mode) {
+    float rate;
+    unsigned int vTotal = mode->vTotal;
+
+    if (mode->modeFlags & RR_DoubleScan) {
+        /* doublescan doubles the number of lines */
+        vTotal *= 2;
+    }
+
+    if (mode->modeFlags & RR_Interlace) {
+        /* interlace splits the frame into two fields */
+        /* the field rate is what is typically reported by monitors */
+        vTotal /= 2;
+    }
+
+    if (mode->hTotal && vTotal) {
+        rate = ( (float) mode->dotClock /
+                 ( (float) mode->hTotal * (float) vTotal )
+               );
+    } else {
+        rate = 0;
+    }
+    return rate;
+}
+
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_dumpInfo0
+  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources)
+{
+    Display * dpy = (Display *) (intptr_t) display;
+    Window root = RootWindow(dpy, (int)screen_idx);
+    XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+    int pos[] = { 0, 0 } ;
+    int i, j, minWidth, minHeight, maxWidth, maxHeight;
+
+    int vs_width = DisplayWidth(dpy, screen_idx);
+    int vs_height = DisplayHeight(dpy, screen_idx);
+    int vs_width_mm = DisplayWidthMM(dpy, screen_idx);
+    int vs_height_mm = DisplayHeightMM(dpy, screen_idx);
+    fprintf(stderr, "ScreenVirtualSize: %dx%d %dx%d mm\n", vs_width, vs_height, vs_width_mm, vs_height_mm);
+
+    XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight, &maxWidth, &maxHeight);
+    fprintf(stderr, "XRRGetScreenSizeRange: %dx%d .. %dx%d\n", minWidth, minHeight, maxWidth, maxHeight);
+
+    if( NULL == resources ) {
+        fprintf(stderr, "XRRScreenResources NULL\n");
+        return;
+    }
+    fprintf(stderr, "XRRScreenResources %p: Crtc count %d\n", resources, resources->ncrtc);
+    for(i=0; i<resources->ncrtc; i++) {
+        RRCrtc crtc = resources->crtcs[i];
+        XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc);
+        fprintf(stderr, "Crtc[%d]: %d/%d %dx%d, rot 0x%X, mode.id %#lx\n", 
+            i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height, xrrCrtcInfo->rotations, xrrCrtcInfo->mode);
+        for(j=0; j<xrrCrtcInfo->noutput; j++) {
+            fprintf(stderr, "    Crtc[%d].Output[%d].id %#lx\n", i, j, xrrCrtcInfo->outputs[j]);
+        }
+        XRRFreeCrtcInfo(xrrCrtcInfo);
+    }
+
+    dumpOutputs("XRRScreenResources.outputs", dpy, resources, resources->noutput, resources->outputs);
+
+    fprintf(stderr, "XRRScreenResources %p: Mode count %d\n", resources, resources->nmode);
+    for(i=0; i<resources->nmode; i++) {
+        XRRModeInfo *mode = &resources->modes[i];
+
+        unsigned int dots = mode->hTotal * mode->vTotal;
+        float refresh = getVRefresh(mode);
+        fprintf(stderr, "Mode[%d, id %#lx]: %ux%u@%f, name %s\n", i, mode->id, mode->width, mode->height, refresh, SAFE_STRING(mode->name));
+    }
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    getMonitorDeviceCount0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDeviceCount0
+  (JNIEnv *env, jclass clazz, jlong screenResources)
+{
+    XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+    return ( NULL != resources ) ? resources->ncrtc : 0;
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    getMonitorInfoHandle0
+ * Signature: (JIJI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorInfoHandle0
+  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint crt_idx) 
+{
+    Display *dpy = (Display *) (intptr_t) display;
+    Window root = RootWindow(dpy, (int)screen_idx);
+    XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+
+    if( NULL == resources || crt_idx >= resources->ncrtc ) {
+        return 0;
+    }
+    RRCrtc crtc = resources->crtcs[crt_idx];
+    XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc);
+
+    return (jlong) (intptr_t) xrrCrtcInfo;
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    freeMonitorInfoHandle0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeMonitorInfoHandle0
+  (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+    XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+    if( NULL != xrrCrtcInfo ) {
+        XRRFreeCrtcInfo( xrrCrtcInfo );
+    }
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    getAvailableRotations0
+ * Signature: (J)I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getAvailableRotations0
+  (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+    XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+    if( NULL == xrrCrtcInfo ) {
+        return NULL;
+    }
+    Rotation rotations_supported = xrrCrtcInfo->rotations;
+
+    int num_rotations = 0;
+    int rotations[4];
+    if(0 != (rotations_supported & RR_Rotate_0)) {
+      rotations[num_rotations++] = 0;
+    }
+    if(0 != (rotations_supported & RR_Rotate_90)) {
+      rotations[num_rotations++] = 90;
+    }
+    if(0 != (rotations_supported & RR_Rotate_180)) {
+      rotations[num_rotations++] = 180;
+    }
+    if(0 != (rotations_supported & RR_Rotate_270)) {
+      rotations[num_rotations++] = 270;
+    }
+
+    jintArray properties = NULL;
+
+    if(num_rotations>0) {
+        properties = (*env)->NewIntArray(env, num_rotations);
+        if (properties == NULL) {
+            NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
+        }
+        
+        // move from the temp structure to the java structure
+        (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
+    }
+        
+    return properties;
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    getMonitorViewport0
+ * Signature: (J)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorViewport0
+  (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+    XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+    if( NULL == xrrCrtcInfo ) {
+        // n/a
+        return NULL;
+    }
+
+    if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+        // disabled
+        return NULL;
+    }
+
+    jsize propCount = 4;
+    jint prop[ propCount ];
+    int propIndex = 0;
+
+    prop[propIndex++] = xrrCrtcInfo->x;
+    prop[propIndex++] = xrrCrtcInfo->y;
+    prop[propIndex++] = xrrCrtcInfo->width;
+    prop[propIndex++] = xrrCrtcInfo->height;
+
+    jintArray properties = (*env)->NewIntArray(env, propCount);
+    if (properties == NULL) {
+        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+    }
+    (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+    
+    return properties;
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    getMonitorMode0
+ * Signature: (JI)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorMode0
+  (JNIEnv *env, jclass clazz, jlong screenResources, jint mode_idx)
+{
+    XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+
+    if( NULL == resources || mode_idx >= resources->nmode ) {
+        return NULL;
+    }
+
+    XRRModeInfo *mode = &resources->modes[mode_idx];
+    unsigned int dots = mode->hTotal * mode->vTotal;
+    int refresh = (int) ( getVRefresh(mode) * 100.0f ); // Hz * 100
+    int flags = 0;
+    if (mode->modeFlags & RR_Interlace) {
+        flags |= FLAG_INTERLACE;
+    }
+    if (mode->modeFlags & RR_DoubleScan) {
+        flags |= FLAG_DOUBLESCAN;
+    }
+
+    jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
+    int propIndex = 0;
+
+    prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+    prop[propIndex++] = mode->width;
+    prop[propIndex++] = mode->height;
+    prop[propIndex++] = 32; // TODO: XRandR > 1.4 may support bpp
+    prop[propIndex++] = refresh;
+    prop[propIndex++] = flags;
+    prop[propIndex++] = mode->id;
+    prop[propIndex++] = -1; // rotation placeholder
+
+    jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
+    if (properties == NULL) {
+        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
+    }
+    (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
+    
+    return properties;
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    getMonitorCurrentMode0
+ * Signature: (JJ)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorCurrentMode0
+  (JNIEnv *env, jclass clazz, jlong screenResources, jlong monitorInfo)
+{
+    XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+    XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+    if( NULL == resources || NULL == xrrCrtcInfo ) {
+        // n/a
+        return NULL;
+    }
+
+    if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+        // disabled
+        return NULL;
+    }
+
+    int modeId = xrrCrtcInfo->mode;
+    XRRModeInfo *mode = NULL;
+    int i;
+    for(i=0; i<resources->nmode; i++) {
+        XRRModeInfo *imode = &resources->modes[i];
+        if( imode->id == modeId ) {
+            mode = imode;
+            break;
+        }
+    }
+    if( NULL == mode ) {
+        // oops ..
+        return NULL;
+    }
+
+    unsigned int dots = mode->hTotal * mode->vTotal;
+    int refresh = (int) ( getVRefresh(mode) * 100.0f ); // Hz * 100
+    int flags = 0;
+    if (mode->modeFlags & RR_Interlace) {
+        flags |= FLAG_INTERLACE;
+    }
+    if (mode->modeFlags & RR_DoubleScan) {
+        flags |= FLAG_DOUBLESCAN;
+    }
+
+    jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
+    int propIndex = 0;
+
+    prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+    prop[propIndex++] = mode->width;
+    prop[propIndex++] = mode->height;
+    prop[propIndex++] = 32; // TODO: XRandR > 1.4 may support bpp
+    prop[propIndex++] = refresh;
+    prop[propIndex++] = flags;
+    prop[propIndex++] = mode->id;
+    prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation);
+
+    jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
+    if (properties == NULL) {
+        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
+    }
+    (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
+    
+    return properties;
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    getMonitorDevice0
+ * Signature: (JJJJ)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDevice0
+  (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx)
+{
+    Display * dpy = (Display *) (intptr_t) display;
+    XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+    XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+    if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) {
+        // n/a
+        return NULL;
+    }
+
+    if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+        // disabled
+        return NULL;
+    }
+
+    RROutput output = xrrCrtcInfo->outputs[0];
+    XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
+    int numModes = xrrOutputInfo->nmode;
+
+    jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 + numModes;
+    jint prop[ propCount ];
+    int propIndex = 0;
+
+    prop[propIndex++] = propCount;
+    prop[propIndex++] = crt_idx;
+    prop[propIndex++] = xrrOutputInfo->mm_width;
+    prop[propIndex++] = xrrOutputInfo->mm_height;
+    prop[propIndex++] = xrrCrtcInfo->x;
+    prop[propIndex++] = xrrCrtcInfo->y;
+    prop[propIndex++] = xrrCrtcInfo->width;
+    prop[propIndex++] = xrrCrtcInfo->height;
+    prop[propIndex++] = xrrCrtcInfo->mode; // current mode id
+    prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation);
+    int i;
+    for(i=0; i<numModes; i++) {
+        // avail modes ..
+        prop[propIndex++] = xrrOutputInfo->modes[i];
+    }
+
+    XRRFreeOutputInfo (xrrOutputInfo);
+
+    jintArray properties = (*env)->NewIntArray(env, propCount);
+    if (properties == NULL) {
+        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+    }
+    (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+    
+    return properties;
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    setMonitorMode0
+ * Signature: (JJJIIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setMonitorMode0
+  (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx, jint modeId, jint rotation, jint x, jint y)
+{
+    Display * dpy = (Display *) (intptr_t) display;
+    XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+    XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+    jboolean res = JNI_FALSE;
+
+    if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) {
+        // n/a
+        return res;
+    }
+
+    if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+        // disabled
+        return res;
+    }
+
+    if( 0 >= modeId ) {
+        // oops ..
+        return res;
+    }
+
+    if( 0 > x || 0 > y ) {
+        x = xrrCrtcInfo->x;
+        y = xrrCrtcInfo->y;
+    }
+
+    Status status = XRRSetCrtcConfig( dpy, resources, resources->crtcs[crt_idx], CurrentTime, 
+                                      x, y, modeId, NewtScreen_Degree2XRotation(env, rotation),
+                                      xrrCrtcInfo->outputs, xrrCrtcInfo->noutput );
+    res = status == RRSetConfigSuccess;
+
+    return res;
+}
+
+/*
+ * Class:     jogamp_newt_driver_x11_RandR13
+ * Method:    setScreenViewport0
+ * Signature: (JIJIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setScreenViewport0
+  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint x, jint y, jint width, jint height)
+{
+    Display * dpy = (Display *) (intptr_t) display;
+    Window root = RootWindow(dpy, (int)screen_idx);
+    XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+    jboolean res = JNI_FALSE;
+
+    if( NULL == resources ) {
+        // n/a
+        return JNI_FALSE;
+    }
+
+    XRRSetScreenSize (dpy, root, width, height, DisplayWidthMM(dpy, screen_idx), DisplayHeightMM(dpy, screen_idx));
+    return JNI_TRUE;
+}
+
+
diff --git a/src/newt/native/X11Screen.c b/src/newt/native/X11Screen.c
index e8a3ca6..152a092 100644
--- a/src/newt/native/X11Screen.c
+++ b/src/newt/native/X11Screen.c
@@ -29,7 +29,7 @@
 // #define VERBOSE_ON 1
 // #define DBG_PERF 1
 
-#include "X11Common.h"
+#include "X11Screen.h"
 
 #ifdef DBG_PERF
     #include "timespec.h"
@@ -74,425 +74,66 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getHeight0
     return (jint) DisplayHeight( dpy, scrn_idx);
 }
 
-static int showedRandRVersion = 0;
-
-static Bool NewtScreen_getRANDRVersion(Display *dpy, int *major, int *minor) {
-    if( 0 == XRRQueryVersion(dpy, major, minor) ) {
-        return False;
-    }
-    if(0 == showedRandRVersion) {
-        DBG_PRINT("X11 RandR Version %d.%d\n", *major, *minor);
-        showedRandRVersion = 1;
-    }
-    return True;
-}
-
-static Bool NewtScreen_hasRANDR(Display *dpy) {
-    int major, minor;
-    return NewtScreen_getRANDRVersion(dpy, &major, &minor);
-}
-
-static int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
-    int rot;
+int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
+    int degree;
     if(xrotation == RR_Rotate_0) {
-      rot = 0;
+      degree = 0;
     }
     else if(xrotation == RR_Rotate_90) {
-      rot = 90;
+      degree = 90;
     }
     else if(xrotation == RR_Rotate_180) {
-      rot = 180;
+      degree = 180;
     }
     else if(xrotation == RR_Rotate_270) {
-      rot = 270;
+      degree = 270;
     } else {
       NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", xrotation);
     }
-    return rot;
+    return degree;
 }
 
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getAvailableScreenModeRotations0
- * Signature: (JI)I
- */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getAvailableScreenModeRotations0
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_idx);
-    int num_rotations = 0;
-    Rotation cur_rotation, rotations_supported;
-    int rotations[4];
-    int major, minor;
-
-    if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) {
-        fprintf(stderr, "RANDR not available\n");
-        return (*env)->NewIntArray(env, 0);
-    }
-
-    rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
-
-    if(0 != (rotations_supported & RR_Rotate_0)) {
-      rotations[num_rotations++] = 0;
-    }
-    if(0 != (rotations_supported & RR_Rotate_90)) {
-      rotations[num_rotations++] = 90;
-    }
-    if(0 != (rotations_supported & RR_Rotate_180)) {
-      rotations[num_rotations++] = 180;
+int NewtScreen_Degree2XRotation(JNIEnv *env, int degree) {
+    int xrot;
+    if(degree == 0) {
+      xrot = RR_Rotate_0;
     }
-    if(0 != (rotations_supported & RR_Rotate_270)) {
-      rotations[num_rotations++] = 270;
+    else if(degree == 90) {
+      xrot = RR_Rotate_90;
     }
-    
-    jintArray properties = NULL;
-
-    if(num_rotations>0) {
-        properties = (*env)->NewIntArray(env, num_rotations);
-        if (properties == NULL) {
-            NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
-        }
-        
-        // move from the temp structure to the java structure
-        (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
-    }
-        
-    return properties;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getNumScreenModeResolution0
- * Signature: (JI)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-#ifdef DBG_PERF
-    struct timespec t0, t1, td;
-    long td_ms;
-    timespec_now(&t0);
-#endif
-    
-    if(False == NewtScreen_hasRANDR(dpy)) {
-        DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0: RANDR not available\n");
-        return 0;
+    else if(degree == 180) {
+      xrot = RR_Rotate_180;
     }
-
-#ifdef DBG_PERF
-    timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
-    fprintf(stderr, "X11Screen_getNumScreenModeResolution0.1: %ld ms\n", td_ms); fflush(NULL);
-#endif
-
-    int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-    
-#ifdef DBG_PERF
-    timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
-    fprintf(stderr, "X11Screen_getNumScreenModeResolution0.2 (XRRSizes): %ld ms\n", td_ms); fflush(NULL);
-#endif
-
-    DBG_PRINT("getNumScreenModeResolutions0: %p:%d -> %d\n", dpy, (int)scrn_idx, num_sizes);
-
-    return num_sizes;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getScreenModeResolutions0
- * Signature: (JII)[I
- */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    
-    if(False == NewtScreen_hasRANDR(dpy)) {
-        DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0: RANDR not available\n");
-        return (*env)->NewIntArray(env, 0);
-    }
-
-    int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
-    if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
-        NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
-    }
- 
-    // Fill the properties in temp jint array
-    int propIndex = 0;
-    jint prop[4];
-    
-    prop[propIndex++] = xrrs[(int)resMode_idx].width; 
-    prop[propIndex++] = xrrs[(int)resMode_idx].height;
-    prop[propIndex++] = xrrs[(int)resMode_idx].mwidth; 
-    prop[propIndex++] = xrrs[(int)resMode_idx].mheight;
-    
-    jintArray properties = (*env)->NewIntArray(env, 4);
-    if (properties == NULL) {
-        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4);
+    else if(degree == 270) {
+      xrot = RR_Rotate_270;
+    } else {
+      NewtCommon_throwNewRuntimeException(env, "invalid degree: %d", degree);
     }
-    
-    // move from the temp structure to the java structure
-    (*env)->SetIntArrayRegion(env, properties, 0, 4, prop);
-    
-    return properties;
+    return xrot;
 }
 
 /*
  * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getScreenModeRates0
- * Signature: (JII)[I
+ * Method:    GetRandRVersion0
+ * Signature: (J)[I
  */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getRandRVersion0
+  (JNIEnv *env, jclass clazz, jlong display) 
 {
-    Display *dpy = (Display *) (intptr_t) display;
-    
-    if(False == NewtScreen_hasRANDR(dpy)) {
-        DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0: RANDR not available\n");
-        return (*env)->NewIntArray(env, 0);
-    }
-
-    int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
-    if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
-        NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+    Display * dpy = (Display *)(intptr_t)display;
+    jint version[2];
+    if( 0 == XRRQueryVersion(dpy, &version[0], &version[1] ) ) {
+        version[0] = 0;
+        version[1] = 0;
     }
- 
-    int num_rates;
-    short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates);
- 
-    jint prop[num_rates];
-    int i;
-    for(i=0; i<num_rates; i++) {
-        prop[i] = (int) rates[i];
-        /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */
-    }
-    
-    jintArray properties = (*env)->NewIntArray(env, num_rates);
-    if (properties == NULL) {
-        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates);
+    jintArray jversion = (*env)->NewIntArray(env, 2);
+    if (jversion == NULL) {
+        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2");
     }
     
     // move from the temp structure to the java structure
-    (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop);
+    (*env)->SetIntArrayRegion(env, jversion, 0, 2, version);
     
-    return properties;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getScreenConfiguration0
- * Signature: (JI)J
- */
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenConfiguration0
-  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx) 
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)screen_idx);
-#ifdef DBG_PERF
-    struct timespec t0, t1, td;
-    long td_ms;
-    timespec_now(&t0);
-#endif
-
-    if(False == NewtScreen_hasRANDR(dpy)) {
-        DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_getScreenConfiguration0: RANDR not available\n");
-        return 0;
-    }
-#ifdef DBG_PERF
-    timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
-    fprintf(stderr, "X11Screen_getScreenConfiguration0.1: %ld ms\n", td_ms); fflush(NULL);
-#endif
-
-    // get current resolutions and frequencies
-    XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
-#ifdef DBG_PERF
-    timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
-    fprintf(stderr, "X11Screen_getScreenConfiguration0.2 (XRRGetScreenInfo): %ld ms\n", td_ms); fflush(NULL);
-#endif
-
-    return (jlong) (intptr_t) conf;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    freeScreenConfiguration0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_freeScreenConfiguration0
-  (JNIEnv *env, jclass clazz, jlong screenConfiguration) 
-{
-    XRRFreeScreenConfigInfo( (XRRScreenConfiguration *) (intptr_t) screenConfiguration );
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getCurrentScreenRate0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRate0
-  (JNIEnv *env, jclass clazz, jlong screenConfiguration) 
-{
-    XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
-    
-    short original_rate = XRRConfigCurrentRate(conf);
-    DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate);
-
-    return (jint) original_rate;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getCurrentScreenRotation0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRotation0
-  (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
-    XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
-    Rotation rotation;
-
-    XRRConfigCurrentConfiguration(conf, &rotation);
-
-    return NewtScreen_XRotation2Degree(env, rotation);
-}
-
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getCurrentScreenResolutionIndex0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenResolutionIndex0
-  (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
-   XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
-  
-   short original_rate = XRRConfigCurrentRate(conf);
-   
-   Rotation original_rotation;
-   SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
-   
-   DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id);
-   return (jint)original_size_id; 
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    setCurrentScreenModeStart0
- * Signature: (JIJIII)Z
- */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModeStart0
-  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenConfiguration, jint resMode_idx, jint freq, jint rotation)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
-    Window root = RootWindow(dpy, (int)screen_idx);
-
-    int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
-    int rot;
-    
-    if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
-        NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
-    }
-
-    switch(rotation) {
-        case   0:
-            rot = RR_Rotate_0; 
-            break;
-        case  90:
-            rot = RR_Rotate_90; 
-            break;
-        case 180:
-            rot = RR_Rotate_180; 
-            break;
-        case 270:
-            rot = RR_Rotate_270; 
-            break;
-        default:
-            NewtCommon_throwNewRuntimeException(env, "Invalid rotation: %d", rotation);
-    }
-    
-    DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n", 
-        resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
-
-    XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
-
-    XSync(dpy, False);
-    XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime);   
-    XSync(dpy, False);
-
-    return JNI_TRUE;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    setCurrentScreenModePollEnd0
- * Signature: (J)Z
- */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0
-  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    int randr_event_base, randr_error_base;
-    XEvent evt;
-    XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
-
-    if(False == NewtScreen_hasRANDR(dpy)) {
-        DBG_PRINT("Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0: RANDR not available\n");
-        return JNI_FALSE;
-    }
-
-    int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
-    XRRScreenConfiguration *conf;
-    
-    if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
-        NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
-    }
-
-    XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
-
-    int done = 0;
-    int rot;
-    do {
-        if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
-            return;
-        }
-        XNextEvent(dpy, &evt);
-
-        switch (evt.type - randr_event_base) {
-            case RRScreenChangeNotify:
-                if(0 < scn_event->rotation ) {
-                    rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
-                    DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(1) %p (root %p) resIdx %d rot %d %dx%d\n", 
-                                (void*)scn_event->window, (void*)scn_event->root, 
-                                (int)scn_event->size_index, rot, 
-                                scn_event->width, scn_event->height);
-                    // done = scn_event->size_index == resMode_idx; // not reliable ..
-                    done = rot == rotation && 
-                           scn_event->width == xrrs[resMode_idx].width && 
-                           scn_event->height == xrrs[resMode_idx].height;
-                } else {
-                    DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(0) %p (root %p) resIdx %d %dx%d\n", 
-                                (void*)scn_event->window, (void*)scn_event->root, 
-                                (int)scn_event->size_index,
-                                scn_event->width, scn_event->height);
-                }
-                break;
-            default:
-                DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
-        }
-        XRRUpdateConfiguration(&evt);
-    } while(!done);
-
-    XSync(dpy, False);
-
+    return jversion;
 }
 
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java b/src/newt/native/X11Screen.h
similarity index 82%
copy from src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
copy to src/newt/native/X11Screen.h
index 93c8409..c81ee05 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
+++ b/src/newt/native/X11Screen.h
@@ -1,6 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -26,16 +25,14 @@
  * authors and should not be interpreted as representing official policies, either expressed
  * or implied, of JogAmp Community.
  */
- 
-package com.jogamp.newt.event;
 
-public abstract class KeyAdapter implements KeyListener
-{
- public void keyPressed(KeyEvent e) {
- }
- public void keyReleased(KeyEvent e) {
- }
- public void keyTyped(KeyEvent e)  {
- }
-}
+#ifndef _X11SCREEN_H
+#define _X11SCREEN_H
 
+
+#include "X11Common.h"
+
+int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation);
+int NewtScreen_Degree2XRotation(JNIEnv *env, int degree);
+
+#endif /*  _X11SCREEN_H */
diff --git a/src/newt/native/X11ScreenRandR13.c b/src/newt/native/X11ScreenRandR13.c
deleted file mode 100644
index da90d15..0000000
--- a/src/newt/native/X11ScreenRandR13.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/**
- * 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.
- */
-
-#include "X11Common.h"
-
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getOrigin0_RandR13
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
-    Display * dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_idx);
-    int pos[] = { 0, 0 } ;
-
-    int i;
-    XRRScreenResources *xrrScreenResources = XRRGetScreenResources(dpy, root);
-    fprintf(stderr, "XRRScreenResources %p: RRCrtc crtcs %d\n", xrrScreenResources, xrrScreenResources->ncrtc);
-    for(i=0; i<xrrScreenResources->ncrtc; i++) {
-        RRCrtc crtc = xrrScreenResources->crtcs[i];
-        XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, xrrScreenResources, crtc);
-        fprintf(stderr, "RRCrtc %d: %d/%d %dx%d\n", i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height);
-        XRRFreeCrtcInfo(xrrCrtcInfo);
-    }
-
-    jintArray jpos = (*env)->NewIntArray(env, num_rotations);
-    if (properties == NULL) {
-        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 2);
-    }
-        
-    // move from the temp structure to the java structure
-    (*env)->SetIntArrayRegion(env, jpos, 0, 2, pos);
-    return jpos;
-}
-
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getAvailableScreenModeRotations0_RandR13
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_idx);
-    int num_rotations = 0;
-    Rotation cur_rotation, rotations_supported;
-    int rotations[4];
-    int major, minor;
-
-    if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) {
-        fprintf(stderr, "RANDR not available\n");
-        return (*env)->NewIntArray(env, 0);
-    }
-
-    rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
-
-    if(0 != (rotations_supported & RR_Rotate_0)) {
-      rotations[num_rotations++] = 0;
-    }
-    if(0 != (rotations_supported & RR_Rotate_90)) {
-      rotations[num_rotations++] = 90;
-    }
-    if(0 != (rotations_supported & RR_Rotate_180)) {
-      rotations[num_rotations++] = 180;
-    }
-    if(0 != (rotations_supported & RR_Rotate_270)) {
-      rotations[num_rotations++] = 270;
-    }
-    
-    jintArray properties = NULL;
-
-    if(num_rotations>0) {
-        properties = (*env)->NewIntArray(env, num_rotations);
-        if (properties == NULL) {
-            NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
-        }
-        
-        // move from the temp structure to the java structure
-        (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
-    }
-        
-    return properties;
-}
-
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getNumScreenModeResolutions0_RandR13
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_idx);
-    
-    int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-    
-    DBG_PRINT("getNumScreenModeResolutions0: %d\n", num_sizes);
-
-    int i;
-    XRRScreenResources *xrrScreenResources = XRRGetScreenResources(dpy, root);
-    fprintf(stderr, "XRRScreenResources %p: RRCrtc crtcs %d\n", xrrScreenResources, xrrScreenResources->ncrtc);
-    for(i=0; i<xrrScreenResources->ncrtc; i++) {
-        RRCrtc crtc = xrrScreenResources->crtcs[i];
-        XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, xrrScreenResources, crtc);
-        fprintf(stderr, "RRCrtc %d: %d/%d %dx%d\n", i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height);
-        XRRFreeCrtcInfo(xrrCrtcInfo);
-    }
-    fprintf(stderr, "XRRScreenResources %p: XRRModeInfo modes %d\n", xrrScreenResources, xrrScreenResources->nmode);
-    for(i=0; i<xrrScreenResources->nmode; i++) {
-        XRRModeInfo xrrModeInfo = xrrScreenResources->modes[i];
-        fprintf(stderr, "XRRModeInfo %d: %dx%d, %s, %X\n", i, xrrModeInfo.width, xrrModeInfo.height, xrrModeInfo.name, xrrModeInfo.id);
-    }
-    XRRFreeScreenResources(xrrScreenResources);
-
-    return num_sizes;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getScreenModeResolutions0_RandR13
- * Signature: (JII)[I
- */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeResolution0_RandR13
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    
-    int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
-    if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
-        NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
-    }
- 
-    // Fill the properties in temp jint array
-    int propIndex = 0;
-    jint prop[4];
-    
-    prop[propIndex++] = xrrs[(int)resMode_idx].width; 
-    prop[propIndex++] = xrrs[(int)resMode_idx].height;
-    prop[propIndex++] = xrrs[(int)resMode_idx].mwidth; 
-    prop[propIndex++] = xrrs[(int)resMode_idx].mheight;
-    
-    jintArray properties = (*env)->NewIntArray(env, 4);
-    if (properties == NULL) {
-        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4);
-    }
-    
-    // move from the temp structure to the java structure
-    (*env)->SetIntArrayRegion(env, properties, 0, 4, prop);
-    
-    return properties;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getScreenModeRates0_RandR13
- * Signature: (JII)[I
- */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getScreenModeRates0_RandR13
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    
-    int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
-    if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
-        NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
-    }
- 
-    int num_rates;
-    short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates);
- 
-    jint prop[num_rates];
-    int i;
-    for(i=0; i<num_rates; i++) {
-        prop[i] = (int) rates[i];
-        /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */
-    }
-    
-    jintArray properties = (*env)->NewIntArray(env, num_rates);
-    if (properties == NULL) {
-        NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates);
-    }
-    
-    // move from the temp structure to the java structure
-    (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop);
-    
-    return properties;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getCurrentScreenRate0_RandR13
- * Signature: (JI)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRate0_RandR13
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) 
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_idx);
-    
-    // get current resolutions and frequencies
-    XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
-    short original_rate = XRRConfigCurrentRate(conf);
-
-    //free
-    XRRFreeScreenConfigInfo(conf);
-    
-    DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate);
-
-    return (jint) original_rate;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getCurrentScreenRotation0_RandR13
- * Signature: (JI)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenRotation0_RandR13
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)scrn_idx);
-    
-    //get current resolutions and frequencies
-    XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
-    
-    Rotation rotation;
-    XRRConfigCurrentConfiguration(conf, &rotation);
-
-    //free
-    XRRFreeScreenConfigInfo(conf);
-    
-    return NewtScreen_XRotation2Degree(env, rotation);
-}
-
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    getCurrentScreenResolutionIndex0_RandR13
- * Signature: (JI)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getCurrentScreenResolutionIndex0_RandR13
-  (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
-   Display *dpy = (Display *) (intptr_t) display;
-   Window root = RootWindow(dpy, (int)scrn_idx);
-  
-   // get current resolutions and frequency configuration
-   XRRScreenConfiguration  *conf = XRRGetScreenInfo(dpy, root);
-   short original_rate = XRRConfigCurrentRate(conf);
-   
-   Rotation original_rotation;
-   SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
-   
-   //free
-   XRRFreeScreenConfigInfo(conf);
-   
-   DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id);
-   return (jint)original_size_id;   
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    setCurrentScreenModeStart0_RandR13
- * Signature: (JIIII)Z
- */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModeStart0_RandR13
-  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    Window root = RootWindow(dpy, (int)screen_idx);
-
-    int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
-    XRRScreenConfiguration *conf;
-    int rot;
-    
-    if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
-        NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
-    }
-
-    conf = XRRGetScreenInfo(dpy, root);
-   
-    rot = int NewtScreen_Degree2XRotation(env, rotation);
-    
-    DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n", 
-        resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
-
-    XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
-
-    XSync(dpy, False);
-    XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime);   
-    XSync(dpy, False);
-
-    //free
-    XRRFreeScreenConfigInfo(conf);
-    XSync(dpy, False);
-
-    return JNI_TRUE;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_ScreenDriver
- * Method:    setCurrentScreenModePollEnd0_RandR13
- * Signature: (J)Z
- */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_setCurrentScreenModePollEnd0_RandR13
-  (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
-{
-    Display *dpy = (Display *) (intptr_t) display;
-    int randr_event_base, randr_error_base;
-    XEvent evt;
-    XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
-
-    int num_sizes;   
-    XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
-    XRRScreenConfiguration *conf;
-    
-    if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
-        NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
-    }
-
-    XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
-
-    int done = 0;
-    int rot;
-    do {
-        if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
-            return;
-        }
-        XNextEvent(dpy, &evt);
-
-        switch (evt.type - randr_event_base) {
-            case RRScreenChangeNotify:
-                rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
-                DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n", 
-                            (void*)scn_event->window, (void*)scn_event->root, 
-                            (int)scn_event->size_index, rot, 
-                            scn_event->width, scn_event->height);
-                // done = scn_event->size_index == resMode_idx; // not reliable ..
-                done = rot == rotation && 
-                       scn_event->width == xrrs[resMode_idx].width && 
-                       scn_event->height == xrrs[resMode_idx].height;
-                break;
-            default:
-                DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
-        }
-        XRRUpdateConfiguration(&evt);
-    } while(!done);
-
-    XSync(dpy, False);
-
-}
-
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 202ad6f..3f50f27 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -438,7 +438,7 @@ Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Wind
     return 0; // Error
 }
 
-static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) {
+static void NewtWindows_requestFocus (Display *dpy, Window w, Bool force) {
     XWindowAttributes xwa;
     Window focus_return;
     int revert_to_return;
@@ -447,7 +447,7 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy,
     XGetInputFocus(dpy, &focus_return, &revert_to_return);
     DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)w, force, focus_return==w);
 
-    if( JNI_TRUE==force || focus_return!=w) {
+    if( True==force || focus_return!=w) {
         DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w);
         XRaiseWindow(dpy, w);
         NewtWindows_setCWAbove(dpy, w);
@@ -671,11 +671,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
  * Signature: (JJ)V
  */
 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
-  (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom)
+  (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/) // XKB disabled for now
 {
     Display * dpy = (Display *) (intptr_t) display;
     Window w = (Window)window;
     jobject jwindow;
+    XWindowAttributes xwa;
 
     if(dpy==NULL) {
         NewtCommon_FatalError(env, "invalid display connection..");
@@ -694,13 +695,18 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
     }
 
     XSync(dpy, False);
+    memset(&xwa, 0, sizeof(XWindowAttributes));
+    XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction
     XSelectInput(dpy, w, 0);
     XUnmapWindow(dpy, w);
 
     // Drain all events related to this window ..
-    Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom);
+    Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
 
     XDestroyWindow(dpy, w);
+    if( None != xwa.colormap ) {
+        XFreeColormap(dpy, xwa.colormap);
+    }
     XSync(dpy, True); // discard all events now, no more handler
 
     (*env)->DeleteGlobalRef(env, jwindow);
@@ -743,7 +749,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
     Bool tempInvisible = ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ) && isVisible ;
     int fsEWMHFlags = 0;
     if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) {
-        fsEWMHFlags |= _NET_WM_FULLSCREEN;
+        if( !TST_FLAG_IS_FULLSCREEN_SPAN(flags) ) { // doesn't work w/ spanning across monitors
+            fsEWMHFlags |= _NET_WM_FULLSCREEN;
+        }
         if( TST_FLAG_IS_FULLSCREEN(flags) ) {
             if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
                 fsEWMHFlags |= _NET_WM_ABOVE; // fs on,  above on
@@ -756,12 +764,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
         fsEWMHFlags |= _NET_WM_ABOVE;         // toggle above
     }
 
-    DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
+    DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d (span %d), alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
         (void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w,
         x, y, width, height, 
         TST_FLAG_CHANGE_PARENTING(flags),   TST_FLAG_HAS_PARENT(flags),
         TST_FLAG_CHANGE_DECORATION(flags),  TST_FLAG_IS_UNDECORATED(flags),
-        TST_FLAG_CHANGE_FULLSCREEN(flags),  TST_FLAG_IS_FULLSCREEN(flags),
+        TST_FLAG_CHANGE_FULLSCREEN(flags),  TST_FLAG_IS_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN_SPAN(flags),
         TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags),
         TST_FLAG_CHANGE_VISIBILITY(flags),  TST_FLAG_IS_VISIBLE(flags), tempInvisible, fsEWMHFlags);
 
@@ -769,9 +777,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
     //          However, we have to consider other cases like reparenting and WM which don't support it.
 
     if( fsEWMHFlags && !TST_FLAG_CHANGE_PARENTING(flags) && isVisible &&
+        !TST_FLAG_IS_FULLSCREEN_SPAN(flags) &&
         ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) {
         Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ;
         if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
+            if ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - restore decoration
+                NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True);
+            }
             #ifdef FS_GRAB_KEYBOARD
             if(TST_FLAG_CHANGE_FULLSCREEN(flags)) {
                 if(TST_FLAG_IS_FULLSCREEN(flags)) {
@@ -866,7 +878,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0
   (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force)
 {
-    NewtWindows_requestFocus ( env, obj, (Display *) (intptr_t) display, (Window)window, force ) ;
+    NewtWindows_requestFocus ( (Display *) (intptr_t) display, (Window)window, JNI_TRUE==force?True:False ) ;
 }
 
 /*
diff --git a/src/newt/native/XCBEvent.c b/src/newt/native/XCBEvent.c
index 77a3380..d02d5a4 100644
--- a/src/newt/native/XCBEvent.c
+++ b/src/newt/native/XCBEvent.c
@@ -129,11 +129,11 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                     #ifdef USE_SENDIO_DIRECT
                     (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, 
                                           modifiers,
-                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0 /*rotation*/);
+                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
                     #else
                     (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, 
                                           modifiers,
-                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0 /*rotation*/);
+                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
                     #endif
                 } break;
             case XCB_BUTTON_RELEASE: {
@@ -141,11 +141,11 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                     #ifdef USE_SENDIO_DIRECT
                     (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, 
                                           modifiers,
-                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0 /*rotation*/);
+                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
                     #else
                     (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, 
                                           modifiers,
-                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0 /*rotation*/);
+                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
                     #endif
                 } break;
             case XCB_MOTION_NOTIFY: {
@@ -153,11 +153,11 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                     #ifdef USE_SENDIO_DIRECT
                     (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, 
                                           modifiers,
-                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0 /*rotation*/);
+                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/);
                     #else
                     (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, 
                                           modifiers,
-                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0 /*rotation*/);
+                                          (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/);
                     #endif
                 } break;
             case XCB_KEY_PRESS: {
@@ -176,15 +176,9 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                 #ifdef USE_SENDIO_DIRECT
                 (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, 
                                       modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
-
-                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED, 
-                                      modifiers, (jint) -1, (jchar) keyChar);
                 #else
                 (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, 
                                       modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
-
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED, 
-                                      modifiers, (jint) -1, (jchar) keyChar);
                 #endif
 
                 } break;
diff --git a/src/newt/native/bcm_vc_iv.c b/src/newt/native/bcm_vc_iv.c
index 0093da4..f3474ee 100644
--- a/src/newt/native/bcm_vc_iv.c
+++ b/src/newt/native/bcm_vc_iv.c
@@ -50,8 +50,6 @@ static jmethodID windowCreatedID = NULL;
 static jmethodID sizeChangedID = NULL;
 static jmethodID visibleChangedID = NULL;
 static jmethodID windowDestroyNotifyID = NULL;
-static jmethodID sendMouseEventID = NULL;
-static jmethodID sendKeyEventID = NULL;
 
 /**
  * Display
@@ -117,14 +115,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_initID
     sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
     visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
     windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
-    sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
-    sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
     if (windowCreatedID == NULL ||
         sizeChangedID == NULL ||
         visibleChangedID == NULL ||
-        windowDestroyNotifyID == NULL ||
-        sendMouseEventID == NULL ||
-        sendKeyEventID == NULL) {
+        windowDestroyNotifyID == NULL) {
         DBG_PRINT( "initIDs failed\n" );
         return JNI_FALSE;
     }
diff --git a/src/test-native/displayMultiple02_mch.c b/src/test-native/displayMultiple02_mch.c
new file mode 100644
index 0000000..c2ab25f
--- /dev/null
+++ b/src/test-native/displayMultiple02_mch.c
@@ -0,0 +1,130 @@
+/**
+ * compile with: gcc -o displayMultiple02 displayMultiple02.c -lX11 -lGL
+ */
+
+#include <stdio.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+static void testOrder(int reverseDestroyOrder, const char * msg);
+
+static int useXLockDisplay = 0;
+
+int main(int nargs, char **vargs) {
+    int arg=1;
+    while(arg<nargs) {
+       if(0 == strcmp(vargs[arg], "-xlock")) {
+          useXLockDisplay = 1;
+       }
+       arg++;
+    }
+    fprintf(stderr, "-xlock    (XLockDisplay): %d\n", useXLockDisplay);
+
+    if( useXLockDisplay ) {
+      XInitThreads();
+    }
+    testOrder(0, "Normal order");
+    testOrder(1, "Reverse order");
+    return 0;
+}
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height);
+
+static void XLOCKDISPLAY(Display *dpy) {
+    if( useXLockDisplay ) {
+        XLockDisplay(dpy);
+    }
+}
+static void XUNLOCKDISPLAY(Display *dpy) {
+    if( useXLockDisplay ) {
+        XUnlockDisplay(dpy);
+    }
+}
+
+void testOrder(int reverseDestroyOrder, const char * msg) {
+    int major, minor;
+    Display *disp1;
+    Window win1;
+    GLXContext ctx1;
+
+    fprintf(stderr, "%s: Create #1\n", msg);
+    disp1 = XOpenDisplay(NULL);
+    XLOCKDISPLAY(disp1);
+      createGLWin(disp1, 200, 200, &win1, &ctx1);
+      useGL(disp1, win1, ctx1, 200, 200);
+    XUNLOCKDISPLAY(disp1);
+
+    if(reverseDestroyOrder) {
+        fprintf(stderr, "%s: Destroy #1.0\n", msg);
+        XLOCKDISPLAY(disp1);
+        fprintf(stderr, "%s: Destroy #1.1\n", msg);
+          glXMakeCurrent(disp1, 0, 0);
+          fprintf(stderr, "%s: Destroy #1.2\n", msg);
+          glXDestroyContext(disp1, ctx1);
+          fprintf(stderr, "%s: Destroy #1.3\n", msg);
+        XUNLOCKDISPLAY(disp1);
+        fprintf(stderr, "%s: Destroy #1.4\n", msg);
+        XCloseDisplay(disp1);
+        fprintf(stderr, "%s: Destroy #1.X\n", msg);
+    } else {
+        fprintf(stderr, "%s: Destroy #1.0\n", msg);
+        XLOCKDISPLAY(disp1);
+          glXMakeCurrent(disp1, 0, 0);
+          glXDestroyContext(disp1, ctx1);
+        XUNLOCKDISPLAY(disp1);
+        XCloseDisplay(disp1);
+        fprintf(stderr, "%s: Destroy #1.X\n", msg);
+    }
+
+    fprintf(stderr, "%s: Success - no bug\n", msg);
+}
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 4 bits per color and a 16 bit depth buffer */
+static int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, 
+    GLX_RED_SIZE, 4, 
+    GLX_GREEN_SIZE, 4, 
+    GLX_BLUE_SIZE, 4, 
+    GLX_DEPTH_SIZE, 16,
+    None };
+
+void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+    int screen = DefaultScreen(dpy);
+    XVisualInfo *vi = glXChooseVisual(dpy, screen, attrListDbl);
+    Colormap cmap;
+    XSetWindowAttributes attr;
+
+    /* create a GLX context */
+    *rCtx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+    /* create a color map */
+    cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+    attr.colormap = cmap;
+    attr.border_pixel = 0;
+
+    /* create a window in window mode*/
+    attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+        StructureNotifyMask;
+    *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+        0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+        CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+    XMapRaised(dpy, *rWin);
+}
+
+void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height)
+{
+    glXMakeCurrent(dpy, win, ctx);
+    glShadeModel(GL_SMOOTH);
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    glClearDepth(1.0f);
+    glViewport(0, 0, width, height);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glXSwapBuffers(dpy, win);
+    glXMakeCurrent(dpy, 0, 0);
+}
+
diff --git a/src/test-native/displayMultiple02_new_mch.c b/src/test-native/displayMultiple02_new_mch.c
new file mode 100644
index 0000000..f64d414
--- /dev/null
+++ b/src/test-native/displayMultiple02_new_mch.c
@@ -0,0 +1,199 @@
+/**
+ * compile with: gcc -o displayMultiple02 displayMultiple02.c -lX11 -lGL
+ */
+
+#include <stdio.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+static void testOrder(int reverseDestroyOrder, const char * msg);
+
+static int useXLockDisplay = 0;
+
+int main(int nargs, char **vargs) {
+    int arg=1;
+    while(arg<nargs) {
+       if(0 == strcmp(vargs[arg], "-xlock")) {
+          useXLockDisplay = 1;
+       }
+       arg++;
+    }
+    fprintf(stderr, "-xlock    (XLockDisplay): %d\n", useXLockDisplay);
+
+    if( useXLockDisplay ) {
+      XInitThreads();
+    }
+    testOrder(0, "Normal order");
+    testOrder(1, "Reverse order");
+    return 0;
+}
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void createGLWinNew(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height);
+
+static void XLOCKDISPLAY(Display *dpy) {
+    if( useXLockDisplay ) {
+        XLockDisplay(dpy);
+    }
+}
+static void XUNLOCKDISPLAY(Display *dpy) {
+    if( useXLockDisplay ) {
+        XUnlockDisplay(dpy);
+    }
+}
+
+void testOrder(int reverseDestroyOrder, const char * msg) {
+    int major, minor;
+    Display *disp1;
+    Window win1;
+    GLXContext ctx1;
+
+    Display *disp2;
+    Window win2;
+    GLXContext ctx2;
+
+    fprintf(stderr, "%s: Create #1\n", msg);
+    disp1 = XOpenDisplay(NULL);
+    XLOCKDISPLAY(disp1);
+      createGLWinNew(disp1, 200, 200, &win1, &ctx1);
+      useGL(disp1, win1, ctx1, 200, 200);
+    XUNLOCKDISPLAY(disp1);
+
+    fprintf(stderr, "%s: Create #2\n", msg);
+    disp2 = XOpenDisplay(NULL);
+    XLOCKDISPLAY(disp2);
+      createGLWinNew(disp2, 300, 300, &win2, &ctx2);
+      useGL(disp2, win2, ctx2, 300, 300);
+    XUNLOCKDISPLAY(disp2);
+
+    if(reverseDestroyOrder) {
+        fprintf(stderr, "%s: Destroy #2.0\n", msg);
+        XLOCKDISPLAY(disp2);
+          glXMakeCurrent(disp2, 0, 0);
+          glXDestroyContext(disp2, ctx2);
+        XUNLOCKDISPLAY(disp2);
+        XCloseDisplay(disp2);
+        fprintf(stderr, "%s: Destroy #2.X\n", msg);
+
+        fprintf(stderr, "%s: Destroy #1.0\n", msg);
+        XLOCKDISPLAY(disp1);
+        fprintf(stderr, "%s: Destroy #1.1\n", msg);
+          glXMakeCurrent(disp1, 0, 0);
+          fprintf(stderr, "%s: Destroy #1.2\n", msg);
+          glXDestroyContext(disp1, ctx1);
+          fprintf(stderr, "%s: Destroy #1.3\n", msg);
+        XUNLOCKDISPLAY(disp1);
+        fprintf(stderr, "%s: Destroy #1.4\n", msg);
+        XCloseDisplay(disp1);
+        fprintf(stderr, "%s: Destroy #1.X\n", msg);
+    } else {
+        fprintf(stderr, "%s: Destroy #1.0\n", msg);
+        XLOCKDISPLAY(disp1);
+          glXMakeCurrent(disp1, 0, 0);
+          glXDestroyContext(disp1, ctx1);
+        XUNLOCKDISPLAY(disp1);
+        XCloseDisplay(disp1);
+        fprintf(stderr, "%s: Destroy #1.X\n", msg);
+
+        fprintf(stderr, "%s: Destroy #2.0\n", msg);
+        XLOCKDISPLAY(disp2);
+        fprintf(stderr, "%s: Destroy #2.1\n", msg);
+          glXMakeCurrent(disp2, 0, 0);
+          fprintf(stderr, "%s: Destroy #2.2\n", msg);
+          glXDestroyContext(disp2, ctx2);
+          fprintf(stderr, "%s: Destroy #2.3\n", msg);
+        XUNLOCKDISPLAY(disp2);
+        fprintf(stderr, "%s: Destroy #2.4\n", msg);
+        XCloseDisplay(disp2);
+        fprintf(stderr, "%s: Destroy #2.X\n", msg);
+    }
+
+    fprintf(stderr, "%s: Success - no bug\n", msg);
+}
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 4 bits per color and a 16 bit depth buffer */
+static int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, 
+    GLX_RED_SIZE, 4, 
+    GLX_GREEN_SIZE, 4, 
+    GLX_BLUE_SIZE, 4, 
+    GLX_DEPTH_SIZE, 16,
+    None };
+static int attrListDblNew[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+				GLX_RENDER_TYPE, GLX_RGBA_BIT,
+				GLX_DOUBLEBUFFER, True,
+				GLX_BUFFER_SIZE, 24,
+				GLX_DEPTH_SIZE, 24,
+				None };
+
+void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+    int screen = DefaultScreen(dpy);
+    XVisualInfo *vi = glXChooseVisual(dpy, screen, attrListDbl);
+    Colormap cmap;
+    XSetWindowAttributes attr;
+
+    /* create a GLX context */
+    *rCtx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+    /* create a color map */
+    cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+    attr.colormap = cmap;
+    attr.border_pixel = 0;
+
+    /* create a window in window mode*/
+    attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+        StructureNotifyMask;
+    *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+        0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+        CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+    XMapRaised(dpy, *rWin);
+}
+
+void createGLWinNew(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+    int screen = DefaultScreen(dpy);
+    Colormap cmap;
+    XSetWindowAttributes attr;
+    
+    // create configs
+    int nelements;
+    GLXFBConfig *fbconfigs = glXChooseFBConfig(dpy,screen,attrListDblNew,&nelements );
+    
+    // get visual
+    XVisualInfo *vi = glXGetVisualFromFBConfig(dpy,*fbconfigs);
+    
+    /* create a GLX context */
+    *rCtx = glXCreateNewContext(dpy, *fbconfigs, GLX_RGBA_TYPE, 0, GL_TRUE);
+    
+    /* create a color map */
+    cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+    attr.colormap = cmap;
+    attr.border_pixel = 0;
+
+    /* create a window in window mode*/
+    attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+        StructureNotifyMask;
+    *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+        0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+        CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+    XMapRaised(dpy, *rWin);
+}
+
+void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height)
+{
+    glXMakeCurrent(dpy, win, ctx);
+    glShadeModel(GL_SMOOTH);
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    glClearDepth(1.0f);
+    glViewport(0, 0, width, height);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glXSwapBuffers(dpy, win);
+    glXMakeCurrent(dpy, 0, 0);
+}
+
diff --git a/src/test-native/make.sh b/src/test-native/make.sh
index 269f09c..c6d47ff 100755
--- a/src/test-native/make.sh
+++ b/src/test-native/make.sh
@@ -2,6 +2,8 @@
 
 gcc -o displayMultiple01 displayMultiple01.c -lX11 -lGL
 gcc -o displayMultiple02 displayMultiple02.c -lX11 -lGL
+gcc -o displayMultiple02_mch displayMultiple02_mch.c -lX11 -lGL
+gcc -o displayMultiple02_new_mch displayMultiple02_new_mch.c -lX11 -lGL
 gcc -o glExtensionsListGL2 glExtensionsListGL2.c -lX11 -lGL
 gcc -o glExtensionsListGL3 glExtensionsListGL3.c -lX11 -lGL
 gcc -o contextRetargetDrawable01 contextRetargetDrawable01.c -lX11 -lGL
diff --git a/src/test/com/jogamp/opengl/test/android/LauncherUtil.java b/src/test/com/jogamp/opengl/test/android/LauncherUtil.java
index 11416cd..ac69e1e 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 a30262e..3e61e50 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
@@ -54,7 +54,7 @@ public class MovieCubeActivity0 extends NewtBaseActivity {
    MouseAdapter showKeyboardMouseListener = new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent e) {
-           if(e.getPressure()>2f) {
+           if( e.getPointerCount() == 4 && e.getPressure(true) > 0.7f ) {
                ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true);
            }
         }
@@ -82,7 +82,6 @@ public class MovieCubeActivity0 extends NewtBaseActivity {
               
        try {
            final Animator animator = new Animator();
-           setAnimator(animator);
            
            // Main           
            final MovieCube demoMain = new MovieCube(urlConnection0, -2.3f, 0f, 0f);
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java
index c4b74c5..2ea162a 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java
@@ -35,8 +35,8 @@ 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() {
@@ -74,8 +74,14 @@ public class MovieCubeActivityLauncher0 extends LauncherUtil.BaseActivityLaunche
     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/MovieSimpleActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java
index 89395e3..bcff3d5 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity0.java
@@ -82,7 +82,6 @@ public class MovieSimpleActivity0 extends NewtBaseActivity {
               
        try {
            final Animator animator = new Animator();
-           setAnimator(animator);
            
            // Main           
            final MovieSimple demoMain = new MovieSimple(urlConnection0);
diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java
index a7fefd8..cb0fd07 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java
@@ -109,7 +109,6 @@ public class MovieSimpleActivity1 extends NewtBaseActivity {
               
        try {
            final Animator animator = new Animator();
-           setAnimator(animator);
            
            // Main           
            final MovieSimple demoMain = new MovieSimple(urlConnection0);
diff --git a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java
index fbb0223..de4238f 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00a.java
@@ -35,8 +35,8 @@ import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
 public class MovieSimpleActivityLauncher00a extends LauncherUtil.BaseActivityLauncher {
 
     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" };
+    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() {
@@ -76,7 +76,12 @@ public class MovieSimpleActivityLauncher00a extends LauncherUtil.BaseActivityLau
         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/MovieSimpleActivityLauncher00b.java b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java
index 8c08e98..3decf39 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher00b.java
@@ -35,8 +35,8 @@ 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() {
@@ -76,7 +76,12 @@ public class MovieSimpleActivityLauncher00b extends LauncherUtil.BaseActivityLau
         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 b2a3fac..c9f6516 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01a.java
@@ -35,8 +35,8 @@ 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() {
@@ -76,7 +76,12 @@ public class MovieSimpleActivityLauncher01a extends LauncherUtil.BaseActivityLau
         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 905e262..db58f98 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher01b.java
@@ -35,8 +35,8 @@ 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() {
@@ -76,7 +76,12 @@ public class MovieSimpleActivityLauncher01b extends LauncherUtil.BaseActivityLau
         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 3694579..0122fdf 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieSimpleActivityLauncher02.java
@@ -35,8 +35,8 @@ 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() {
@@ -76,7 +76,12 @@ public class MovieSimpleActivityLauncher02 extends LauncherUtil.BaseActivityLaun
         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 d1c8f27..88cd9a7 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;
@@ -58,15 +58,16 @@ public class NEWTElektronActivity extends NewtBaseActivity {
        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 33e05de..527d661 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 c24c3af..f10cfc1 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 d0f6263..dca4531 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 4468868..2e97745 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2Activity.java
@@ -27,15 +27,19 @@
  */
 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.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;
@@ -47,6 +51,10 @@ import android.util.Log;
 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");
@@ -54,33 +62,65 @@ public class NEWTGearsES2Activity extends NewtBaseActivity {
        
        // create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
        GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
+       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
-               ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true);
-           }
-        }
-       });
        
        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);
@@ -88,5 +128,5 @@ public class NEWTGearsES2Activity extends NewtBaseActivity {
        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 415efc7..c87e661 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,7 +49,7 @@ 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");       
@@ -57,17 +57,27 @@ public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLaunc
        // 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.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/NEWTGearsES2ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ECTActivityLauncher.java
similarity index 81%
copy from src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java
copy to src/test/com/jogamp/opengl/test/android/NEWTGearsES2ECTActivityLauncher.java
index 415efc7..fb00ecb 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ECTActivityLauncher.java
@@ -32,11 +32,11 @@ import java.util.List;
 
 import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
 
-public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLauncher {
+public class NEWTGearsES2ECTActivityLauncher 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,7 +49,7 @@ 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");       
@@ -57,9 +57,11 @@ public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLaunc
        // 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", "true");
+       props.setProperty("newt.debug.Window.MouseEvent", "true");
        props.setProperty("newt.debug.Window.KeyEvent", "true");
+       
+       props.setProperty("demo.force.ect", "true");       
     }
     
     @Override
@@ -67,7 +69,12 @@ public class NEWTGearsES2ActivityLauncher 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/NEWTGearsES2ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2RGB565ActivityLauncher.java
similarity index 81%
copy from src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java
copy to src/test/com/jogamp/opengl/test/android/NEWTGearsES2RGB565ActivityLauncher.java
index 415efc7..8acd2c0 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2RGB565ActivityLauncher.java
@@ -32,11 +32,11 @@ import java.util.List;
 
 import com.jogamp.opengl.test.android.LauncherUtil.OrderedProperties;
 
-public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLauncher {
+public class NEWTGearsES2RGB565ActivityLauncher 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,7 +49,7 @@ 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");       
@@ -57,9 +57,11 @@ public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLaunc
        // 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", "true");
+       props.setProperty("newt.debug.Window.MouseEvent", "true");
        props.setProperty("newt.debug.Window.KeyEvent", "true");
+       
+       props.setProperty("demo.force.rgba5650", "true");
     }
     
     @Override
@@ -67,7 +69,12 @@ public class NEWTGearsES2ActivityLauncher 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/NEWTGearsES2TransActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2TransActivity.java
index 9e50a1b..98e6b7c 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;
@@ -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 c29c0c5..e6fe2a2 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 b8bf285..42db9d8 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;
@@ -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 5763058..c18cf16 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java
@@ -7,7 +7,8 @@ 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() {
@@ -37,8 +38,14 @@ public class NEWTGraphUI1pActivityLauncher 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/NEWTGraphUI2pActivity.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI2pActivity.java
index 103af1a..c68de95 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;
@@ -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 8f6b514..501d425 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 a394482..08fbf64 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 478fe65..59bf5ce 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 e850b93..cefdd84 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;
@@ -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);
        
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTRedSquareES2ActivityLauncher.java
index 96299e8..a631eab 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 9bf492e..66889e9 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 0000000..2261a3c
--- /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 at 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 0000000..fe90a4e
--- /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 at 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 0000000..cf5bd39
--- /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 at 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 0000000..3f9bb25
--- /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 at 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 0000000..940cad6
--- /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 at 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 0000000..f443459
--- /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>
+ */
+ at 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 0000000..e8cef5e
--- /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>
+ */
+ at 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 0000000..6340d2b
--- /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>
+ */
+ at 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 0000000..0a4c540
--- /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>
+ */
+ at 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 0000000..f0be22b
--- /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/Issue344Base.java b/src/test/com/jogamp/opengl/test/bugs/Issue344Base.java
index 9b0a4c6..2a7afab 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/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
index b22be0a..b594fab 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java
@@ -50,9 +50,9 @@ 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;
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java
old mode 100755
new mode 100644
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 ff7eb4e..eb2c7bf 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java
@@ -43,8 +43,8 @@ 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;
@@ -54,6 +54,9 @@ 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 float[] textPosition = new float[] {0,0,0};
     static final int[] texSize = new int[] { 0 }; 
@@ -72,10 +75,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();
@@ -91,8 +99,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/demos/GPURegionNewtDemo01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java
old mode 100755
new mode 100644
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 6378c1e..4ebb937 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
@@ -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 7fb199a..3137702 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;
 
 /**
  *
@@ -295,10 +295,13 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
             }
         }
         
-        public void keyTyped(KeyEvent arg0) {
+        public void keyReleased(KeyEvent e) {
+            if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+                return;
+            }            
             if(userInput) {                
-                char c = arg0.getKeyChar();
-                
+                char c = e.getKeyChar();
+
                 if(c == 0x0d) {
                     userInput = false;
                     setIgnoreInput(false);
@@ -309,6 +312,5 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
                 }
             }
         }
-        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 eaac2b1..f43a933 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);
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 bf40390..12c90f8 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 c6d4348..616dd9b 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 15daf70..c94b634 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
@@ -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 2f87fab..c38f8f7 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/InitConcurrentBaseNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java
index 6b2de83..f8e6ee5 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/InitConcurrentBaseNEWT.java
@@ -53,7 +53,7 @@ import com.jogamp.opengl.util.Animator;
  * Rendering is always lock-free and independent of the EDT.
  * </p>
  */
-public class InitConcurrentBaseNEWT extends UITestCase {
+public abstract class InitConcurrentBaseNEWT extends UITestCase {
 
     static final int demoSize = 128;
     
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 8df5498..89de086 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
@@ -29,19 +29,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 +50,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 0000000..c2eebbf
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java
@@ -0,0 +1,287 @@
+/**
+ * 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 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;
+
+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 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
+    {
+
+        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(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);
+        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(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);
+        
+        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 0000000..8b44748
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove02GLWindowNewtCanvasAWT.java
@@ -0,0 +1,285 @@
+/**
+ * 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 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;
+
+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 0000000..981b14a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove03GLWindowNEWT.java
@@ -0,0 +1,144 @@
+/**
+ * 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 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;
+
+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 0000000..7b85291
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.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.GLContext;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import jogamp.opengl.GLContextImpl;
+
+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;
+
+/**
+ * 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>
+ */
+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 0000000..104355a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext02NEWT.java
@@ -0,0 +1,132 @@
+/**
+ * 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 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>
+ */
+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/TestBug692GL3VAO.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug692GL3VAO.java
new file mode 100644
index 0000000..95944cd
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug692GL3VAO.java
@@ -0,0 +1,352 @@
+/**
+ * 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.DebugGL3;
+import javax.media.opengl.GL3;
+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 junit.framework.Assert;
+
+import org.junit.Test;
+
+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.
+ * <p>
+ * testGL3() tests VAO alone, i.e. w/o VBO enable/disabling.
+ * </p>
+ * <p>
+ * testGL3bc() tests VAO and VBO while alternating between both methods.
+ * </p>
+ */
+public class TestBug692GL3VAO extends UITestCase {
+    static long duration = 500; // ms
+    
+    static class GL3VAODemo implements GLEventListener {
+        /** Different modes of displaying the geometry */
+        public enum Mode {
+            /** Traditional one without using VAO */
+            NON_VAO {
+                @Override
+                void display(GL3VAODemo t, GL3 gl) {
+                    t.displayNonVAO(gl);
+                }
+            },
+            
+            /** Using VAOs throws [incorrectly as of JOGL 2.0rc11] a GLException */
+            VAO_NORMAL {
+                @Override
+                void display(GL3VAODemo t, GL3 gl) {
+                    t.displayVAONormal(gl);
+                }
+            };
+            
+            abstract void display(GL3VAODemo t, GL3 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[] vertexData = 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 int ibo = -1;
+        private int vbo = -1;
+        private int vertID = -1;
+        private int fragID = -1;
+        private int progID = -1;
+        
+        private int vaoNormal  = -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);
+            FloatBuffer buffer = GLBuffers.newDirectFloatBuffer(vertexData);
+            assert buffer.remaining() == vertexData.length;
+            gl.glBufferData(GL3.GL_ARRAY_BUFFER, vertexData.length * Buffers.SIZEOF_FLOAT,
+                    buffer, 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;
+            final short[] indices = new short[]{0, 1, 2};
+            ShortBuffer shortBuffer = GLBuffers.newDirectShortBuffer(indices);
+            assert shortBuffer.remaining() == indices.length;
+            gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, ibo);
+            gl.glBufferData(GL3.GL_ELEMENT_ARRAY_BUFFER,indices.length*Buffers.SIZEOF_SHORT,
+                    shortBuffer, GL3.GL_STATIC_DRAW);
+            gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, 0);
+        }
+        private void initShaders(GL3 gl) {
+            final String[] vertSrc = new String[]{
+                "#version 150 core\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 core\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);
+            return vao;
+        }
+    
+        @Override
+        public void init(GLAutoDrawable drawable) {
+            drawable.setGL(new DebugGL3(drawable.getGL().getGL3()));
+            
+            final GL3 gl = drawable.getGL().getGL3();
+            gl.glEnable(GL3.GL_DEPTH_TEST);
+            gl.glDisable(GL3.GL_CULL_FACE);
+            initBuffers(gl);
+            initShaders(gl);
+            
+            vaoNormal  = 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 displayNonVAO(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 displayVAONormal(final GL3 gl) {
+            try {
+                gl.glBindVertexArray(vaoNormal);
+                gl.glDrawElements(GL3.GL_TRIANGLES, 3, GL3.GL_UNSIGNED_SHORT, 0L);
+                gl.glBindVertexArray(0);
+            } catch (GLException ex) {
+                Logger.getLogger(TestBug692GL3VAO.class.getName()).log(Level.SEVERE,null,ex);
+            }
+        }
+        
+        @Override
+        public void display(GLAutoDrawable drawable) {
+            final GL3 gl = drawable.getGL().getGL3();
+            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 testGL3() throws GLException, InterruptedException {
+        if( ! GLProfile.isAvailable(GLProfile.GL3) ) {
+            System.err.println("GL3 n/a");
+            return;
+        }
+        GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.VAO_NORMAL }; 
+        testImpl(GLProfile.get(GLProfile.GL3), modes);        
+    }
+    
+    @Test
+    public void testGL3bc() throws GLException, InterruptedException {
+        if( ! GLProfile.isAvailable(GLProfile.GL3bc) ) {
+            System.err.println("GL3bc n/a");
+            return;
+        }
+        GL3VAODemo.Mode[] modes = new GL3VAODemo.Mode[] { GL3VAODemo.Mode.VAO_NORMAL, GL3VAODemo.Mode.NON_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 = TestBug692GL3VAO.class.getName();
+        org.junit.runner.JUnitCore.main(tstname);
+    }    
+    
+}
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
index eab1a37..4341513 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java
@@ -80,7 +80,7 @@ public class TestFBOAutoDrawableDeadlockAWT 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());
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
index b3c542c..87d4df3 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java
@@ -152,7 +152,10 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase {
         });
         
         glWindow.addKeyListener(new KeyAdapter() {
-            public void keyTyped(KeyEvent e) {
+            public void keyReleased(KeyEvent e) {
+                if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+                    return;
+                }            
                 System.err.println("*** "+e);
                 if(e.getKeyChar()=='f') {
                     new Thread() {
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
index 3ecf89b..19e57c9 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java
@@ -44,6 +44,7 @@ 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;
@@ -136,6 +137,7 @@ public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase {
         {
             GearsES2 demo0 = new GearsES2(-1);
             fbod1.addGLEventListener(demo0);
+            fbod1.addGLEventListener(new GLFinishOnDisplay());            
             demo0.setIgnoreFocus(true);
         }
         fbod1.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() {
@@ -152,6 +154,7 @@ public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase {
                 factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight(), glWindow.getContext());        
         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) {
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
index 7d9a9c6..acd46f5 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java
@@ -43,6 +43,7 @@ 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;
 
@@ -133,6 +134,7 @@ public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase {
         {
             GearsES2 demo0 = new GearsES2(-1);
             fbod1.addGLEventListener(demo0);
+            fbod1.addGLEventListener(new GLFinishOnDisplay());
             demo0.setIgnoreFocus(true);
         }
         fbod1.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() {
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 0000000..2729d6a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java
@@ -0,0 +1,160 @@
+/**
+ * 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 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> 
+ */
+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, drawable.createContext(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
index d9e9b2b..6fc4902 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java
@@ -169,6 +169,11 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
                 }
             };
         
+        window.setWindowDestroyNotifyAction( new Runnable() {
+            public void run() {
+                glad.windowDestroyNotifyOp();
+            } } );
+                
         window.addWindowListener(new WindowAdapter() {
                 @Override
                 public void windowRepaint(WindowUpdateEvent e) {
@@ -179,11 +184,6 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
                 public void windowResized(WindowEvent e) {
                     glad.windowResizedOp(window.getWidth(), window.getHeight());
                 }
-
-                @Override
-                public void windowDestroyNotify(WindowEvent e) {
-                    glad.windowDestroyNotifyOp();
-                }
             });
 
         glad.addGLEventListener(demo);
@@ -235,20 +235,20 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
     }
     
     @Test
-    public void testGL2OnScreenDblBuf() throws InterruptedException {
+    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 testGL2OnScreenSglBuf() throws InterruptedException {
+    public void testGL2OnScreenDblBuf() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
         if(null == reqGLCaps) return;
-        reqGLCaps.setDoubleBuffered(false);
         doTest(reqGLCaps, new GearsES2(1));
     }
-  
+    
     @Test
     public void testGL2OffScreenAutoDblBuf() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
@@ -258,21 +258,21 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
     }
 
     @Test
-    public void testGL2OffScreenFBODblBuf() throws InterruptedException {
+    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 testGL2OffScreenFBOSglBuf() throws InterruptedException {
+    public void testGL2OffScreenFBODblBuf() 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));
     }
     
@@ -306,17 +306,17 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
     }
     
     @Test
-    public void testES2OnScreenDblBuf() throws InterruptedException {
+    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 testES2OnScreenSglBuf() throws InterruptedException {
+    public void testES2OnScreenDblBuf() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
-        reqGLCaps.setDoubleBuffered(false);
         doTest(reqGLCaps, new GearsES2(1));
     }
     
@@ -329,21 +329,21 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
     }
 
     @Test
-    public void testES2OffScreenFBODblBuf() throws InterruptedException {
+    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 testES2OffScreenFBOSglBuf() throws InterruptedException {
+    public void testES2OffScreenFBODblBuf() 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));
     }
     
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java
similarity index 76%
copy from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java
index 51f9cc4..adef9ed 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java
@@ -46,7 +46,6 @@ import org.junit.Test;
 
 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;
 
@@ -57,7 +56,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
  * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}.  
  * </p> 
  */
-public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
+public class TestGLAutoDrawableFactoryES2OffscrnCapsNEWT extends UITestCase {
     static final int widthStep = 800/4;
     static final int heightStep = 600/4;
     volatile int szStep = 2;
@@ -90,9 +89,9 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
         System.out.println("Drawable Caps Pre_GL : "+chosenCaps);
         Assert.assertNotNull(chosenCaps);
-        Assert.assertTrue(chosenCaps.getGreenBits()>5);
-        Assert.assertTrue(chosenCaps.getBlueBits()>5);
-        Assert.assertTrue(chosenCaps.getRedBits()>5);
+        Assert.assertTrue(chosenCaps.getGreenBits()>4);
+        Assert.assertTrue(chosenCaps.getBlueBits()>4);
+        Assert.assertTrue(chosenCaps.getRedBits()>4);
         
         glad.display(); // force native context creation
 
@@ -103,9 +102,9 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         System.out.println("Chosen     GL Caps(2): "+glad.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities());
 
         Assert.assertNotNull(chosenGLCaps);
-        Assert.assertTrue(chosenGLCaps.getGreenBits()>5);
-        Assert.assertTrue(chosenGLCaps.getBlueBits()>5);
-        Assert.assertTrue(chosenGLCaps.getRedBits()>5);
+        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());
@@ -165,16 +164,16 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
     }    
     
     @Test
-    public void testGL2OffScreenAutoDblBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+    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 testGL2OffScreenFBODblBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+    public void testES2OffScreenFBODblBuf() throws InterruptedException {
+        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setFBO(true);
@@ -182,8 +181,8 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
     }
     
     @Test
-    public void testGL2OffScreenFBOSglBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+    public void testES2OffScreenFBOSglBuf() throws InterruptedException {
+        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setFBO(true);
@@ -192,8 +191,8 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
     }    
     
     @Test
-    public void testGL2OffScreenFBOStencil() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+    public void testES2OffScreenFBODblBufStencil() throws InterruptedException {
+        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setFBO(true);
@@ -202,19 +201,31 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
     }
     
     @Test
-    public void testGL2OffScreenFBOStencilMSAA() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+    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 testGL2OffScreenPbufferDblBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+    public void testES2OffScreenPbufferDblBuf() throws InterruptedException {
+        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setPBuffer(true);
@@ -222,8 +233,8 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
     }    
     
     @Test
-    public void testGL2OffScreenPbufferSglBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+    public void testES2OffScreenPbufferSglBuf() throws InterruptedException {
+        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setPBuffer(true);
@@ -231,76 +242,101 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         doTest(reqGLCaps, new GearsES2(1));
     }
     
+    // Might be reduced to !stencil
     @Test
-    public void testGL2OffScreenBitmapSglBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+    public void testES2OffScreenPbufferDblBufStencil() 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));
+        reqGLCaps.setPBuffer(true);
+        reqGLCaps.setStencilBits(1);
+        doTest(reqGLCaps, new GearsES2(1));
     }
     
+    // Might be reduced to !MSAA
     @Test
-    public void testES2OffScreenAutoDblBuf() throws InterruptedException {
+    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 testES2OffScreenFBODblBuf() throws InterruptedException {
+    public void testES2OffScreenPbufferDblBufStencilMSAA() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
-        reqGLCaps.setFBO(true);
+        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 testES2OffScreenFBOSglBuf() throws InterruptedException {
+    public void testES2OffScreenBitmapSglBuf() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
-        reqGLCaps.setFBO(true);
+        reqGLCaps.setBitmap(true);
         reqGLCaps.setDoubleBuffered(false);
-        doTest(reqGLCaps, new GearsES2(1));
+        doTest(reqGLCaps, new Gears(1));
     }
     
+    // Might be reduced to !stencil
     @Test
-    public void testES2OffScreenPbufferDblBuf() throws InterruptedException {
+    public void testES2OffScreenBitmapDblBufStencil() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
-        reqGLCaps.setPBuffer(true);
+        reqGLCaps.setBitmap(true);
+        reqGLCaps.setStencilBits(1);
         doTest(reqGLCaps, new GearsES2(1));
     }
     
+    // Might be reduced to !MSAA
     @Test
-    public void testES2OffScreenPbufferSglBuf() throws InterruptedException {
+    public void testES2OffScreenBitmapDblBufMSAA() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
-        reqGLCaps.setPBuffer(true);
-        reqGLCaps.setDoubleBuffered(false);
+        reqGLCaps.setBitmap(true);
+        reqGLCaps.setSampleBuffers(true);
+        reqGLCaps.setNumSamples(4);
         doTest(reqGLCaps, new GearsES2(1));
-    }
-    
-    /** Not implemented !
+    }    
+        
+    // Might be reduced to !stencil && !MSAA
     @Test
-    public void testES2OffScreenBitmapDblBuf() throws InterruptedException {
-        if(!checkProfile(GLProfile.GLES2)) {
-            return;
-        }
-        final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));        
+    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(TestGLAutoDrawableFactoryOffscrnCapsNEWT.class.getName());
+        org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.class.getName());
     }
 
 }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java
similarity index 68%
copy from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java
index 51f9cc4..80e56f8 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java
@@ -45,7 +45,6 @@ import org.junit.Assert;
 import org.junit.Test;
 
 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;
@@ -57,7 +56,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
  * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}.  
  * </p> 
  */
-public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
+public class TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT extends UITestCase {
     static final int widthStep = 800/4;
     static final int heightStep = 600/4;
     volatile int szStep = 2;
@@ -90,9 +89,9 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
         System.out.println("Drawable Caps Pre_GL : "+chosenCaps);
         Assert.assertNotNull(chosenCaps);
-        Assert.assertTrue(chosenCaps.getGreenBits()>5);
-        Assert.assertTrue(chosenCaps.getBlueBits()>5);
-        Assert.assertTrue(chosenCaps.getRedBits()>5);
+        Assert.assertTrue(chosenCaps.getGreenBits()>4);
+        Assert.assertTrue(chosenCaps.getBlueBits()>4);
+        Assert.assertTrue(chosenCaps.getRedBits()>4);
         
         glad.display(); // force native context creation
 
@@ -103,9 +102,9 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         System.out.println("Chosen     GL Caps(2): "+glad.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities());
 
         Assert.assertNotNull(chosenGLCaps);
-        Assert.assertTrue(chosenGLCaps.getGreenBits()>5);
-        Assert.assertTrue(chosenGLCaps.getBlueBits()>5);
-        Assert.assertTrue(chosenGLCaps.getRedBits()>5);
+        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());
@@ -169,7 +168,7 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
-        doTest(reqGLCaps, new GearsES2(1));
+        doTest(reqGLCaps, new Gears(1));
     }
 
     @Test
@@ -178,7 +177,7 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setFBO(true);
-        doTest(reqGLCaps, new GearsES2(1));
+        doTest(reqGLCaps, new Gears(1));
     }
     
     @Test
@@ -188,28 +187,40 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setFBO(true);
         reqGLCaps.setDoubleBuffered(false);
-        doTest(reqGLCaps, new GearsES2(1));
+        doTest(reqGLCaps, new Gears(1));
     }    
     
     @Test
-    public void testGL2OffScreenFBOStencil() throws InterruptedException {
+    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));
+        doTest(reqGLCaps, new Gears(1));
     }
     
     @Test
-    public void testGL2OffScreenFBOStencilMSAA() throws InterruptedException {
+    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);
-        doTest(reqGLCaps, new GearsES2(1));
+        reqGLCaps.setNumSamples(4);
+        doTest(reqGLCaps, new Gears(1));
     }    
         
     @Test
@@ -218,7 +229,7 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setPBuffer(true);
-        doTest(reqGLCaps, new GearsES2(1));
+        doTest(reqGLCaps, new Gears(1));
     }    
     
     @Test
@@ -228,79 +239,143 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setPBuffer(true);
         reqGLCaps.setDoubleBuffered(false);
-        doTest(reqGLCaps, new GearsES2(1));
+        doTest(reqGLCaps, new Gears(1));
     }
     
+    // Might be reduced to !stencil 
     @Test
-    public void testGL2OffScreenBitmapSglBuf() throws InterruptedException {
+    public void testGL2OffScreenPbufferDblBufStencil() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
-        reqGLCaps.setBitmap(true);
-        reqGLCaps.setDoubleBuffered(false);
+        reqGLCaps.setPBuffer(true);
+        reqGLCaps.setStencilBits(1);
         doTest(reqGLCaps, new Gears(1));
     }
     
+    // Might be reduced to !MSAA
     @Test
-    public void testES2OffScreenAutoDblBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+    public void testGL2OffScreenPbufferDblBufMSAA() throws InterruptedException {
+        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
-        doTest(reqGLCaps, new GearsES2(1));
+        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 testES2OffScreenFBODblBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+    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.setFBO(true);
-        doTest(reqGLCaps, new GearsES2(1));
+        reqGLCaps.setBitmap(true);
+        doTest(reqGLCaps, new Gears(1));
     }
     
     @Test
-    public void testES2OffScreenFBOSglBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+    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.setFBO(true);
-        reqGLCaps.setDoubleBuffered(false);
-        doTest(reqGLCaps, new GearsES2(1));
+        reqGLCaps.setBitmap(true);
+        doTest(reqGLCaps, new Gears(1));
     }
     
     @Test
-    public void testES2OffScreenPbufferDblBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+    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.setPBuffer(true);
-        doTest(reqGLCaps, new GearsES2(1));
+        reqGLCaps.setBitmap(true);
+        doTest(reqGLCaps, new Gears(1));
     }
     
     @Test
-    public void testES2OffScreenPbufferSglBuf() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+    public void testGL2OffScreenBitmapSglBuf() throws InterruptedException {
+        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
-        reqGLCaps.setPBuffer(true);
+        reqGLCaps.setBitmap(true);
         reqGLCaps.setDoubleBuffered(false);
-        doTest(reqGLCaps, new GearsES2(1));
+        doTest(reqGLCaps, new Gears(1));
     }
     
-    /** Not implemented !
+    // Might be reduced to !stencil
     @Test
-    public void testES2OffScreenBitmapDblBuf() throws InterruptedException {
-        if(!checkProfile(GLProfile.GLES2)) {
-            return;
-        }
-        final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));        
+    public void testGL2OffScreenBitmapDblBufStencil() throws InterruptedException {
+        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
+        if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setBitmap(true);
-        doTest(reqGLCaps, new GearsES2(1));
-    } */
-    
+        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(TestGLAutoDrawableFactoryOffscrnCapsNEWT.class.getName());
+        org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.class.getName());
     }
 
 }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java
similarity index 60%
rename from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java
rename to src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java
index 51f9cc4..746b8e1 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java
@@ -45,7 +45,6 @@ import org.junit.Assert;
 import org.junit.Test;
 
 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;
@@ -57,19 +56,11 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
  * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}.  
  * </p> 
  */
-public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
+public class TestGLAutoDrawableFactoryGLnBitmapCapsNEWT 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());
@@ -90,9 +81,9 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
         System.out.println("Drawable Caps Pre_GL : "+chosenCaps);
         Assert.assertNotNull(chosenCaps);
-        Assert.assertTrue(chosenCaps.getGreenBits()>5);
-        Assert.assertTrue(chosenCaps.getBlueBits()>5);
-        Assert.assertTrue(chosenCaps.getRedBits()>5);
+        Assert.assertTrue(chosenCaps.getGreenBits()>4);
+        Assert.assertTrue(chosenCaps.getBlueBits()>4);
+        Assert.assertTrue(chosenCaps.getRedBits()>4);
         
         glad.display(); // force native context creation
 
@@ -103,9 +94,9 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         System.out.println("Chosen     GL Caps(2): "+glad.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities());
 
         Assert.assertNotNull(chosenGLCaps);
-        Assert.assertTrue(chosenGLCaps.getGreenBits()>5);
-        Assert.assertTrue(chosenGLCaps.getBlueBits()>5);
-        Assert.assertTrue(chosenGLCaps.getRedBits()>5);
+        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());
@@ -164,143 +155,28 @@ public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase {
         }
     }    
     
+    // Might be reduced to !double-buff
     @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 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 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 testGL2OffScreenFBOStencil() 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 testGL2OffScreenFBOStencilMSAA() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
-        if(null == reqGLCaps) return;
-        reqGLCaps.setOnscreen(false);
-        reqGLCaps.setFBO(true);
-        reqGLCaps.setStencilBits(1);
-        reqGLCaps.setSampleBuffers(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;
+    public void testGL2OffScreenBitmapDblBuf() throws InterruptedException {
+        final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.getDefault());
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setBitmap(true);
-        reqGLCaps.setDoubleBuffered(false);
         doTest(reqGLCaps, new Gears(1));
     }
     
+    // Might be reduced to !MSAA
     @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 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));        
+    public void testGL2OffScreenBitmapDblBufMSAA() throws InterruptedException {
+        final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.getDefault());
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setBitmap(true);
-        doTest(reqGLCaps, new GearsES2(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(TestGLAutoDrawableFactoryOffscrnCapsNEWT.class.getName());
+        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
index a2ffa90..2df1d3c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java
@@ -57,13 +57,11 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
 
 /**
  * Tests using an AWT {@link GLCanvas} {@link GLAutoDrawable auto drawable} for on- and offscreen cases.
- * <p>
- * The NEWT  {@link GLAutoDrawable} is being used to run the {@link GLEventListener}.  
- * </p> 
  */
 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) {
@@ -247,77 +245,98 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase {
     }
     
     @Test
-    public void testGL2OnScreen() throws InterruptedException {
+    public void testGL2OnScreenDblBuf() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
         if(null == reqGLCaps) return;
         doTest(reqGLCaps, new GearsES2(1));
     }
     
     @Test
-    public void testGL2OffScreenAuto() throws InterruptedException {
+    public void testGL2OnScreenDblBufStencil() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
         if(null == reqGLCaps) return;
-        reqGLCaps.setOnscreen(false);
+        reqGLCaps.setStencilBits(1);
         doTest(reqGLCaps, new GearsES2(1));
     }
-
+    
     @Test
-    public void testGL2OffScreenFBOMSAA() throws InterruptedException {
+    public void testGL2OnScreenDblBufMSAA() 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 testGL2OffScreenPbuffer() throws InterruptedException {
+    public void testGL2OnScreenDblBufStencilMSAA() 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 GearsES2(1));
     }
     
     @Test
-    public void testES2OnScreen() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+    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 testES2OffScreenAuto() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+    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 testES2OffScreenFBOMSAA() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+    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 testES2OffScreenPbuffer() throws InterruptedException {
-        final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+    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
index da54567..0a60566 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java
@@ -189,6 +189,14 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
     }
     
     @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;
@@ -196,10 +204,29 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
     }
     
     @Test
-    public void testGL2OnScreenSglBuf() throws InterruptedException {
+    public void testGL2OnScreenDblBufStencil() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
         if(null == reqGLCaps) return;
-        reqGLCaps.setDoubleBuffered(false);
+        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));
     }
     
@@ -212,6 +239,16 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
     }
 
     @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;
@@ -221,12 +258,35 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
     }
     
     @Test
-    public void testGL2OffScreenFBOSglBuf() throws InterruptedException {
+    public void testGL2OffScreenFBODblBufStencil() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setFBO(true);
-        reqGLCaps.setDoubleBuffered(false);
+        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));
     }
     
@@ -260,6 +320,14 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
     }
     
     @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;
@@ -267,10 +335,29 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
     }
     
     @Test
-    public void testES2OnScreenSglBuf() throws InterruptedException {
+    public void testES2OnScreenDblBufStencil() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
-        reqGLCaps.setDoubleBuffered(false);
+        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));
     }
     
@@ -283,6 +370,16 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
     }
 
     @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;
@@ -292,12 +389,35 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
     }
     
     @Test
-    public void testES2OffScreenFBOSglBuf() throws InterruptedException {
+    public void testES2OffScreenFBODblBufStencil() throws InterruptedException {
         final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
         if(null == reqGLCaps) return;
         reqGLCaps.setOnscreen(false);
         reqGLCaps.setFBO(true);
-        reqGLCaps.setDoubleBuffered(false);
+        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));
     }
     
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
index 37483f7..f4999c0 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java
@@ -266,18 +266,67 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase
     }
     
     @Test
-    public void testGL2OffScreenLayerAuto() throws InterruptedException {
+    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 testGL2OffScreenFBOMSAA() throws InterruptedException {
+    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));
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 0000000..9251120
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java
@@ -0,0 +1,222 @@
+/**
+ * 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;
+
+/**
+ * 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>
+ */
+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 0000000..25b0b93
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java
@@ -0,0 +1,200 @@
+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 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>
+ */
+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.glGetBoundBuffer(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/TestPointsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLPointsNEWT.java
similarity index 97%
rename from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPointsNEWT.java
rename to src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLPointsNEWT.java
index 0ac75d4..692a318 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPointsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLPointsNEWT.java
@@ -43,7 +43,7 @@ import org.junit.BeforeClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
-public class TestPointsNEWT extends UITestCase {
+public class TestGLPointsNEWT extends UITestCase {
     static int width, height;
 
     @BeforeClass
@@ -151,6 +151,6 @@ public class TestPointsNEWT extends UITestCase {
                 } catch (Exception ex) { ex.printStackTrace(); }
             }
         }
-        org.junit.runner.JUnitCore.main(TestPointsNEWT.class.getName());
+        org.junit.runner.JUnitCore.main(TestGLPointsNEWT.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 0000000..a39e68a
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java
@@ -0,0 +1,201 @@
+/**
+ * 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 jogamp.opengl.GLVersionNumber;
+
+import com.jogamp.common.util.VersionNumberString;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+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/TestInitConcurrent01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
index 719d1fc..20c098f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
@@ -44,17 +44,17 @@ import com.jogamp.common.os.Platform;
 public class TestInitConcurrent01NEWT extends InitConcurrentBaseNEWT {
     static boolean mainRun = false;
 
-    @Test
+    @Test(timeout=180000) // TO 3 min
     public void test02TwoThreads() throws InterruptedException {
         runJOGLTasks(2, true);
     }
     
-    @Test
+    @Test(timeout=180000) // TO 3 min
     public void test02FourThreads() throws InterruptedException {
         runJOGLTasks(4, true);
     }
     
-    @Test
+    @Test(timeout=300000) // TO 5 min
     public void test16SixteenThreads() throws InterruptedException {
         if( !mainRun &&
             Platform.getCPUFamily() != Platform.CPUFamily.ARM &&
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
index f2871a6..5b754ef 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent02NEWT.java
@@ -44,7 +44,7 @@ import com.jogamp.common.os.Platform;
 public class TestInitConcurrent02NEWT extends InitConcurrentBaseNEWT {
     static boolean mainRun = false;
     
-    @Test
+    @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");
@@ -53,7 +53,7 @@ public class TestInitConcurrent02NEWT extends InitConcurrentBaseNEWT {
         runJOGLTasks(2, false);
     }
     
-    @Test
+    @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");
@@ -62,7 +62,7 @@ public class TestInitConcurrent02NEWT extends InitConcurrentBaseNEWT {
         runJOGLTasks(4, false);
     }
     
-    @Test
+    @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");
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java
index 9040716..8cc0942 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java
@@ -33,9 +33,7 @@ import java.awt.Button;
 import java.awt.Container;
 import java.awt.Dimension;
 import java.awt.Frame;
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.lang.reflect.InvocationTargetException;
 
 import javax.media.opengl.GLAnimatorControl;
@@ -70,6 +68,7 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
     static Dimension frameSize1;
     static Dimension preferredGLSize;
     static long durationPerTest = 1000;
+    static boolean waitForKey = false;
 
     @BeforeClass
     public static void initClass() {
@@ -189,7 +188,10 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
         
         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) {
@@ -214,7 +216,6 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
     }
 
     public static void main(String args[]) throws IOException {
-        boolean waitForKey = false;
         for(int i=0; i<args.length; i++) {
             if(args[i].equals("-time")) {
                 durationPerTest = atoi(args[++i]);
@@ -234,11 +235,7 @@ public class TestOffscreenLayer01GLCanvasAWT extends UITestCase {
             }
         }
         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");
         }
         String tstname = TestOffscreenLayer01GLCanvasAWT.class.getName();
         /*
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java
index e4a3bce..2236f4b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java
@@ -33,9 +33,7 @@ import java.awt.Button;
 import java.awt.Container;
 import java.awt.Dimension;
 import java.awt.Frame;
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.lang.reflect.InvocationTargetException;
 
 import javax.media.opengl.GLAnimatorControl;
@@ -70,6 +68,7 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
     static Dimension frameSize1;
     static Dimension preferredGLSize;
     static long durationPerTest = 1000;
+    static boolean waitForKey = false;
 
     @BeforeClass
     public static void initClass() {
@@ -79,7 +78,6 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
     }
 
     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);
@@ -169,7 +167,7 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
         Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glWindow1, true));
         Assert.assertEquals(newtCanvasAWT1.getNativeWindow(),glWindow1.getParent());
         Assert.assertEquals(true, newtCanvasAWT1.isOffscreenLayerSurfaceEnabled());
-
+        
         GLAnimatorControl animator1 = new Animator(glWindow1);
         if(!noAnimation) {
             animator1.start();
@@ -187,6 +185,9 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
         Thread.sleep(durationPerTest/2);
         
         end(animator1, frame1, glWindow1);
+        if( waitForKey ) {
+            UITestCase.waitForKey("Continue");
+        }
     }
 
     public static void setDemoFields(GLEventListener demo, GLWindow glWindow, boolean debug) {
@@ -211,7 +212,6 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
     }
 
     public static void main(String args[]) throws IOException {
-        boolean waitForKey = false;
         for(int i=0; i<args.length; i++) {
             if(args[i].equals("-time")) {
                 durationPerTest = atoi(args[++i]);
@@ -231,11 +231,7 @@ public class TestOffscreenLayer02NewtCanvasAWT extends UITestCase {
             }
         }
         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");
         }
         String tstname = TestOffscreenLayer02NewtCanvasAWT.class.getName();
         /*
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 90934f1..3f97cbc 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
@@ -81,7 +81,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());
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 7894f3e..fbea81a 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
@@ -68,6 +68,7 @@ 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;
 
@@ -507,6 +508,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());
@@ -699,7 +702,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) {
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 976885d..afcf51e 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
@@ -54,7 +54,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,6 +61,7 @@ public class TestShutdownCompleteAWT extends UITestCase {
 
         javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
             public void run() {
+                frame.setSize(256, 256);
                 frame.setVisible(true);
             }});
         
@@ -78,7 +78,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() {
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/acore/TestX11DefaultDisplay.java
similarity index 52%
copy from src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/acore/TestX11DefaultDisplay.java
index b0e6b2b..a2c6204 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestRedSquareES1NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestX11DefaultDisplay.java
@@ -26,81 +26,69 @@
  * or implied, of JogAmp Community.
  */
  
-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.UITestCase;
-import com.jogamp.opengl.test.junit.util.QuitAdapter;
-
-import com.jogamp.opengl.util.Animator;
-
-import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1;
+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.AfterClass;
 import org.junit.Test;
 
-public class TestRedSquareES1NEWT extends UITestCase {
-    static int width, height;
-    static boolean forceES2 = false;
-    static boolean forceFFPEmu = false;
+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.
+ *
+ */
+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() {
-        width  = 512;
-        height = 512;
-    }
-
-    @AfterClass
-    public static void releaseClass() {
+        System.setProperty("nativewindow.x11.display.default", x11DefaultDisplay);
     }
 
-    protected void runTestGL(GLCapabilities caps, boolean forceFFPEmu) throws InterruptedException {
-        GLWindow glWindow = GLWindow.create(caps);
+    protected void runTestGL(GLCapabilities caps) throws InterruptedException {
+        final GLWindow glWindow = GLWindow.create(caps);
         Assert.assertNotNull(glWindow);
-        glWindow.setTitle("Gears NEWT Test");
+        glWindow.setTitle(getSimpleTestName("."));
+        glWindow.setSize(width, height);
 
         final RedSquareES1 demo = new RedSquareES1();
-        demo.setForceFFPEmu(forceFFPEmu, forceFFPEmu, false, false);
         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(new TraceKeyAdapter(quitAdapter));
-        //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
         glWindow.addKeyListener(quitAdapter);
         glWindow.addWindowListener(quitAdapter);
 
-        final GLWindow f_glWindow = glWindow;
-        glWindow.addKeyListener(new KeyAdapter() {
-            public void keyTyped(KeyEvent e) {
-                if(e.getKeyChar()=='f') {
-                    new Thread() {
-                        public void run() {
-                            f_glWindow.setFullscreen(!f_glWindow.isFullscreen());
-                    } }.start();
-                } else if(e.getKeyChar()=='d') {
-                    new Thread() {
-                        public void run() {
-                            f_glWindow.setUndecorated(!f_glWindow.isUndecorated());
-                    } }.start();
-                }
-            }
-        });
-
-        glWindow.setSize(width, height);
-        glWindow.setVisible(true);
-        animator.setUpdateFPSFrames(1, null);
         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) {
@@ -112,26 +100,45 @@ public class TestRedSquareES1NEWT extends UITestCase {
     }
 
     @Test
-    public void test00() throws InterruptedException {
-        GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES1());
-        runTestGL(caps, forceFFPEmu);
+    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);
     }
     
-    static long duration = 1000; // 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;
+                duration = MiscUtils.atol(args[i], duration);
+            } else if(args[i].equals("-x11DefaultDisplay")) {
+                x11DefaultDisplay = args[++i];
             }
         }
-        org.junit.runner.JUnitCore.main(TestRedSquareES1NEWT.class.getName());
+        org.junit.runner.JUnitCore.main(TestX11DefaultDisplay.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 0000000..3a03b05
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00.java
@@ -0,0 +1,420 @@
+/**
+ * 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;
+
+/**
+ * ExclusiveContextThread base implementation to test correctness of the ExclusiveContext feature _and_ AnimatorBase. 
+ */
+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 0000000..387f6b7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00AWT.java
@@ -0,0 +1,161 @@
+/**
+ * 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 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. 
+ */
+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 .. CWrapper at NSWindow.isKeyWindow
+        // 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 0000000..43b1e14
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase00NEWT.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.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;
+
+/**
+ * ExclusiveContextThread base implementation to test correctness of the ExclusiveContext feature _and_ AnimatorBase with NEWT. 
+ */
+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 0000000..dc99e49
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10.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.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;
+
+/**
+ * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with AnimatorBase. 
+ */
+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 0000000..fcccafa
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10AWT.java
@@ -0,0 +1,161 @@
+/**
+ * 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 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. 
+ */
+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 .. CWrapper at NSWindow.isKeyWindow
+        // 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 0000000..94a32e2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/ExclusiveContextBase10NEWT.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.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;
+
+/**
+ * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with AnimatorBase and NEWT. 
+ */
+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/TestInitConcurrent01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimAWT.java
similarity index 53%
copy from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimAWT.java
index 719d1fc..25554a8 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimAWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -26,59 +26,45 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.jogl.acore;
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
 
 import java.io.IOException;
 
-import org.junit.Test;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
 
-import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
 
 /**
- * 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>
+ * ExclusiveContextThread VSync Animator to test correctness of the ExclusiveContext feature _and_ Animator with AWT. 
  */
-public class TestInitConcurrent01NEWT extends InitConcurrentBaseNEWT {
-    static boolean mainRun = false;
-
-    @Test
-    public void test02TwoThreads() throws InterruptedException {
-        runJOGLTasks(2, true);
-    }
+public class TestExclusiveContext01VSyncAnimAWT extends ExclusiveContextBase00AWT {    
     
-    @Test
-    public void test02FourThreads() throws InterruptedException {
-        runJOGLTasks(4, true);
-    }
-    
-    @Test
-    public void test16SixteenThreads() throws InterruptedException {
-        if( !mainRun &&
-            Platform.getCPUFamily() != Platform.CPUFamily.ARM &&
-            Platform.getOSType() != Platform.OSType.WINDOWS ) {
-            runJOGLTasks(16, true);
-        } else {
-            runJOGLTasks( 6, true);
-        }
+    @Override
+    protected AnimatorBase createAnimator() {
+        return new Animator();
     }
     
     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")) {
+            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("-showFPS")) {
+                i++;
+                showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ;
+            } else if(args[i].equals("-forceExclusiveTest")) {
+                testExclusiveWithAWT = true;
             }
         }
-        String tstname = TestInitConcurrent01NEWT.class.getName();
-        org.junit.runner.JUnitCore.main(tstname);
-    }
+        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/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimNEWT.java
similarity index 53%
copy from src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimNEWT.java
index 38bd70a..3ea2704 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext01VSyncAnimNEWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -26,37 +26,42 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.nativewindow;
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
 
-import com.jogamp.common.GlueGenVersion;
-import com.jogamp.common.util.JogampVersion;
-import com.jogamp.common.util.VersionUtil;
-import java.util.jar.Manifest;
+import java.io.IOException;
 
-public class NativeWindowVersion extends JogampVersion {
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
 
-    protected static volatile NativeWindowVersion jogampCommonVersionInfo;
 
-    protected NativeWindowVersion(String packageName, Manifest mf) {
-        super(packageName, mf);
+/**
+ * ExclusiveContextThread VSync Animator to test correctness of the ExclusiveContext feature _and_ Animator with NEWT. 
+ */
+public class TestExclusiveContext01VSyncAnimNEWT extends ExclusiveContextBase00NEWT {    
+
+    @Override
+    protected AnimatorBase createAnimator() {
+        return new Animator();
     }
 
-    public static NativeWindowVersion getInstance() {
-        if(null == jogampCommonVersionInfo) { // volatile: ok
-            synchronized(NativeWindowVersion.class) {
-                if( null == jogampCommonVersionInfo ) {
-                    final String packageName = "javax.media.nativewindow";
-                    final Manifest mf = VersionUtil.getManifest(NativeWindowVersion.class.getClassLoader(), packageName);
-                    jogampCommonVersionInfo = new NativeWindowVersion(packageName, mf);
-                }
+    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 ;
             }
         }
-        return jogampCommonVersionInfo;
-    }
+        System.err.println("duration "+duration);
+        System.err.println("showFPS "+showFPS);
+        System.err.println("swapInterval "+swapInterval);
 
-    public static void main(String args[]) {
-        System.err.println(VersionUtil.getPlatformInfo());
-        System.err.println(GlueGenVersion.getInstance());
-        System.err.println(NativeWindowVersion.getInstance());
+        org.junit.runner.JUnitCore.main(TestExclusiveContext01VSyncAnimNEWT.class.getName());
     }
 }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimAWT.java
similarity index 53%
copy from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimAWT.java
index 719d1fc..a91f7e1 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimAWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -26,59 +26,45 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.jogl.acore;
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
 
 import java.io.IOException;
 
-import org.junit.Test;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.FPSAnimator;
 
-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>
+ * ExclusiveContextThread FPS Animator to test correctness of the ExclusiveContext feature _and_ FPSAnimator with AWT. 
  */
-public class TestInitConcurrent01NEWT extends InitConcurrentBaseNEWT {
-    static boolean mainRun = false;
-
-    @Test
-    public void test02TwoThreads() throws InterruptedException {
-        runJOGLTasks(2, true);
-    }
-    
-    @Test
-    public void test02FourThreads() throws InterruptedException {
-        runJOGLTasks(4, true);
-    }
-    
-    @Test
-    public void test16SixteenThreads() throws InterruptedException {
-        if( !mainRun &&
-            Platform.getCPUFamily() != Platform.CPUFamily.ARM &&
-            Platform.getOSType() != Platform.OSType.WINDOWS ) {
-            runJOGLTasks(16, true);
-        } else {
-            runJOGLTasks( 6, true);
-        }
+public class TestExclusiveContext02FPSAnimAWT extends ExclusiveContextBase00AWT {    
+        
+    @Override
+    protected AnimatorBase createAnimator() {
+        return new FPSAnimator(0);
     }
     
     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")) {
+            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++;
-                try {
-                    duration = Integer.parseInt(args[i]);
-                } catch (Exception ex) { ex.printStackTrace(); }
+                showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ;
+            } else if(args[i].equals("-forceExclusiveTest")) {
+                testExclusiveWithAWT = true;
             }
         }
-        String tstname = TestInitConcurrent01NEWT.class.getName();
-        org.junit.runner.JUnitCore.main(tstname);
-    }
+        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/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimNEWT.java
similarity index 53%
copy from src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimNEWT.java
index 38bd70a..c83bfd2 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext02FPSAnimNEWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -26,37 +26,42 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.nativewindow;
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
 
-import com.jogamp.common.GlueGenVersion;
-import com.jogamp.common.util.JogampVersion;
-import com.jogamp.common.util.VersionUtil;
-import java.util.jar.Manifest;
+import java.io.IOException;
 
-public class NativeWindowVersion extends JogampVersion {
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.FPSAnimator;
 
-    protected static volatile NativeWindowVersion jogampCommonVersionInfo;
 
-    protected NativeWindowVersion(String packageName, Manifest mf) {
-        super(packageName, mf);
+/**
+ * ExclusiveContextThread FPS Animator to test correctness of the ExclusiveContext feature _and_ FPSAnimator with NEWT. 
+ */
+public class TestExclusiveContext02FPSAnimNEWT extends ExclusiveContextBase00NEWT {    
+        
+    @Override
+    protected AnimatorBase createAnimator() {
+        return new FPSAnimator(0);
     }
-
-    public static NativeWindowVersion getInstance() {
-        if(null == jogampCommonVersionInfo) { // volatile: ok
-            synchronized(NativeWindowVersion.class) {
-                if( null == jogampCommonVersionInfo ) {
-                    final String packageName = "javax.media.nativewindow";
-                    final Manifest mf = VersionUtil.getManifest(NativeWindowVersion.class.getClassLoader(), packageName);
-                    jogampCommonVersionInfo = new NativeWindowVersion(packageName, mf);
-                }
+    
+    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 ;
             }
         }
-        return jogampCommonVersionInfo;
-    }
+        System.err.println("duration "+duration);
+        System.err.println("showFPS "+showFPS);
+        System.err.println("swapInterval "+swapInterval);
 
-    public static void main(String args[]) {
-        System.err.println(VersionUtil.getPlatformInfo());
-        System.err.println(GlueGenVersion.getInstance());
-        System.err.println(NativeWindowVersion.getInstance());
+        org.junit.runner.JUnitCore.main(TestExclusiveContext02FPSAnimNEWT.class.getName());
     }
 }
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext11VSyncAnimNEWT.java
similarity index 53%
copy from src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext11VSyncAnimNEWT.java
index 38bd70a..7caab62 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowVersion.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext11VSyncAnimNEWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -26,37 +26,41 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.nativewindow;
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
 
-import com.jogamp.common.GlueGenVersion;
-import com.jogamp.common.util.JogampVersion;
-import com.jogamp.common.util.VersionUtil;
-import java.util.jar.Manifest;
+import java.io.IOException;
 
-public class NativeWindowVersion extends JogampVersion {
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
 
-    protected static volatile NativeWindowVersion jogampCommonVersionInfo;
+/**
+ * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with Animator and NEWT. 
+ */
+public class TestExclusiveContext11VSyncAnimNEWT extends ExclusiveContextBase10NEWT {    
 
-    protected NativeWindowVersion(String packageName, Manifest mf) {
-        super(packageName, mf);
+    @Override
+    protected AnimatorBase createAnimator() {
+        return new Animator();
     }
 
-    public static NativeWindowVersion getInstance() {
-        if(null == jogampCommonVersionInfo) { // volatile: ok
-            synchronized(NativeWindowVersion.class) {
-                if( null == jogampCommonVersionInfo ) {
-                    final String packageName = "javax.media.nativewindow";
-                    final Manifest mf = VersionUtil.getManifest(NativeWindowVersion.class.getClassLoader(), packageName);
-                    jogampCommonVersionInfo = new NativeWindowVersion(packageName, mf);
-                }
+    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 ;
             }
         }
-        return jogampCommonVersionInfo;
-    }
+        System.err.println("duration "+duration);
+        System.err.println("showFPS "+showFPS);
+        System.err.println("swapInterval "+swapInterval);
 
-    public static void main(String args[]) {
-        System.err.println(VersionUtil.getPlatformInfo());
-        System.err.println(GlueGenVersion.getInstance());
-        System.err.println(NativeWindowVersion.getInstance());
+        org.junit.runner.JUnitCore.main(TestExclusiveContext11VSyncAnimNEWT.class.getName());
     }
 }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext12FPSAnimNEWT.java
similarity index 53%
copy from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext12FPSAnimNEWT.java
index 719d1fc..798d09b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestInitConcurrent01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/ect/TestExclusiveContext12FPSAnimNEWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -26,59 +26,42 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.jogl.acore;
+package com.jogamp.opengl.test.junit.jogl.acore.ect;
 
 import java.io.IOException;
 
-import org.junit.Test;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.FPSAnimator;
 
-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>
+ * ExclusiveContextThread base implementation to test performance impact of the ExclusiveContext feature with FPSAnimator and NEWT. 
  */
-public class TestInitConcurrent01NEWT extends InitConcurrentBaseNEWT {
-    static boolean mainRun = false;
-
-    @Test
-    public void test02TwoThreads() throws InterruptedException {
-        runJOGLTasks(2, true);
-    }
-    
-    @Test
-    public void test02FourThreads() throws InterruptedException {
-        runJOGLTasks(4, true);
-    }
-    
-    @Test
-    public void test16SixteenThreads() throws InterruptedException {
-        if( !mainRun &&
-            Platform.getCPUFamily() != Platform.CPUFamily.ARM &&
-            Platform.getOSType() != Platform.OSType.WINDOWS ) {
-            runJOGLTasks(16, true);
-        } else {
-            runJOGLTasks( 6, true);
-        }
+public class TestExclusiveContext12FPSAnimNEWT extends ExclusiveContextBase10NEWT {    
+        
+    @Override
+    protected AnimatorBase createAnimator() {
+        return new FPSAnimator(0);
     }
     
     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")) {
+            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++;
-                try {
-                    duration = Integer.parseInt(args[i]);
-                } catch (Exception ex) { ex.printStackTrace(); }
+                showFPS = MiscUtils.atoi(args[i], showFPS ? 1 : 0) == 0 ? false : true ;
             }
         }
-        String tstname = TestInitConcurrent01NEWT.class.getName();
-        org.junit.runner.JUnitCore.main(tstname);
-    }
+        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 0000000..905cbcf
--- /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, null);
+    }
+
+    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 0000000..c670f4c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java
@@ -0,0 +1,143 @@
+/**
+ * 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;
+
+/**
+ * Tests Bug 722
+ * <p>
+ * See Bug 722 - https://jogamp.org/bugzilla/show_bug.cgi?id=722.
+ * </p>
+ */
+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) 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/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java
similarity index 62%
rename from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java
rename to src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java
index 496be3d..5f2b9fb 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java
@@ -26,7 +26,7 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.jogl.acore;
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
 
 import java.io.IOException;
 
@@ -43,11 +43,11 @@ 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 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;
@@ -59,20 +59,27 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-public class TestGLContextDrawableSwitchNEWT extends UITestCase {
-    static GLProfile glp;
-    static GLCapabilities caps;
+/**
+ * Test re-association (switching) of GLContext/GLDrawables,
+ * i.e. ctx1/draw1, ctx2/draw2 -> ctx1/draw2, ctx2/draw1.
+ */
+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() {
-        glp = GLProfile.getGL2ES2();
-        caps = new GLCapabilities(glp);
         width  = 256;
         height = 256;
     }
 
-    /** Note: No GLContext is attached w/ this implementation ! */
     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);
@@ -100,6 +107,11 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
             }            
         };
         
+        window.setWindowDestroyNotifyAction( new Runnable() {
+            public void run() {
+                glad.windowDestroyNotifyOp();
+            } } );
+        
         // add basic window interaction
         window.addWindowListener(new WindowAdapter() {
             @Override
@@ -110,10 +122,6 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
             public void windowResized(WindowEvent e) {
                 glad.windowResizedOp(window.getWidth(), window.getHeight());
             }
-            @Override
-            public void windowDestroyNotify(WindowEvent e) {
-                glad.windowDestroyNotifyOp();
-            }
         });
         window.addWindowListener(wl);
         
@@ -121,28 +129,43 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
     }
         
     @Test(timeout=30000)
-    public void testSwitch2WindowSingleContext() throws InterruptedException {
+    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,
-        // after destroying the prev. context!
+        // destroy the prev. context afterwards.
         {
-            final GLContext oldCtx = glad1.getContext();
+            final GLContext newCtx = glad1.createContext(null);
+            Assert.assertNotNull(newCtx);        
+            final GLContext oldCtx = glad1.setContext(newCtx, true);
             Assert.assertNotNull(oldCtx);
-            oldCtx.destroy();
-            final GLContext singleCtx = glad1.createContext(null);
-            Assert.assertNotNull(singleCtx);        
-            int res = singleCtx.makeCurrent();
+            Assert.assertFalse(oldCtx.isCreated());
+            final int res = newCtx.makeCurrent();
             Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
-            singleCtx.release();
-            glad1.setContext(singleCtx);
+            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);
@@ -157,28 +180,11 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
             if( ( t1 - t0 ) / period > s) {
                 s++;
                 System.err.println(s+" - switch - START "+ ( t1 - t0 ));
-                animator.pause();
 
                 // switch context _and_ the demo synchronously
-                if(0 == s%2) {
-                    final GLEventListener demo = glad2.removeGLEventListener(0);
-                    GLContext ctx1 = glad1.setContext(glad2.getContext());
-                    glad2.setContext(ctx1);
-                    glad1.addGLEventListener(0, demo);
-                } else {
-                    final GLEventListener demo = glad1.removeGLEventListener(0);
-                    GLContext ctx2 = glad2.setContext(glad1.getContext());                    
-                    glad1.setContext(ctx2);
-                    glad2.addGLEventListener(0, demo);
-                }
-                System.err.println(s+" - switch - display-1");
-                glad1.display();
-                System.err.println(s+" - switch - display-2");
-                glad2.display();
-                
-                System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+                GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2);
                 
-                animator.resume();
+                System.err.println(s+" - switch - END "+ ( t1 - t0 ));                
             }
             Thread.sleep(100);
             t1 = System.currentTimeMillis();
@@ -190,8 +196,22 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
     }
     
     @Test(timeout=30000)
-    public void testSwitch2GLWindowOneDemo() throws InterruptedException {
-        GearsES2 gears = new GearsES2(1);
+    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);        
@@ -199,6 +219,7 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
         glWindow1.setSize(width, height);
         glWindow1.setPosition(64, 64);
         glWindow1.addGLEventListener(0, gears);
+        glWindow1.addGLEventListener(snapshotGLEventListener);
         glWindow1.addWindowListener(quitAdapter);
         
         GLWindow glWindow2 = GLWindow.create(caps);                
@@ -215,6 +236,8 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
         glWindow1.setVisible(true);
         glWindow2.setVisible(true);
 
+        snapshotGLEventListener.setMakeSnapshot();
+         
         int s = 0;
         long t0 = System.currentTimeMillis();
         long t1 = t0;
@@ -223,24 +246,17 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
             if( ( t1 - t0 ) / period > s) {
                 s++;
                 System.err.println(s+" - switch - START "+ ( t1 - t0 ));
-                animator.pause();
+                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
-                if(0 == s%2) {
-                    final GLEventListener demo = glWindow2.removeGLEventListener(0);
-                    GLContext ctx1 = glWindow1.setContext(glWindow2.getContext());
-                    glWindow1.addGLEventListener(0, demo);
-                    glWindow2.setContext(ctx1);
-                } else {
-                    final GLEventListener demo = glWindow1.removeGLEventListener(0);
-                    GLContext ctx2 = glWindow2.setContext(glWindow1.getContext());                    
-                    glWindow2.addGLEventListener(0, demo);
-                    glWindow1.setContext(ctx2);
-                }
+                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 ));
                 
-                animator.resume();
+                snapshotGLEventListener.setMakeSnapshot();
             }
             Thread.sleep(100);
             t1 = System.currentTimeMillis();
@@ -253,16 +269,32 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
     }
     
     @Test(timeout=30000)
-    public void testSwitch2GLWindowEachWithOwnDemo() throws InterruptedException {
-        GearsES2 gears = new GearsES2(1);
-        RedSquareES2 rsquare = new RedSquareES2(1);
+    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);                
@@ -270,6 +302,7 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
         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();
@@ -280,6 +313,9 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
         glWindow1.setVisible(true);
         glWindow2.setVisible(true);
 
+        snapshotGLEventListener1.setMakeSnapshot();
+        snapshotGLEventListener2.setMakeSnapshot();
+        
         int s = 0;
         long t0 = System.currentTimeMillis();
         long t1 = t0;
@@ -288,27 +324,25 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
             if( ( t1 - t0 ) / period > s) {
                 s++;
                 System.err.println(s+" - switch - START "+ ( t1 - t0 ));
-                animator.pause();
-                
-                GLEventListener demo1 = glWindow1.removeGLEventListener(0);
-                GLEventListener demo2 = glWindow2.removeGLEventListener(0);
-                
-                GLContext ctx1 = glWindow1.setContext(glWindow2.getContext());
-                glWindow1.addGLEventListener(0, demo2);
-                
-                glWindow2.setContext(ctx1);
-                glWindow2.addGLEventListener(0, demo1);
-                
+                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 ));
-                
-                animator.resume();
+                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();
         
     }
@@ -335,6 +369,6 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase {
         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(TestGLContextDrawableSwitchNEWT.class.getName());
+        org.junit.runner.JUnitCore.main(TestGLContextDrawableSwitch01NEWT.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 0000000..2bba76e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java
@@ -0,0 +1,274 @@
+/**
+ * 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;
+
+/**
+ * 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>
+ */
+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 0000000..a3f3ffb
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java
@@ -0,0 +1,118 @@
+/**
+ * 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;
+
+/**
+ * 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>
+ */
+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 0000000..95e895d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java
@@ -0,0 +1,144 @@
+/**
+ * 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;
+
+/**
+ * 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>
+ */
+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 0000000..d337570
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.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.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;
+
+/**
+ * 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>
+ */
+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 e1048c2..d444f02 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
@@ -60,15 +60,15 @@ public class TestAWT01GLn extends UITestCase {
         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) {
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 f83c8c0..6c0bc77 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,16 +29,12 @@
 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;
 
 public class TestAWT02WindowClosing extends UITestCase {
@@ -47,15 +43,14 @@ public class TestAWT02WindowClosing extends UITestCase {
 
     @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 aa7b4e0..49ad1c9 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
@@ -139,7 +139,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/TestAWTCardLayoutAnimatorStartStopBug532.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java
index 3f69355..1237fc9 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWTCardLayoutAnimatorStartStopBug532.java
@@ -167,11 +167,10 @@ public class TestAWTCardLayoutAnimatorStartStopBug532 extends UITestCase {
       
       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);
         }});
     
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
index 42949af..22c1f62 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java
@@ -28,6 +28,7 @@
 
 package com.jogamp.opengl.test.junit.jogl.awt;
 
+import java.awt.Container;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
  
@@ -49,7 +50,9 @@ import javax.swing.JLabel;
 import org.junit.Assert;
 import org.junit.Test;
 
+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
@@ -57,10 +60,11 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
  *
  * @author Wade Walker (from code sample provided by Owen Dimond)
  */
- at SuppressWarnings("deprecation")
 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();
@@ -79,7 +83,8 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
     }
     
     /* @Override */
-    public void init(GLAutoDrawable drawable) {                        
+    public void init(GLAutoDrawable drawable) {
+        awtGLReadBufferUtil = new AWTGLReadBufferUtil(drawable.getGLProfile(), false);
     }
 
     /* @Override */
@@ -89,16 +94,28 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
     /* @Override */
     public void display(GLAutoDrawable drawable) {             
         render(offScreenBuffer);
-        BufferedImage outputImage = com.jogamp.opengl.util.awt.Screenshot.readToBufferedImage(200, 200, false);        
+        // 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);
-        JLabel imageLabel = new JLabel(imageIcon);        
-        jframe.getContentPane().add(imageLabel);
+        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);
@@ -113,7 +130,6 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
     public void testOffscreenSupersampling() throws InterruptedException, InvocationTargetException {
         jframe = new JFrame("Offscreen Supersampling");
         Assert.assertNotNull(jframe);
-        jframe.setSize( 300, 300);
         jframe.addWindowListener(new WindowAdapter() {
             public void windowClosing(WindowEvent e) {
                 System.exit(0);
@@ -136,7 +152,8 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
         glCap.setSampleBuffers(true);
       
         // Without line below, there is an error on Windows.
-        glCap.setDoubleBuffered(false);
+        // glCap.setDoubleBuffered(false); // implicit double buffer -> MSAA + FBO
+        
         // Needed for drop shadows
         glCap.setStencilBits(1);
 
@@ -144,15 +161,25 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
         offScreenBuffer = fac.createOffscreenAutoDrawable(GLProfile.getDefaultDevice(), glCap, null, 200, 200, null);
         Assert.assertNotNull(offScreenBuffer);
         offScreenBuffer.addGLEventListener(this);        
-        offScreenBuffer.display();
         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/TestBug572AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java
index b3abc41..ea8fe07 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug572AWT.java
@@ -28,6 +28,7 @@
  
 package com.jogamp.opengl.test.junit.jogl.awt;
 
+import java.awt.Dimension;
 import java.awt.Window;
 import java.lang.reflect.InvocationTargetException;
 
@@ -47,11 +48,32 @@ import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
 import com.jogamp.opengl.test.junit.util.UITestCase;
 
 /**
- * Tests context creation + display on various kinds of Window implementations.
+ * Test realize GLCanvas and setVisible(true) AWT-Frames on AWT-EDT and on current thread (non AWT-EDT)
  */
 public class TestBug572AWT extends UITestCase {
-
-    protected void runTestGL() throws InterruptedException, InvocationTargetException {
+     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);
@@ -61,23 +83,40 @@ public class TestBug572AWT extends UITestCase {
         glCanvas.addGLEventListener(snapshooter);
         window.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.
-        window.setSize(512, 512);
-        window.validate();
-
-        window.setVisible(true);
+        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);
         
-        // Immediately displayable after issuing initial setVisible(true) .. even not within AWT-EDT ?
         Assert.assertTrue("GLCanvas didn't become displayable", glCanvas.isDisplayable());
         Assert.assertTrue("GLCanvas didn't become realized", glCanvas.isRealized());
         
-        // Would be required if not immediately displayable ...   
-        // Assert.assertTrue("GLCanvas didn't become displayable and realized", AWTRobotUtil.waitForRealized(glCanvas, true));
-        // System.err.println("XXXX-1 "+glCanvas.getDelegatedDrawable().isRealized()+", "+glCanvas);
-        
         // 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());
@@ -94,33 +133,35 @@ public class TestBug572AWT extends UITestCase {
         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.
 
-        Runnable cleanup = new Runnable() {
-            public void run() {
-                System.err.println("cleaning up...");
-                window.setVisible(false);
-                try {
-                    window.removeAll();
-                } catch (Throwable t) {
-                    Assume.assumeNoException(t);
-                    t.printStackTrace();
-                }
-                window.dispose();
-            }
-
-        };
-
         // AWT / Swing on EDT..
-        SwingUtilities.invokeAndWait(cleanup);
+        SwingUtilities.invokeAndWait(new Cleanup(window));
+    }
+    
+    @Test(timeout = 10000) // 10s timeout
+    public void test01RealizeGLCanvasOnAWTEDTUseFrameSize() throws InterruptedException, InvocationTargetException {
+        testRealizeGLCanvas(true, true);
     }
 
-    @Test
-    public void test01() throws InterruptedException, InvocationTargetException {
-        runTestGL();
+    @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/TestJScrollPaneMixHwLw01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug642JSplitPaneMixHwLw01AWT.java
similarity index 54%
copy from src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug642JSplitPaneMixHwLw01AWT.java
index bb525c9..8b88a86 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug642JSplitPaneMixHwLw01AWT.java
@@ -1,21 +1,25 @@
 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.ScrollPane;
 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.JTextArea;
+import javax.swing.JSplitPane;
 import javax.swing.WindowConstants;
 
 import org.junit.Assert;
@@ -27,20 +31,18 @@ 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 586
+ * Documenting Bug 642 (related to 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.
+ * JSplitPane cannot mix hw/lw components, only if setting property '-Dsun.awt.disableMixing=true'.
  * </p>
+ * See Bug 586
  * See git commit '8df12ca151dfc577c90b485d4ebfe491b88e55aa'.
  */
-public class TestJScrollPaneMixHwLw01AWT extends UITestCase {
+public class TestBug642JSplitPaneMixHwLw01AWT extends UITestCase {
     static long durationPerTest = 500;
     
     static {
@@ -76,53 +78,68 @@ public class TestJScrollPaneMixHwLw01AWT extends UITestCase {
         }
     }
     
-    protected void runTestGL(GLCapabilities caps, boolean useJScroll) throws InterruptedException {
-        final JFrame frame = new JFrame("Mix Hw/Lw Swing");
+    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(600,400);
-        final Dimension glc_sz = new Dimension(500,600);
+        final Dimension f_sz = new Dimension(824,568);
+        // 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);
+        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
         
-        JPanel panel = new JPanel(new BorderLayout());
-        panel.setOpaque(false);
-        if(useJScroll) {
-            final JScrollPane scrollPane = new TransparentJScrollPane(glCanvas);      
-            panel.add(scrollPane, BorderLayout.CENTER);
+        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 {
-            ScrollPane scrollPane = new ScrollPane();
-            scrollPane.add(glCanvas);
-            panel.add(scrollPane, BorderLayout.CENTER);
+            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;
         }
         
-        JTextArea textArea = new JTextArea();
-        textArea.setText("Test\nTest\nTest\nTest\n");
-
-        panel.add(textArea, BorderLayout.NORTH);
-
-        frame.add(panel);
-        frame.setLocationRelativeTo(null);
-        frame.setTitle("GLCanvas in JScrollPane example");
-        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+        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.setSize(f_sz);
+                    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 animator = new Animator(glCanvas);
-        animator.start();
-
+        animator.setUpdateFPSFrames(60, System.err);
         Thread.sleep(durationPerTest);
 
         animator.stop();
@@ -139,18 +156,25 @@ public class TestJScrollPaneMixHwLw01AWT extends UITestCase {
         }
     }
 
-    // @Test doesn't work
-    public void test01JScrollPane() throws InterruptedException {
+    @Test
+    public void test01JSplitPaneWithHwGLCanvasPlain() throws InterruptedException {
         GLProfile glp = GLProfile.getGL2ES2();
         GLCapabilities caps = new GLCapabilities(glp);
-        runTestGL(caps, true);
+        runTestGL(caps, false, false);
     }
 
     @Test
-    public void test01ScrollPane() throws InterruptedException {
+    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, false);
+        runTestGL(caps, true, false);
     }
     
     public static void main(String args[]) throws IOException {
@@ -165,7 +189,7 @@ public class TestJScrollPaneMixHwLw01AWT extends UITestCase {
         System.err.println(stdin.readLine()); 
         */
         System.out.println("durationPerTest: "+durationPerTest);
-        String tstname = TestJScrollPaneMixHwLw01AWT.class.getName();
+        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 0000000..d59bc22
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug664GLCanvasSetVisibleSwingAWT.java
@@ -0,0 +1,283 @@
+/**
+ * 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 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;
+
+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]);
+            
+            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, null);
+            anim.start();
+            anim.resetFPSCounter();
+            System.err.println("Visible Part 1/3");
+            
+            while( anim.getTotalFPSDuration() < durationPerTest ) {
+                Thread.sleep(60);
+            }            
+            
+            setComponentVisible(glc, false);
+            Assert.assertTrue("Component didn't become invisible", AWTRobotUtil.waitForVisible(glc, false));            
+            final int frameCountT0 = frameCount;
+            anim.resetFPSCounter();
+            System.err.println("Invisible Part 2/3");
+            
+            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);
+            
+            setComponentVisible(glc, true);
+            Assert.assertTrue("Component didn't become visible", AWTRobotUtil.waitForVisible(glc, true));
+            anim.resetFPSCounter();
+            System.err.println("Visible Part 3/3");
+            
+            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 0000000..0c09753
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug675BeansInDesignTimeAWT.java
@@ -0,0 +1,111 @@
+/**
+ * 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 junit.framework.Assert;
+
+import org.junit.Test;
+
+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;
+
+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/TestGLCanvasAWTActionDeadlock00AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock00AWT.java
new file mode 100644
index 0000000..f026fa2
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock00AWT.java
@@ -0,0 +1,241 @@
+/**
+ * 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;
+
+
+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 0000000..0bcde2b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock01AWT.java
@@ -0,0 +1,348 @@
+/**
+ * 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;
+
+/**
+ * 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>
+ */
+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 0000000..289c624
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLCanvasAWTActionDeadlock02AWT.java
@@ -0,0 +1,687 @@
+/**
+ * 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 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>
+ */
+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 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 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 boolean isStarted() {
+              stateSync.lock();
+              try {
+                  return (timer != null);
+              } finally {
+                  stateSync.unlock();
+              }
+          }
+    
+          public final boolean isAnimating() {
+              stateSync.lock();
+              try {
+                  return (timer != null) && (task != null);
+              } finally {
+                  stateSync.unlock();
+              }
+          }
+    
+          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;
+              }
+              stateSync.lock();
+              try {
+                  timer = new Timer();
+                  startTask();
+              } finally {
+                  stateSync.unlock();
+              }
+              return true;
+          }
+    
+          /** Stops this CustomAnimator. */
+          public synchronized boolean stop() {
+              if (timer == null) {
+                  return false;
+              }
+              stateSync.lock();
+              try {
+                  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) { }
+              } finally {
+                  stateSync.unlock();
+              }
+              return true;
+          }
+          
+          public final 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/TestIsRealizedConcurrency01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestIsRealizedConcurrency01AWT.java
new file mode 100644
index 0000000..74e5d6c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestIsRealizedConcurrency01AWT.java
@@ -0,0 +1,101 @@
+/**
+ * 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;
+
+
+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
index bb525c9..991f4ac 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestJScrollPaneMixHwLw01AWT.java
@@ -77,7 +77,8 @@ public class TestJScrollPaneMixHwLw01AWT extends UITestCase {
     }
     
     protected void runTestGL(GLCapabilities caps, boolean useJScroll) throws InterruptedException {
-        final JFrame frame = new JFrame("Mix Hw/Lw Swing");
+        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);
@@ -105,13 +106,13 @@ public class TestJScrollPaneMixHwLw01AWT extends UITestCase {
         panel.add(textArea, BorderLayout.NORTH);
 
         frame.add(panel);
-        frame.setLocationRelativeTo(null);
-        frame.setTitle("GLCanvas in JScrollPane example");
         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);
                 }});
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 ab369a9..ffe3bb3 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;
@@ -84,9 +83,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/TestBug605FlippedImageNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java
index 837d94c..dc1d528 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java
@@ -128,7 +128,7 @@ public class TestBug605FlippedImageNEWT extends UITestCase {
         glad.display();
         System.err.println("XXX "+glad.getChosenGLCapabilities());
         System.err.println("XXX "+glad.getContext().getGLVersion());
-        testFlipped(rbu.getPixelBuffer(), glad.getWidth(), glad.getHeight(), 3);        
+        testFlipped((ByteBuffer)rbu.getPixelBuffer().buffer, glad.getWidth(), glad.getHeight(), 3);        
         
         glad.destroy();        
     }
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
old mode 100755
new mode 100644
index c5bdfb5..2083671
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES1AWT.java
@@ -116,11 +116,11 @@ public class TestMultisampleES1AWT extends UITestCase {
     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);
             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
old mode 100755
new mode 100644
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 7cce5d1..6d8270a 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
@@ -119,18 +119,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 67e8524..f184873 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
@@ -85,7 +85,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 0000000..cb76f10
--- /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 44a74a3..82dd707 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
@@ -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;
@@ -47,7 +48,7 @@ public abstract class GearsObject {
 
     public abstract GLArrayDataServer createInterleaved(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);
     
     public void destroy(GL gl) {
         if(!isShared) {
@@ -88,9 +89,11 @@ public abstract class GearsObject {
         backSide = shared.backSide;
         outwardFace = shared.outwardFace;
         insideRadiusCyl = shared.insideRadiusCyl;
+        gearColor = shared.gearColor;
     }
             
     public GearsObject (
+            FloatBuffer gearColor,
             float inner_radius,
             float outer_radius,
             float width,
@@ -107,7 +110,8 @@ public abstract class GearsObject {
         float normal[] = new float[3];
         // final int tris_per_tooth = 32;
 
-        isShared = false;
+        this.isShared = false;
+        this.gearColor = gearColor;
         
         r0 = inner_radius;
         r1 = outer_radius - tooth_depth / 2.0f;
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 5186fd7..0cd45e5 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
@@ -21,6 +21,8 @@
 
 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;
@@ -57,6 +59,7 @@ public class GearsES1 implements GLEventListener {
 
   private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f;
   private GearsObject gear1=null, gear2=null, gear3=null;
+  private FloatBuffer gear1Color=GearsObject.red, gear2Color=GearsObject.green, gear3Color=GearsObject.blue;
   private float angle = 0.0f;
   private int swapInterval;
   private MouseListener gearsMouse = new GearsMouseAdapter();    
@@ -80,6 +83,12 @@ public class GearsES1 implements GLEventListener {
     this.traceFFPEmu = traceFFPEmu;
   }
   
+  public void setGearsColors(FloatBuffer gear1Color, FloatBuffer gear2Color, FloatBuffer gear3Color) {
+    this.gear1Color = gear1Color;
+    this.gear2Color = gear2Color;
+    this.gear3Color = gear3Color;
+  }
+    
   public void setGears(GearsObject g1, GearsObject g2, GearsObject g3) {
       gear1 = g1;
       gear2 = g2;
@@ -140,7 +149,7 @@ public class GearsES1 implements GLEventListener {
     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: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+    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());
@@ -153,21 +162,21 @@ public class GearsES1 implements GLEventListener {
             
     /* make the gears */
     if(null == gear1) {
-        gear1 = new GearsObjectES1(1.0f, 4.0f, 1.0f, 20, 0.7f);
+        gear1 = new GearsObjectES1(gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f);
         System.err.println("gear1 created: "+gear1);
     } else {
         System.err.println("gear1 reused: "+gear1);
     }
                 
     if(null == gear2) {
-        gear2 = new GearsObjectES1(0.5f, 2.0f, 2.0f, 10, 0.7f);
+        gear2 = new GearsObjectES1(gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f);
         System.err.println("gear2 created: "+gear2);
     } else {
         System.err.println("gear2 reused: "+gear2);
     }
             
     if(null == gear3) {
-        gear3 = new GearsObjectES1(1.3f, 2.0f, 0.5f, 10, 0.7f);
+        gear3 = new GearsObjectES1(gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f);
         System.err.println("gear3 created: "+gear3);
     } else {
         System.err.println("gear3 reused: "+gear3);
@@ -268,9 +277,9 @@ public class GearsES1 implements GLEventListener {
     gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
     gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
             
-    gear1.draw(gl, -3.0f, -2.0f, angle, 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
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 8276c6b..89e4697 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
@@ -36,9 +36,9 @@ import com.jogamp.opengl.util.GLArrayDataServer;
  */
 public class GearsObjectES1 extends GearsObject {
 
-    public GearsObjectES1(float inner_radius, float outer_radius, float width,
+    public GearsObjectES1(FloatBuffer gearColor, float inner_radius, float outer_radius, float width,
             int teeth, float tooth_depth) {
-        super(inner_radius, outer_radius, width, teeth, tooth_depth);
+        super(gearColor, inner_radius, outer_radius, width, teeth, tooth_depth);
     }
 
     @Override
@@ -59,12 +59,12 @@ public class GearsObjectES1 extends GearsObject {
     }
 
     @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) {
         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);
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 0000000..04fe264
--- /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/RedSquareES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java
index 37ed83e..97519e7 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
@@ -83,7 +83,7 @@ public class RedSquareES1 implements GLEventListener {
         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: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+        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());
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 9e0bbae..34fa79b 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;
 
@@ -50,6 +51,7 @@ 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() {
@@ -66,7 +68,7 @@ public class TestGearsES1NEWT extends UITestCase {
         Assert.assertNotNull(glWindow);
         glWindow.setTitle("Gears NEWT Test");
 
-        final GearsES1 demo = new GearsES1();
+        final GearsES1 demo = new GearsES1(swapInterval);
         demo.setForceFFPEmu(forceFFPEmu, forceFFPEmu, false, false);
         glWindow.addGLEventListener(demo);
         final SnapshotGLEventListener snap = new SnapshotGLEventListener();
@@ -82,7 +84,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() {
@@ -117,7 +122,7 @@ public class TestGearsES1NEWT extends UITestCase {
         runTestGL(caps, forceFFPEmu);
     }
     
-    static long duration = 1000; // ms
+    static long duration = 500; // ms
     
     public static void main(String args[]) {
         for(int i=0; i<args.length; i++) {
@@ -126,6 +131,9 @@ 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")) {
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/TestOlympicES1NEWT.java
similarity index 62%
copy from src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestGearsES1NEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/newt/TestOlympicES1NEWT.java
index 9e0bbae..84be7c6 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/TestOlympicES1NEWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2011 JogAmp Community. 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:
@@ -28,16 +28,14 @@
  
 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;
+import com.jogamp.opengl.test.junit.jogl.demos.es1.OlympicES1;
 
 import com.jogamp.opengl.util.Animator;
 
-import com.jogamp.opengl.test.junit.jogl.demos.es1.GearsES1;
-
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLProfile;
 
@@ -46,10 +44,13 @@ import org.junit.BeforeClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
-public class TestGearsES1NEWT extends UITestCase {
+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() {
@@ -61,64 +62,56 @@ public class TestGearsES1NEWT extends UITestCase {
     public static void releaseClass() {
     }
 
-    protected void runTestGL(GLCapabilities caps, boolean forceFFPEmu) throws InterruptedException {
+    protected void runTestGL(GLCapabilities caps) throws InterruptedException {
         GLWindow glWindow = GLWindow.create(caps);
         Assert.assertNotNull(glWindow);
-        glWindow.setTitle("Gears NEWT Test");
+        glWindow.setTitle("Olympic NEWT Test");
 
-        final GearsES1 demo = new GearsES1();
-        demo.setForceFFPEmu(forceFFPEmu, forceFFPEmu, false, false);
-        glWindow.addGLEventListener(demo);
+        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(glWindow);
+        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);
-
-        final GLWindow f_glWindow = glWindow;
-        glWindow.addKeyListener(new KeyAdapter() {
-            public void keyTyped(KeyEvent e) {
-                if(e.getKeyChar()=='f') {
-                    new Thread() {
-                        public void run() {
-                            f_glWindow.setFullscreen(!f_glWindow.isFullscreen());
-                    } }.start();
-                } else if(e.getKeyChar()=='d') {
-                    new Thread() {
-                        public void run() {
-                            f_glWindow.setUndecorated(!f_glWindow.isUndecorated());
-                    } }.start();
-                }
-            }
-        });
-
         glWindow.setSize(width, height);
         glWindow.setVisible(true);
-        animator.setUpdateFPSFrames(1, null);
+        
+        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, forceFFPEmu);
+        runTestGL(caps);
     }
-    
-    static long duration = 1000; // ms
-    
+
+    static long duration = 500; // ms
+
     public static void main(String args[]) {
         for(int i=0; i<args.length; i++) {
             if(args[i].equals("-time")) {
@@ -126,12 +119,23 @@ 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("-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;
             }
         }
-        org.junit.runner.JUnitCore.main(TestGearsES1NEWT.class.getName());
+        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 b0e6b2b..478195c 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
@@ -82,7 +82,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() {
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 e703b6f..7e86db9 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
@@ -25,7 +25,6 @@ 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.opengl.test.junit.jogl.demos.GearsObject;
@@ -38,6 +37,7 @@ 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;
@@ -55,18 +55,22 @@ public class GearsES2 implements GLEventListener {
     private GLUniformData pmvMatrixUniform = null;
     private GLUniformData colorU = null;
     private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f;
+    private float panX = 0.0f, panY = 0.0f, panZ=0.0f;
+    private int drawableHeight = 1;
     private GearsObjectES2 gear1=null, gear2=null, gear3=null;
+    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 int prevMouseX, prevMouseY;
     private boolean doRotate = true;
-    private boolean isInitialized = false;
-    boolean ignoreFocus = false;
+    private boolean ignoreFocus = false;
+    private float[] clearColor = null;
+    private boolean clearBuffers = true;
+    private boolean verbose = true;
 
     public GearsES2(int swapInterval) {
         this.swapInterval = swapInterval;
@@ -78,11 +82,24 @@ public class GearsES2 implements GLEventListener {
 
     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 setPMVUseBackingArray(boolean pmvUseBackingArray) {
         this.pmvUseBackingArray = pmvUseBackingArray;
     }
     
+    /** 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 setGears(GearsObjectES2 g1, GearsObjectES2 g2, GearsObjectES2 g3) {
         gear1 = g1;
         gear2 = g2;
@@ -106,25 +123,26 @@ public class GearsES2 implements GLEventListener {
 
 
     public void init(GLAutoDrawable drawable) {
-        if(isInitialized) {
-            System.err.println(Thread.currentThread()+" GearsES2.init skipped!");
-            return; 
-        }
-        isInitialized = true;
         System.err.println(Thread.currentThread()+" GearsES2.init ...");
-        GL2ES2 gl = drawable.getGL().getGL2ES2();
-
-        System.err.println("GearsES2 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: "+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 GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+        if(verbose) {
+            System.err.println("GearsES2 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());
+        }        
+        if( !gl.hasGLSL() ) {
+            System.err.println("No GLSL available, no rendering.");
+            return;
+        }
 
         gl.glEnable(GL.GL_DEPTH_TEST);
         
@@ -134,8 +152,8 @@ public class GearsES2 implements GLEventListener {
                 "shader/bin", "gears", true);
         final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
                 "shader/bin", "gears", true);
-        vp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
-        fp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+        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);
@@ -158,27 +176,39 @@ public class GearsES2 implements GLEventListener {
         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);
+            gear1 = new GearsObjectES2(st, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, pmvMatrix, pmvMatrixUniform, colorU);
+            if(verbose) {
+                System.err.println("gear1 created: "+gear1);
+            }
         } else {
-            gear1 = new GearsObjectES2(gear1, pmvMatrix, pmvMatrixUniform, colorU);
-            System.err.println("gear1 reused: "+gear1);
+            gear1 = new GearsObjectES2(gear1, st, pmvMatrix, pmvMatrixUniform, colorU);
+            if(verbose) {
+                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);
+            gear2 = new GearsObjectES2(st, gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU);
+            if(verbose) {
+                System.err.println("gear2 created: "+gear2);
+            }
         } else {
-            gear2 = new GearsObjectES2(gear2, pmvMatrix, pmvMatrixUniform, colorU);
-            System.err.println("gear2 reused: "+gear2);
+            gear2 = new GearsObjectES2(gear2, st, pmvMatrix, pmvMatrixUniform, colorU);
+            if(verbose) {
+                System.err.println("gear2 reused: "+gear2);
+            }
         }
                 
         if(null == gear3) {
-            gear3 = new GearsObjectES2(1.3f, 2.0f, 0.5f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU);
-            System.err.println("gear3 created: "+gear3);
+            gear3 = new GearsObjectES2(st, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU);
+            if(verbose) {
+                System.err.println("gear3 created: "+gear3);
+            }
         } else {
-            gear3 = new GearsObjectES2(gear3, pmvMatrix, pmvMatrixUniform, colorU);
-            System.err.println("gear3 reused: "+gear3);
+            gear3 = new GearsObjectES2(gear3, st, pmvMatrix, pmvMatrixUniform, colorU);
+            if(verbose) {
+                System.err.println("gear3 reused: "+gear3);
+            }
         }
     
         final Object upstreamWidget = drawable.getUpstreamWidget();
@@ -198,12 +228,18 @@ public class GearsES2 implements GLEventListener {
 
     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+", drawable 0x"+Long.toHexString(drawable.getHandle()));
+        
+        drawableHeight = height;
+        
         // Thread.dumpStack();
-        GL2ES2 gl = drawable.getGL().getGL2ES2();
+        final GL2ES2 gl = drawable.getGL().getGL2ES2();
 
         if(-1 != swapInterval) {
             gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
         }
+        if( !gl.hasGLSL() ) {
+            return;
+        }
         
         st.useProgram(gl, true);
         pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
@@ -211,10 +247,10 @@ public class GearsES2 implements GLEventListener {
         
         if(height>width) {
             float h = (float)height / (float)width;
-            pmvMatrix.glFrustumf(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
+            pmvMatrix.glFrustumf(-1.0f, 1.0f, -h, h, 5.0f, 200.0f);
         } else {
             float h = (float)width / (float)height;
-            pmvMatrix.glFrustumf(-h, h, -1.0f, 1.0f, 5.0f, 60.0f);
+            pmvMatrix.glFrustumf(-h, h, -1.0f, 1.0f, 5.0f, 200.0f);
         }
 
         pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
@@ -228,11 +264,6 @@ public class GearsES2 implements GLEventListener {
     // private boolean useAndroidDebug = false;
 
     public void dispose(GLAutoDrawable drawable) {
-        if(!isInitialized) {
-            System.err.println(Thread.currentThread()+" GearsES2.dispose skipped!");
-            return; 
-        }
-        isInitialized = false;
         System.err.println(Thread.currentThread()+" GearsES2.dispose ... ");
         final Object upstreamWidget = drawable.getUpstreamWidget();
         if (upstreamWidget instanceof Window) {            
@@ -240,7 +271,10 @@ public class GearsES2 implements GLEventListener {
             window.removeMouseListener(gearsMouse);
             window.removeKeyListener(gearsKeys);
         }
-        GL2ES2 gl = drawable.getGL().getGL2ES2();
+        final GL2ES2 gl = drawable.getGL().getGL2ES2();
+        if( !gl.hasGLSL() ) {
+            return;
+        }
         st.useProgram(gl, false);
         gear1.destroy(gl);
         gear1 = null;
@@ -257,13 +291,17 @@ public class GearsES2 implements GLEventListener {
     }
 
     public void display(GLAutoDrawable drawable) {
+        GLAnimatorControl anim = drawable.getAnimator();
+        if( verbose && ( null == anim || !anim.isAnimating() ) ) {
+            System.err.println(Thread.currentThread()+" GearsES2.display "+drawable.getWidth()+"x"+drawable.getHeight()+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(drawable.getHandle()));
+        }
         // Turn the gears' teeth
         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;
         final Object upstreamWidget = drawable.getUpstreamWidget();
@@ -273,34 +311,41 @@ public class GearsES2 implements GLEventListener {
           hasFocus = true;
         }
         
-        gl.glEnable(GL.GL_CULL_FACE);
-        
-        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( clearBuffers ) {
+            if( null != clearColor ) {
+              gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+            } 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;
         }
 
+        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);
         
@@ -328,28 +373,134 @@ public class GearsES2 implements GLEventListener {
         }
     }
 
-    class GearsMouseAdapter extends MouseAdapter {
+    interface GestureHandler {
+        /** Returns true if within the gesture */ 
+        public boolean isWithinGesture();
+        /** Returns true if within the gesture */
+        public boolean onReleased(MouseEvent e);
+        /** Returns true if within the gesture */
+        public boolean onDragged(MouseEvent e);
+    }
+    final GestureHandler gesture2PtrZoom = new GestureHandler() {
+        private int zoomLastYDist;
+        private boolean zoomFirstTouch = true;
+        private boolean zoomMode = false;
+        
+        @Override
+        public boolean isWithinGesture() {
+            return zoomMode;
+        }
+
+        @Override
+        public boolean onReleased(MouseEvent e) {
+            if( zoomMode && e.getPointerCount()==1 ) {
+                zoomFirstTouch = true;
+                zoomMode = false;
+                System.err.println("panZ.X: "+e);
+            }
+            return zoomMode;
+        }
+
+        @Override
+        public boolean onDragged(MouseEvent e) {
+            if( e.getPointerCount() >=2 ) {
+                // 2 pointers zoom .. [ -15 .. 15 ], range 30
+                /** 
+                // Simple 1:1 Zoom: finger-distance to screen-coord
+                final int dy = Math.abs(e.getY(0)-e.getY(1));
+                float scale =  (float)dy / (float)drawableHeight;
+                panZ = 30f * scale - 15f; 
+                System.err.println("panZ: scale "+scale+" ["+dy+"/"+drawableHeight+"] -> "+panZ);
+                 */
+                // Diff. 1:1 Zoom: finger-distance to screen-coord
+                if(zoomFirstTouch) {
+                    zoomLastYDist = Math.abs(e.getY(0)-e.getY(1));
+                    zoomFirstTouch=false;
+                    zoomMode = true;
+                    System.err.println("panZ: 1st pinch "+zoomLastYDist+", "+e);
+                } else if( zoomMode ) {
+                    final int dy = Math.abs(e.getY(0)-e.getY(1));
+                    final int ddy = dy - zoomLastYDist;
+                    
+                    final float incr =  ( (float)ddy / (float)drawableHeight ) * 15.0f;                    
+                    panZ += incr; 
+                    if( e.getPointerCount() > 2 ) {
+                        panZ += incr;
+                    }
+                    System.err.println("panZ.1: ddy "+ddy+", incr "+incr+" ["+dy+"/"+drawableHeight+"], dblZoom "+(e.getPointerCount() > 2)+" -> "+panZ);
+                    
+                    zoomLastYDist = dy;
+                }
+            }
+            return zoomMode;
+        }        
+    };
+    
+    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( !gesture2PtrZoom.isWithinGesture() ) {
+                if( e.getPointerCount()==1 ) {
+                    prevMouseX = e.getX();
+                    prevMouseY = e.getY();
+                } else if( e.getPointerCount() == 4 ) {
+                    final Object src = e.getSource();
+                    if( e.getPressure(true) > 0.7f && src instanceof Window) { // show Keyboard
+                       ((Window) src).setKeyboardVisible(true);
+                    }
+                }
+            }
         }
 
         public void mouseReleased(MouseEvent e) {
+            gesture2PtrZoom.onReleased(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.
-                prevMouseX = e.getX();
-                prevMouseY = e.getY();
+        public void mouseMoved(MouseEvent e) {
+            if( !gesture2PtrZoom.isWithinGesture() && e.getPointerCount()==1 ) {
+                if( e.isConfined() ) {
+                    navigate(e);
+                } else {
+                    // track prev. position so we don't have 'jumps'
+                    // in case we move to confined navigation.
+                    prevMouseX = e.getX();
+                    prevMouseY = e.getY();
+                }
             }
         }
         
         public void mouseDragged(MouseEvent e) {
-            navigate(e);
+            if( !gesture2PtrZoom.onDragged(e) && e.getPointerCount()==1 ) {
+                navigate(e);
+            }
         }
         
         private void navigate(MouseEvent e) {
@@ -363,6 +514,10 @@ 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();
@@ -381,6 +536,7 @@ public class GearsES2 implements GLEventListener {
             }
             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 32cc4c4..c5f5f7a 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
@@ -36,31 +36,45 @@ 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;
+    final PMVMatrix pmvMatrix;
+    final GLUniformData pmvMatrixUniform;
+    final GLUniformData colorUniform;
+    final ShaderState st;
     
-    public GearsObjectES2(float inner_radius, float outer_radius, float width,
-                          int teeth, float tooth_depth,
-                          PMVMatrix pmvMatrix, 
-                          GLUniformData pmvMatrixUniform,
-                          GLUniformData colorUniform) 
+    public GearsObjectES2(ShaderState st, FloatBuffer gearColor, float inner_radius, float outer_radius,
+                          float width, int teeth,
+                          float tooth_depth, 
+                          PMVMatrix pmvMatrix,
+                          GLUniformData pmvMatrixUniform, GLUniformData colorUniform) 
     {
-        super(inner_radius, outer_radius, width, teeth, tooth_depth);
+        super(gearColor, inner_radius, outer_radius, width, teeth, tooth_depth);
         this.pmvMatrix = pmvMatrix;
         this.pmvMatrixUniform = pmvMatrixUniform;
         this.colorUniform = colorUniform;
+        this.st = st;
+        associate(st);
     }
 
     public GearsObjectES2(GearsObjectES2 shared,
-                          PMVMatrix pmvMatrix, 
-                          GLUniformData pmvMatrixUniform,
-                          GLUniformData colorUniform) 
+                          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
@@ -81,9 +95,8 @@ public class GearsObjectES2 extends GearsObject {
     }
 
     @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);
@@ -93,7 +106,7 @@ public class GearsObjectES2 extends GearsObject {
             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);
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 0000000..e7f980c
--- /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
index 26e7e23..cd40b5c 100644
--- 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
@@ -42,7 +42,8 @@ public class Mix2TexturesES2 implements GLEventListener {
     private final PMVMatrix pmvMatrix;
     private final GLUniformData texUnit0, texUnit1;
     
-    private volatile int texID0, texID1;
+    private Object syncTexIDs = new Object();
+    private int texID0, texID1;
     private ShaderProgram sp0;
     private GLUniformData pmvMatrixUniform;
     private GLArrayDataServer interleavedVBO;
@@ -66,10 +67,14 @@ public class Mix2TexturesES2 implements GLEventListener {
     }
     
     public void setTexID0(int texID) {
-        this.texID0 = texID;
+        synchronized( syncTexIDs ) {
+            this.texID0 = texID;
+        }
     }
     public void setTexID1(int texID) {
-        this.texID1 = texID;
+        synchronized( syncTexIDs ) {
+            this.texID1 = texID;
+        }
     }
         
     static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
@@ -156,20 +161,22 @@ public class Mix2TexturesES2 implements GLEventListener {
         
         interleavedVBO.enableBuffer(gl, true);
         
-        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);
+        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);
+            }
+            
+            gl.glEnable(GL.GL_TEXTURE_2D);
+            
+            gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
         }
         
-        gl.glEnable(GL.GL_TEXTURE_2D);
-        
-        gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
-        
         interleavedVBO.enableBuffer(gl, false);
         
         st.useProgram(gl, false);        
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
index 691e08e..9864139 100644
--- 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
@@ -117,7 +117,7 @@ public class MultisampleDemoES2 implements GLEventListener {
                                               4, GL.GL_FLOAT,  // color
                                               0, GL.GL_FLOAT,  // normal
                                               0, GL.GL_FLOAT,  // texCoords
-                                              GL.GL_STATIC_DRAW);
+                                              GL.GL_STATIC_DRAW, st);
         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/es2/PointsDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
index 1e0f959..52af491 100644
--- 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
@@ -85,7 +85,7 @@ public class PointsDemoES2 extends PointsDemo {
         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: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+        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();
@@ -94,8 +94,8 @@ public class PointsDemoES2 extends PointsDemo {
                 "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, ShaderCode.es2_default_precision_vp);
-        fp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+        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);
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 bf1ca5c..b7f9896 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,7 +27,6 @@
  */
 package com.jogamp.opengl.test.junit.jogl.demos.es2;
 
-import com.jogamp.newt.Window;
 import com.jogamp.opengl.util.GLArrayDataServer;
 import com.jogamp.opengl.util.PMVMatrix;
 import com.jogamp.opengl.util.glsl.ShaderCode;
@@ -40,17 +39,16 @@ import javax.media.opengl.GLEventListener;
 import javax.media.opengl.GLUniformData;
 
 public class RedSquareES2 implements GLEventListener {
-    ShaderState st;
-    PMVMatrix pmvMatrix;
-    GLUniformData pmvMatrixUniform;
-    GLArrayDataServer vertices ;
-    GLArrayDataServer colors ;
-    long t0;
+    private ShaderState st;
+    private PMVMatrix pmvMatrix;
+    private GLUniformData pmvMatrixUniform;
+    private GLArrayDataServer vertices ;
+    private GLArrayDataServer colors ;
+    private long t0;
     private int swapInterval = 0;
-    Window window = null;
-    float aspect = 1.0f;
-    boolean doRotate = true;
-    boolean isInitialized = false;
+    private float aspect = 1.0f;
+    private boolean doRotate = true;
+    private boolean clearBuffers = true;
 
     public RedSquareES2(int swapInterval) {
         this.swapInterval = swapInterval;
@@ -62,15 +60,11 @@ public class RedSquareES2 implements GLEventListener {
         
     public void setAspect(float aspect) { this.aspect = aspect; }
     public void setDoRotation(boolean rotate) { this.doRotate = rotate; }
+    public void setClearBuffers(boolean v) { clearBuffers = v; }
     
     public void init(GLAutoDrawable glad) {
-        if(isInitialized) {
-            System.err.println(Thread.currentThread()+" RedSquareES2.init skipped!");
-            return; 
-        }
-        isInitialized = true;
         System.err.println(Thread.currentThread()+" RedSquareES2.init ...");
-        GL2ES2 gl = glad.getGL().getGL2ES2();
+        final GL2ES2 gl = glad.getGL().getGL2ES2();
         
         System.err.println("RedSquareES2 init on "+Thread.currentThread());
         System.err.println("Chosen GLCapabilities: " + glad.getChosenGLCapabilities());
@@ -78,20 +72,23 @@ public class RedSquareES2 implements GLEventListener {
         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: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+        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 Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
         System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
-        
+        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, ShaderCode.es2_default_precision_vp);
-        fp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+        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);
@@ -138,9 +135,14 @@ public class RedSquareES2 implements GLEventListener {
     public void display(GLAutoDrawable glad) {
         long t1 = System.currentTimeMillis();
 
-        GL2ES2 gl = glad.getGL().getGL2ES2();
-        gl.glClearColor(0, 0, 0, 0);
-        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+        final GL2ES2 gl = glad.getGL().getGL2ES2();
+        if( clearBuffers ) {
+            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);
@@ -165,7 +167,10 @@ public class RedSquareES2 implements GLEventListener {
     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+", drawable 0x"+Long.toHexString(glad.getHandle()));
         // Thread.dumpStack();
-        GL2ES2 gl = glad.getGL().getGL2ES2();
+        final GL2ES2 gl = glad.getGL().getGL2ES2();
+        if( !gl.hasGLSL() ) {
+            return;
+        }
         
         if(-1 != swapInterval) {        
             gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
@@ -184,13 +189,11 @@ public class RedSquareES2 implements GLEventListener {
     }
 
     public void dispose(GLAutoDrawable glad) {
-        if(!isInitialized) {
-            System.err.println(Thread.currentThread()+" RedSquareES2.dispose skipped!");
-            return; 
-        }
-        isInitialized = false;
         System.err.println(Thread.currentThread()+" RedSquareES2.dispose ... ");
-        GL2ES2 gl = glad.getGL().getGL2ES2();
+        final GL2ES2 gl = glad.getGL().getGL2ES2();
+        if( !gl.hasGLSL() ) {
+            return;
+        }
         st.destroy(gl);
         st = null;
         pmvMatrix.destroy();
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
index 4bcb073..622df86 100644
--- 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
@@ -70,8 +70,8 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
                                             "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, ShaderCode.es2_default_precision_vp);
-        rsFp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+        rsVp.defaultShaderCustomization(gl, true, true);
+        rsFp.defaultShaderCustomization(gl, true, true);
         
         // Create & Link the shader program
         ShaderProgram sp = new ShaderProgram();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
index 9217e2b..25f8740 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
@@ -75,7 +75,6 @@ public class TextureSequenceCubeES2 implements GLEventListener {
     private float view_rotx = 0.0f, view_roty = 0.0f, view_rotz = 0.0f;
     int[] vboNames = new int[4];
     boolean innerCube;
-    boolean initialized = false;
     private ByteBuffer cubeIndices;
         
     private final MouseListener mouseAction = new MouseAdapter() {
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
old mode 100755
new mode 100644
index 7f27133..b7c4e72
--- 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
@@ -82,7 +82,10 @@ public class MovieCube implements GLEventListener, GLMediaEventListener {
     }
 
     private final KeyListener keyAction = new KeyAdapter() {
-        public void keyTyped(KeyEvent e)  {
+        public void keyReleased(KeyEvent e)  {
+            if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+                return;
+            }            
             System.err.println("MC "+e);
             int pts0 = mPlayer.getCurrentPosition();
             int pts1 = 0;
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
old mode 100755
new mode 100644
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 07899b7..d47017f 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
@@ -40,12 +40,17 @@ 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;
@@ -54,57 +59,156 @@ 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;
 
 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 FrameLayout frameLayout = FrameLayout.None;
+    static ResizeBy resizeBy = ResizeBy.Component;
+    
     static boolean forceES2 = false;
     static boolean forceGL3 = false;
-    static boolean shallUseOffscreenLayer = false;
+    static boolean mainRun = false;
+    static boolean shallUseOffscreenFBOLayer = false;
     static boolean shallUseOffscreenPBufferLayer = false;
     static boolean useMSAA = false;
-    static boolean addComp = true;
+    static boolean useStencil = false;
     static boolean shutdownRemoveGLCanvas = true;
     static boolean shutdownDisposeFrame = true;
     static boolean shutdownSystemExit = false;
     static int swapInterval = 1;
+    static boolean exclusiveContext = false;
+    static boolean useAnimator = true;
+    static Thread awtEDT;
+    static java.awt.Dimension rwsize = null;
 
     @BeforeClass
     public static void initClass() {
         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);
-        Dimension glc_sz = new Dimension(width, height);
-        glCanvas.setMinimumSize(glc_sz);
-        glCanvas.setPreferredSize(glc_sz);
-        glCanvas.setSize(glc_sz);
-        if(addComp) {
-            final TextArea ta = new TextArea(2, 20);
-            ta.append("0123456789");
-            ta.append(Platform.getNewline());
-            ta.append("Some Text");
-            ta.append(Platform.getNewline());
-            frame.add(ta, BorderLayout.SOUTH);
-        }
-        frame.add(glCanvas, BorderLayout.CENTER);
+        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);
@@ -112,23 +216,59 @@ public class TestGearsES2AWT extends UITestCase {
 
         javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
             public void run() {
-                frame.pack();
-                frame.setVisible(true);
-            }});
-        animator.start();
-        animator.setUpdateFPSFrames(60, System.err);
+               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() {
@@ -159,26 +299,65 @@ public class TestGearsES2AWT extends UITestCase {
             caps.setNumSamples(4);
             caps.setSampleBuffers(true);
         }
-        if(shallUseOffscreenLayer) {
+        if(useStencil) {
+            caps.setStencilBits(1);
+        }
+        if(shallUseOffscreenFBOLayer) {
             caps.setOnscreen(false);
         }
         if(shallUseOffscreenPBufferLayer) {
             caps.setPBuffer(true);
         }
-        runTestGL(caps);
+        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")) {
@@ -186,16 +365,20 @@ public class TestGearsES2AWT extends UITestCase {
             } 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("-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("-justGears")) {
-                addComp = false;
             } else if(args[i].equals("-shutdownKeepGLCanvas")) {
                 shutdownRemoveGLCanvas = false;
             } else if(args[i].equals("-shutdownKeepFrame")) {
@@ -207,10 +390,22 @@ public class TestGearsES2AWT extends UITestCase {
                 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 0000000..e3be7b8
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java
@@ -0,0 +1,361 @@
+/**
+ * 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 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;
+
+public class TestGearsES2GLJPanelAWT extends UITestCase {
+    static Dimension wsize, rwsize=null;
+    static boolean forceES2 = false;
+    static boolean forceGL3 = 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;
+
+    @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.setMinimumSize(wsize);
+        glJPanel.setPreferredSize(wsize);
+        glJPanel.setSize(wsize);
+        if( caps.isBitmap() ) {
+            glJPanel.addGLEventListener(new Gears(swapInterval));
+        } else {
+            glJPanel.addGLEventListener(new GearsES2(swapInterval));
+        }
+        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 {
+            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("-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("-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("swapInterval "+swapInterval);
+        System.err.println("forceES2 "+forceES2);
+        System.err.println("forceGL3 "+forceGL3);
+        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 0000000..4668603
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java
@@ -0,0 +1,419 @@
+/**
+ * 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 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;
+
+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.isGL2GL3() /* 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 ed308bd..e22b00d 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
@@ -103,7 +103,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 86831a6..a876b5c 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
@@ -28,9 +28,7 @@
  
 package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
 
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
 
 import com.jogamp.newt.Display;
 import com.jogamp.newt.NewtFactory;
@@ -71,7 +69,7 @@ import org.junit.Test;
 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;
@@ -90,6 +88,10 @@ public class TestGearsES2NEWT extends UITestCase {
     static boolean forceES2 = false;
     static boolean forceGL3 = false;
     static boolean mainRun = false;
+    static boolean exclusiveContext = false;
+    static boolean useAnimator = true;
+    static enum SysExit { none, testExit, testError, displayExit, displayError };
+    static SysExit sysExit = SysExit.none;
     
     @BeforeClass
     public static void initClass() {
@@ -122,6 +124,9 @@ public class TestGearsES2NEWT extends UITestCase {
         final GearsES2 demo = new GearsES2(swapInterval);
         demo.setPMVUseBackingArray(pmvUseBackingArray);
         glWindow.addGLEventListener(demo);
+        
+        final SnapshotGLEventListener snap = new SnapshotGLEventListener();
+        glWindow.addGLEventListener(snap);
         if(waitForKey) {
             glWindow.addGLEventListener(new GLEventListener() {
                 public void init(GLAutoDrawable drawable) { }
@@ -129,11 +134,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;
                     }
@@ -143,9 +144,13 @@ public class TestGearsES2NEWT extends UITestCase {
             });
         }
 
-        Animator animator = new Animator(glWindow);
+        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);
@@ -161,66 +166,95 @@ public class TestGearsES2NEWT extends UITestCase {
         });
         
         glWindow.addKeyListener(new KeyAdapter() {
-            public void keyTyped(KeyEvent e) {
+            @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()=='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();
                 }
             }
@@ -232,30 +266,93 @@ public class TestGearsES2NEWT extends UITestCase {
             }
          });
 
-        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 ) {
+            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() ) {
+                        if( anim.getTotalFPSDuration() >= duration/2 ) {
+                            if( SysExit.displayError == sysExit ) {
+                                throw new Error("test error send from GLEventListener");
+                            } else if ( SysExit.displayExit == sysExit ) {
+                                System.err.println("exit(0) send from GLEventListener");
+                                System.exit(0);                                
+                            }
+                        }
+                    } 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);
+        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();
         
-        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();
+            if( t1-t0 >= duration/2 ) {
+                if( SysExit.testError == sysExit || SysExit.testExit == sysExit ) {
+                    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);                                
+                    }
+                }
+            }
         }
 
-        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));
     }
 
     @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);
             final GLProfile glp;
@@ -279,11 +376,25 @@ public class TestGearsES2NEWT extends UITestCase {
     }
 
     @Test
-    public void test02GL3() throws InterruptedException {
+    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 );
@@ -293,7 +404,7 @@ public class TestGearsES2NEWT extends UITestCase {
     public static void main(String args[]) throws IOException {
         mainRun = true;
         
-        int x=0, y=0, w=640, h=480;
+        int x=0, y=0, w=640, h=480, rw=-1, rh=-1;
         boolean usePos = false;
         
         for(int i=0; i<args.length; i++) {
@@ -316,6 +427,10 @@ 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("-gl3")) {
@@ -342,6 +457,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);
@@ -350,36 +471,42 @@ public class TestGearsES2NEWT extends UITestCase {
                 loops = MiscUtils.atoi(args[i], 1);
             } else if(args[i].equals("-loop-shutdown")) {
                 loop_shutdown = true;
+            } else if(args[i].equals("-sysExit")) {
+                i++;
+                sysExit = SysExit.valueOf(args[i]);
             }
         }
         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("pmvDirect "+(!pmvUseBackingArray));        
         System.err.println("mouseVisible "+mouseVisible);
         System.err.println("mouseConfined "+mouseConfined);
         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);
+        System.err.println("useAnimator "+useAnimator);
+        System.err.println("sysExitWithin "+sysExit);        
 
         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 0000000..f12f02c
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java
@@ -0,0 +1,511 @@
+/**
+ * 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.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.test.junit.jogl.demos.es2.GearsES2;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.InsetsImmutable;
+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;
+
+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 KeyAdapter() {
+            public void keyReleased(KeyEvent e) {
+                if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+                    return;
+                }            
+                if(e.getKeyChar()=='f') {
+                    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);
+                            quitAdapter.clear();
+                            quitAdapter.enable(true);
+                    } }.start();
+                } else if(e.getKeyChar()=='r') {
+                    quitAdapter.enable(false);
+                    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();
+                        }
+                        glWindow.setPosition(frame.getX()+frame.getWidth()+dx, frame.getY()+dy);
+                    }
+                    glWindow.requestFocus();
+                    quitAdapter.clear();
+                    quitAdapter.enable(true);
+                }
+            }
+        });
+
+        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/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java
similarity index 54%
copy from src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasSWT.java
index 86831a6..eed2e12 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/TestGearsES2NewtCanvasSWT.java
@@ -28,20 +28,17 @@
  
 package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
 
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
 
-import com.jogamp.newt.Display;
+import com.jogamp.nativewindow.swt.SWTAccessor;
 import com.jogamp.newt.NewtFactory;
-import com.jogamp.newt.Screen;
 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.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;
@@ -56,40 +53,41 @@ 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;
 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.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;
 
-public class TestGearsES2NEWT extends UITestCase {    
+public class TestGearsES2NewtCanvasSWT 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;
     static boolean pmvUseBackingArray = true;
     static int swapInterval = 1;
-    static boolean waitForKey = false;
-    static boolean mouseVisible = true;
-    static boolean mouseConfined = false;
     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() {
@@ -102,50 +100,69 @@ public class TestGearsES2NEWT extends UITestCase {
     public static void releaseClass() {
     }
 
-    protected void runTestGL(GLCapabilitiesImmutable caps, boolean undecorated) throws InterruptedException {
+    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);
-        Display dpy = NewtFactory.createDisplay(null);
-        Screen screen = NewtFactory.createScreen(dpy, screenIdx);
+        com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null);
+        com.jogamp.newt.Screen screen = NewtFactory.createScreen(dpy, screenIdx);
         final GLWindow glWindow = GLWindow.create(screen, caps);
         Assert.assertNotNull(glWindow);
-        glWindow.setTitle("Gears NEWT Test (translucent "+!caps.isBackgroundOpaque()+"), swapInterval "+swapInterval+", size "+wsize+", pos "+wpos);
-        glWindow.setSize(wsize.getWidth(), wsize.getHeight());
-        if(null != wpos) {
-            glWindow.setPosition(wpos.getX(), wpos.getY());
-        }
-        glWindow.setUndecorated(undecorated);
-        glWindow.setAlwaysOnTop(alwaysOnTop);
-        glWindow.setFullscreen(fullscreen);
-        glWindow.setPointerVisible(mouseVisible);
-        glWindow.confinePointer(mouseConfined);
-
+        
         final GearsES2 demo = new GearsES2(swapInterval);
         demo.setPMVUseBackingArray(pmvUseBackingArray);
         glWindow.addGLEventListener(demo);
-        if(waitForKey) {
-            glWindow.addGLEventListener(new GLEventListener() {
-                public void init(GLAutoDrawable drawable) { }
-                public void dispose(GLAutoDrawable drawable) { }
-                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) { }
-                        actrl.resetFPSCounter();
-                        waitForKey = false;
-                    }
-                }
-                public void reshape(GLAutoDrawable drawable, int x, int y,
-                        int width, int height) { }
-            });
-        }
-
-        Animator animator = new Animator(glWindow);
+        
+        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);
@@ -161,101 +178,84 @@ public class TestGearsES2NEWT extends UITestCase {
         });
         
         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() {
+                            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());
-                    } }.start();
-                } else if(e.getKeyChar()=='a') {
-                    new Thread() {
-                        public void run() {
-                            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());
-                    } }.start();
-                } else if(e.getKeyChar()=='d') {
-                    new Thread() {
-                        public void run() {
-                            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());
-                    } }.start();
-                } else if(e.getKeyChar()=='s') {
-                    new Thread() {
-                        public void run() {
-                            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());
-                    } }.start();
-                } else if(e.getKeyChar()=='i') {
-                    new Thread() {
-                        public void run() {
-                            System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible());
-                            glWindow.setPointerVisible(!glWindow.isPointerVisible());
-                            System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible());
-                    } }.start();
-                } else if(e.getKeyChar()=='j') {
-                    new Thread() {
-                        public void run() {
-                            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);
-                            }
-                    } }.start();
-                } else if(e.getKeyChar()=='J') {
-                    new Thread() {
-                        public void run() {
-                            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());
-                    } }.start();
-                } else if(e.getKeyChar()=='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]");
+                            glWindow.setExclusiveContextThread(t);
                     } }.start();
                 }
             }
         });
-        glWindow.addMouseListener(new MouseAdapter() {
-            public void mouseClicked(MouseEvent e) {
-                glWindow.setFullscreen(!glWindow.isFullscreen());
-                System.err.println("setFullscreen: "+glWindow.isFullscreen());
-            }
-         });
 
+        animator.add(glWindow);
         animator.start();
-        // glWindow.setSkipContextReleaseThread(animator.getThread());
+        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 );
 
-        glWindow.setVisible(true);
+        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());
-        
-        animator.setUpdateFPSFrames(60, showFPS ? System.err : null);
+                
+        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) {
-            Thread.sleep(100);
+            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 {
+    public void test01GL2ES2() throws InterruptedException, InvocationTargetException {
         for(int i=1; i<=loops; i++) {
             System.err.println("Loop "+i+"/"+loops);
             final GLProfile glp;
@@ -271,7 +271,7 @@ public class TestGearsES2NEWT extends UITestCase {
             if(-1 < forceAlpha) {
                 caps.setAlphaBits(forceAlpha); 
             }
-            runTestGL(caps, undecorated);
+            runTestGL(caps);
             if(loop_shutdown) {
                 GLProfile.shutdown();
             }
@@ -279,21 +279,22 @@ public class TestGearsES2NEWT extends UITestCase {
     }
 
     @Test
-    public void test02GL3() throws InterruptedException {
+    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, undecorated);
+        runTestGL(caps);
     }
     
     public static void main(String args[]) throws IOException {
         mainRun = true;
         
-        int x=0, y=0, w=640, h=480;
+        int x=0, y=0, w=640, h=480, rw=-1, rh=-1;
         boolean usePos = false;
         
         for(int i=0; i<args.length; i++) {
@@ -305,10 +306,6 @@ public class TestGearsES2NEWT extends UITestCase {
             } 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")) {
-                alwaysOnTop = true;
             } else if(args[i].equals("-fullscreen")) {
                 fullscreen = true;
             } else if(args[i].equals("-pmvDirect")) {
@@ -316,16 +313,12 @@ 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("-es2")) {
                 forceES2 = true;
             } else if(args[i].equals("-gl3")) {
                 forceGL3 = 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("-showFPS")) {
                 showFPS = true;
             } else if(args[i].equals("-width")) {
@@ -342,6 +335,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);
@@ -353,34 +352,28 @@ public class TestGearsES2NEWT extends UITestCase {
             }
         }
         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("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);
 
-        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(TestGearsES2NEWT.class.getName());
+        org.junit.runner.JUnitCore.main(TestGearsES2NewtCanvasSWT.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/TestLandscapeES2NEWT.java
similarity index 63%
copy from src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NEWT.java
index dbba4fa..281ee54 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/TestLandscapeES2NEWT.java
@@ -31,55 +31,47 @@ 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.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.LandscapeES2;
 
 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;
 
-public class TestRedSquareES2NEWT extends UITestCase {
-    static int width, height;
-    static int loops = 1;
-    static boolean loop_shutdown = false;
-    static boolean vsync = false;
+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 doRotate = true;
-
-    @BeforeClass
-    public static void initClass() {
-        width  = 512;
-        height = 512;
-    }
-
-    @AfterClass
-    public static void releaseClass() {
-    }
+    static boolean exclusiveContext = false;
+    static boolean useAnimator = true;
 
     protected void runTestGL(GLCapabilities caps) throws InterruptedException {
-        System.err.println("requested: vsync "+vsync+", "+caps);
-        GLWindow glWindow = GLWindow.create(caps);
-        Assert.assertNotNull(glWindow);
-        glWindow.setTitle("Gears NEWT Test");
+        System.err.println("requested: swapInterval "+swapInterval+", "+caps);
+        final GLWindow glWindow = GLWindow.create(caps);
+        glWindow.setTitle(getSimpleTestName("."));
         glWindow.setSize(width, height);
 
-        final RedSquareES2 demo = new RedSquareES2(vsync ? 1 : -1);
-        demo.setDoRotation(doRotate);
+        final LandscapeES2 demo = new LandscapeES2(swapInterval);
         glWindow.addGLEventListener(demo);
 
-        Animator animator = new Animator(glWindow);
+        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));
@@ -87,62 +79,62 @@ 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();
-        
+        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());
         
-        animator.setUpdateFPSFrames(60, System.err);
+        snap.setMakeSnapshot();
         
         while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
             Thread.sleep(100);
         }
 
-        animator.stop();
-        Assert.assertFalse(animator.isAnimating());
-        Assert.assertFalse(animator.isStarted());
+        if( useAnimator ) {
+            animator.stop();
+        }
         glWindow.destroy();
-        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);
-            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(loop_shutdown) {
-                GLProfile.shutdown();
-            }
+        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
@@ -151,6 +143,7 @@ public class TestRedSquareES2NEWT extends UITestCase {
         
         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 );
@@ -164,26 +157,22 @@ public class TestRedSquareES2NEWT extends UITestCase {
         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("-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("-norotate")) {
-                doRotate = false;
-            } else if(args[i].equals("-loops")) {
-                i++;
-                loops = MiscUtils.atoi(args[i], 1);
-            } else if(args[i].equals("-loop-shutdown")) {
-                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);
-        org.junit.runner.JUnitCore.main(TestRedSquareES2NEWT.class.getName());
+        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 0000000..72357dc
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestLandscapeES2NewtCanvasAWT.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.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.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.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.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.InsetsImmutable;
+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;
+
+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 KeyAdapter() {
+            public void keyReleased(KeyEvent e) {
+                if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+                    return;
+                }            
+                if(e.getKeyChar()=='f') {
+                    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);
+                            quitAdapter.clear();
+                            quitAdapter.enable(true);
+                    } }.start();
+                } else if(e.getKeyChar()=='r') {
+                    quitAdapter.enable(false);
+                    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();
+                        }
+                        glWindow.setPosition(frame.getX()+frame.getWidth()+dx, frame.getY()+dy);
+                    }
+                    glWindow.requestFocus();
+                    quitAdapter.clear();
+                    quitAdapter.enable(true);
+                }
+            }
+        });
+
+        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 dbba4fa..b880c2f 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
@@ -35,6 +35,7 @@ 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.util.UITestCase.SnapshotGLEventListener;
 
 import com.jogamp.opengl.util.Animator;
 
@@ -70,15 +71,19 @@ 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);
 
         final RedSquareES2 demo = new RedSquareES2(vsync ? 1 : -1);
         demo.setDoRotation(doRotate);
         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();
 
@@ -87,18 +92,20 @@ 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();
                 }
             }
@@ -113,6 +120,7 @@ public class TestRedSquareES2NEWT extends UITestCase {
         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);
@@ -151,6 +159,7 @@ public class TestRedSquareES2NEWT extends UITestCase {
         
         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 );
@@ -164,9 +173,7 @@ public class TestRedSquareES2NEWT extends UITestCase {
         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")) {
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 0000000..b19c057
--- /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 0000000..fc698f2
--- /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/swt/TestGearsES2SWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java
new file mode 100644
index 0000000..008349d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/swt/TestGearsES2SWT.java
@@ -0,0 +1,341 @@
+/**
+ * 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;
+
+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, 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 9c1293e..fbcfb26 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
@@ -67,23 +67,20 @@ public class Gears implements GLEventListener {
   public int getGear3() { return gear3; }
 
   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("Gears (GL2) init on "+Thread.currentThread());
+    System.err.println("GearsGL2 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: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+    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());
-
+    
     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 };
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 0000000..ae5a0b3
--- /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-160x90.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) {
+    }
+}
\ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java
index bd9b7ca..aaf995e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java
@@ -87,10 +87,10 @@ public class TestGLJPanelAWTBug450 extends UITestCase {
             throws AWTException, InterruptedException, InvocationTargetException
     {
         final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
-        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);
         RedSquareES2 demo = new RedSquareES2();
         demo.setAspect((float)width/(float)height);
@@ -129,13 +129,11 @@ public class TestGLJPanelAWTBug450 extends UITestCase {
 
         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);        
@@ -154,11 +152,11 @@ public class TestGLJPanelAWTBug450 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 );
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 498a328..528762a 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
@@ -114,7 +114,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() {
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 4807e5d..22df331 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
@@ -105,7 +105,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 +117,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 +133,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 cb54c26..02e44e7 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,11 +30,18 @@ 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;
@@ -50,6 +57,12 @@ import org.junit.Test;
 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() {
@@ -70,72 +83,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);
         Dimension glc_sz = new Dimension(width, height);
         glJPanel.setMinimumSize(glc_sz);
         glJPanel.setPreferredSize(glc_sz);
         glJPanel.setSize(glc_sz);
-        glJPanel.addGLEventListener(new Gears());
+        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.getContentPane().validate();
-                    _frame.pack();
-                    _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 93dc885..3c33a48 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
@@ -83,7 +83,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 cc20cc2..0b907d5 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
@@ -34,6 +34,7 @@ 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;
@@ -49,6 +50,9 @@ import org.junit.Test;
 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() {
@@ -73,39 +77,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));
 
+        if( useAnimator ) {
+            animator.start();
+        }
+        
         int div = 3;
         glWindow.setSize(width/div, height/div);
         glWindow.setVisible(true);
-        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));
-        
-        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));
-
-        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));
-
-        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();
     }
 
@@ -115,17 +130,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/TestGearsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestTeapotNEWT.java
similarity index 57%
copy from src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestTeapotNEWT.java
index 93dc885..ddde837 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/TestTeapotNEWT.java
@@ -28,15 +28,13 @@
  
 package com.jogamp.opengl.test.junit.jogl.demos.gl2.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.UITestCase;
 import com.jogamp.opengl.test.junit.util.QuitAdapter;
 
 import com.jogamp.opengl.util.Animator;
 
-import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import com.jogamp.opengl.test.junit.jogl.demos.gl2.Teapot;
 
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLProfile;
@@ -46,7 +44,7 @@ import org.junit.BeforeClass;
 import org.junit.AfterClass;
 import org.junit.Test;
 
-public class TestGearsNEWT extends UITestCase {
+public class TestTeapotNEWT extends UITestCase {
     static GLProfile glp;
     static int width, height;
 
@@ -66,55 +64,83 @@ public class TestGearsNEWT extends UITestCase {
     public static void releaseClass() {
     }
 
-    protected void runTestGL(GLCapabilities caps) throws InterruptedException {
-        GLWindow glWindow = GLWindow.create(caps);
-        Assert.assertNotNull(glWindow);
-        glWindow.setTitle("Gears NEWT Test");
-
-        glWindow.addGLEventListener(new Gears());
+    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);
 
-        Animator animator = new Animator(glWindow);
-        QuitAdapter quitAdapter = new QuitAdapter();
+        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);
 
-        final GLWindow f_glWindow = glWindow;
-        glWindow.addKeyListener(new KeyAdapter() {
-            public void keyTyped(KeyEvent e) {
-                if(e.getKeyChar()=='f') {
-                    new Thread() {
-                        public void run() {
-                            f_glWindow.setFullscreen(!f_glWindow.isFullscreen());
-                    } }.start();
-                } else if(e.getKeyChar()=='d') {
-                    new Thread() {
-                        public void run() {
-                            f_glWindow.setUndecorated(!f_glWindow.isUndecorated());
-                    } }.start();
-                }
-            }
-        });
-
         glWindow.setSize(width, height);
         glWindow.setVisible(true);
-        animator.setUpdateFPSFrames(1, null);
-        animator.start();
+        if( withAnimator ) {
+            animator.setUpdateFPSFrames(60, System.err);
+            animator.start();
+        }
 
-        while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
+        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();
+            }
         }
 
-        animator.stop();
+        if( withAnimator ) {
+            animator.stop();
+        }
         glWindow.destroy();
     }
 
     @Test
-    public void test01() throws InterruptedException {
-        GLCapabilities caps = new GLCapabilities(glp);
-        runTestGL(caps);
+    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
@@ -128,6 +154,6 @@ public class TestGearsNEWT extends UITestCase {
                 } catch (Exception ex) { ex.printStackTrace(); }
             }
         }
-        org.junit.runner.JUnitCore.main(TestGearsNEWT.class.getName());
+        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 0000000..e692863
--- /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/gl2/newt/TestGearsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/newt/TestGeomShader01TextureGL3NEWT.java
similarity index 51%
copy from src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/newt/TestGearsNEWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/newt/TestGeomShader01TextureGL3NEWT.java
index 93dc885..71c0ae7 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/gl3/newt/TestGeomShader01TextureGL3NEWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -25,109 +25,102 @@
  * 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;
+package com.jogamp.opengl.test.junit.jogl.demos.gl3.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.UITestCase;
-import com.jogamp.opengl.test.junit.util.QuitAdapter;
-
-import com.jogamp.opengl.util.Animator;
-
-import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears;
+import java.io.IOException;
 
 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;
 
-public class TestGearsNEWT extends UITestCase {
-    static GLProfile glp;
-    static int width, height;
+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
+ */
+public class TestGeomShader01TextureGL3NEWT extends UITestCase {
+    static long duration = 500; // ms
 
-    @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);
+    static GLCapabilities getCaps(String profile) {
+        if( !GLProfile.isAvailable(profile) )  {
+            System.err.println("Profile "+profile+" n/a");
+            return null;
         }
+        return new GLCapabilities(GLProfile.get(profile));
     }
-
-    @AfterClass
-    public static void releaseClass() {
+    
+    @Test
+    public void test01_GL3Core_Passthrough() throws InterruptedException {
+        GLCapabilities caps = getCaps(GLProfile.GL3);
+        if( null == caps ) { return; }
+        testImpl(caps, 0);
     }
-
-    protected void runTestGL(GLCapabilities caps) throws InterruptedException {
+    
+    @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.setTitle("Gears NEWT Test");
-
-        glWindow.addGLEventListener(new Gears());
-
-        Animator animator = new Animator(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(new TraceKeyAdapter(quitAdapter));
-        //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter));
         glWindow.addKeyListener(quitAdapter);
         glWindow.addWindowListener(quitAdapter);
-
-        final GLWindow f_glWindow = glWindow;
-        glWindow.addKeyListener(new KeyAdapter() {
-            public void keyTyped(KeyEvent e) {
-                if(e.getKeyChar()=='f') {
-                    new Thread() {
-                        public void run() {
-                            f_glWindow.setFullscreen(!f_glWindow.isFullscreen());
-                    } }.start();
-                } else if(e.getKeyChar()=='d') {
-                    new Thread() {
-                        public void run() {
-                            f_glWindow.setUndecorated(!f_glWindow.isUndecorated());
-                    } }.start();
-                }
-            }
-        });
-
-        glWindow.setSize(width, height);
-        glWindow.setVisible(true);
-        animator.setUpdateFPSFrames(1, null);
+        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();
     }
-
-    @Test
-    public void test01() throws InterruptedException {
-        GLCapabilities caps = new GLCapabilities(glp);
-        runTestGL(caps);
-    }
-
-    static long duration = 500; // ms
-
-    public static void main(String args[]) {
+    
+    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(); }
+                duration = MiscUtils.atol(args[i], duration);
             }
         }
-        org.junit.runner.JUnitCore.main(TestGearsNEWT.class.getName());
+        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 0000000..f65ffac
--- /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 0000000..588b724
--- /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 0000000..61f4529
--- /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 0000000..b220c83
--- /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/glsl/GLSLMiscHelper.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java
index c2285ba..361c291 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(0, gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP
-        validateGLArrayDataServerState(gl, vertices0);
-        return vertices0;
+        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(0, gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP
-        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(0, gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP
-        validateGLArrayDataServerState(gl, colors0);
-        return colors0;
+        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(0, gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP
-        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 ab4b2d8..65b86c6 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
@@ -60,7 +60,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);
@@ -77,8 +193,8 @@ public class TestGLSLShaderState01NEWT extends UITestCase {
                 "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, ShaderCode.es2_default_precision_vp);
-        rsFp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+        rsVp.defaultShaderCustomization(gl, true, true);
+        rsFp.defaultShaderCustomization(gl, true, true);
 
         final ShaderProgram sp = new ShaderProgram();
         Assert.assertTrue(0 == sp.program());
@@ -95,33 +211,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());
@@ -138,18 +248,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);
@@ -168,13 +276,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);
@@ -183,15 +291,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);
@@ -226,13 +334,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
@@ -252,7 +358,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++) {
@@ -280,7 +386,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);
@@ -315,23 +421,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
@@ -351,8 +453,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) {
@@ -397,7 +499,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 7022b74..2e783e9 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
@@ -86,9 +86,9 @@ public class TestGLSLShaderState02NEWT extends UITestCase {
                 "shader/bin", "RedSquareShader", true);
         final ShaderCode rsFp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
                 "shader/bin", "RedSquareShader2", true);
-        rsVp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
-        rsFp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
-        rsFp1.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+        rsVp0.defaultShaderCustomization(gl, true, true);
+        rsFp0.defaultShaderCustomization(gl, true, true);
+        rsFp1.defaultShaderCustomization(gl, true, true);
 
         final ShaderProgram sp1 = new ShaderProgram();
         sp1.add(rsVp0);
@@ -121,20 +121,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());
@@ -166,14 +161,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);
         
@@ -194,16 +187,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);        
@@ -222,16 +215,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);
@@ -286,23 +279,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
@@ -323,11 +312,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/TestRulerNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java
index 98620e0..658e3e7 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;
@@ -77,8 +77,8 @@ public class TestRulerNEWT01 extends UITestCase {
                 "shader/bin", "default", true);
         final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader",
                 "shader/bin", "ruler", true);
-        vp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
-        fp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+        vp0.defaultShaderCustomization(gl, true, true);
+        fp0.defaultShaderCustomization(gl, true, true);
 
         final ShaderProgram sp0 = new ShaderProgram();
         sp0.add(gl, vp0, System.err);
@@ -109,11 +109,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 d133ebd..4d87843 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
@@ -81,7 +81,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 +130,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/glu/TestBug694ScaleImageUnpackBufferSizeAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug694ScaleImageUnpackBufferSizeAWT.java
new file mode 100644
index 0000000..d3bcce1
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/glu/TestBug694ScaleImageUnpackBufferSizeAWT.java
@@ -0,0 +1,160 @@
+/**
+ * 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 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)}.
+ */
+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/acore/TestFloatUtil01MatrixMatrixMultNOUI.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil01MatrixMatrixMultNOUI.java
old mode 100755
new mode 100644
similarity index 98%
rename from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFloatUtil01MatrixMatrixMultNOUI.java
rename to src/test/com/jogamp/opengl/test/junit/jogl/math/TestFloatUtil01MatrixMatrixMultNOUI.java
index 42b5972..83a1be4
--- 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,12 +26,12 @@
  * 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 com.jogamp.opengl.FloatUtil;
+import com.jogamp.opengl.math.FloatUtil;
 
 public class TestFloatUtil01MatrixMatrixMultNOUI {
 
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
old mode 100755
new mode 100644
similarity index 98%
rename from src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectDoubleNOUI.java
rename to src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectDoubleNOUI.java
index 34b30f0..32861f7
--- 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,7 +26,7 @@
  * 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;
 
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
old mode 100755
new mode 100644
similarity index 98%
rename from src/test/com/jogamp/opengl/test/junit/jogl/glu/TestGluUnprojectFloatNOUI.java
rename to src/test/com/jogamp/opengl/test/junit/jogl/math/TestGluUnprojectFloatNOUI.java
index 717d5e4..9951500
--- 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,7 +26,7 @@
  * 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;
 
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPMVMatrix01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java
similarity index 82%
rename from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPMVMatrix01NEWT.java
rename to src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java
index c44a82a..3d9bfed 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPMVMatrix01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix01NEWT.java
@@ -26,7 +26,7 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.jogl.acore;
+package com.jogamp.opengl.test.junit.jogl.math;
 
 import java.nio.FloatBuffer;
 
@@ -44,7 +44,8 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 import com.jogamp.common.os.Platform;
-import com.jogamp.opengl.FloatUtil;
+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;
@@ -136,18 +137,20 @@ public class TestPMVMatrix01NEWT extends UITestCase {
     /**
      * Test using traditional access workflow, i.e. 1) operation 2) get-matrix references
      * <p>
-     * The Mvi and Mvit dirty-bits and request-mask will be validated.
+     * 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());
         
         //
@@ -164,6 +167,7 @@ public class TestPMVMatrix01NEWT extends UITestCase {
         }        
         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());
         
         //
@@ -172,12 +176,14 @@ public class TestPMVMatrix01NEWT extends UITestCase {
         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());
         
@@ -190,14 +196,19 @@ public class TestPMVMatrix01NEWT extends UITestCase {
         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("Remaining dirty bits not Mvit, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW, pmv.getDirtyBits());
         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 and Mvit not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW, pmv.getRequestMask());        
+        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());
 
         //
@@ -206,37 +217,42 @@ public class TestPMVMatrix01NEWT extends UITestCase {
         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("Request bits Mvi and Mvit not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW, pmv.getRequestMask());
+        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 and Mvit not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW, pmv.getRequestMask());
+        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 and Mvit dirty-bits and request-mask will be validated.
+     * 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());
         
         //
@@ -254,6 +270,7 @@ public class TestPMVMatrix01NEWT extends UITestCase {
         // 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());
         
@@ -269,31 +286,38 @@ public class TestPMVMatrix01NEWT extends UITestCase {
         
         mvi  = pmv.glGetMviMatrixf();
         MiscUtils.assertFloatBufferEquals("Mvi not identity, "+pmv.toString(), ident, mvi, epsilon);        
-        Assert.assertEquals("Remaining dirty bits not Mvit, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW, pmv.getDirtyBits());
+        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.assertTrue("Dirty bits not clean, "+pmv.toString(), 0 == pmv.getDirtyBits());
+        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 and Mvit not set, "+pmv.toString(), PMVMatrix.DIRTY_INVERSE_MODELVIEW | PMVMatrix.DIRTY_INVERSE_TRANSPOSED_MODELVIEW, pmv.getRequestMask());
+        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());        
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPMVMatrix02NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix02NOUI.java
similarity index 92%
rename from src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPMVMatrix02NEWT.java
rename to src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix02NOUI.java
index 4e959d4..0c66ad2 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestPMVMatrix02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix02NOUI.java
@@ -26,7 +26,7 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.jogl.acore;
+package com.jogamp.opengl.test.junit.jogl.math;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -41,7 +41,7 @@ import static org.junit.Assert.assertArrayEquals;
 /**
  * @author Thomas De Bodt
  */
-public class TestPMVMatrix02NEWT {
+public class TestPMVMatrix02NOUI {
 
   private PMVMatrix fMat;
 
@@ -104,6 +104,6 @@ public class TestPMVMatrix02NEWT {
   }
 
   public static void main(String args[]) {
-      org.junit.runner.JUnitCore.main(TestPMVMatrix02NEWT.class.getName());
+      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 0000000..81242ce
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/math/TestPMVMatrix03NOUI.java
@@ -0,0 +1,125 @@
+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;
+
+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 b165a96..d8a2e78 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;
@@ -140,24 +142,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 +210,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 +264,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 +278,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 +318,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/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java
new file mode 100644
index 0000000..e7037aa
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlockAWT.java
@@ -0,0 +1,405 @@
+/**
+ * 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.Assume;
+import org.junit.Test;
+
+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 junit.framework.Assert;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+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;
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+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 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;
+        
+        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;            
+        }
+    }
+    
+    @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 ) ;
+            glWindow = GLWindow.create( 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() ;
+            } } );
+                        
+        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
index fe40cec..396d219 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java
@@ -52,6 +52,7 @@ 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.MiscUtils;
 import com.jogamp.opengl.test.junit.util.UITestCase;
 import com.jogamp.opengl.util.Animator;
 import com.jogamp.opengl.util.GLReadBufferUtil;
@@ -92,6 +93,9 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
             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() );
@@ -107,10 +111,13 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
         Assert.assertNotNull( shell );
         Assert.assertNotNull( composite );
         try {
-            SWTAccessor.invoke(true, new Runnable() {
+            display.syncExec(new Runnable() {
                public void run() {
                 composite.dispose();
                 shell.dispose();
+               }});
+            SWTAccessor.invoke(true, new Runnable() {
+               public void run() {
                 display.dispose();
                }});
         }
@@ -148,7 +155,7 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
         final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite, 0, postAttach ? null : glWindow1 );
         Assert.assertNotNull( canvas1 );
 
-        SWTAccessor.invoke(true, new Runnable() {
+        display.syncExec( new Runnable() {
            public void run() {
               shell.setText( getSimpleTestName(".") );
               shell.setSize( 640, 480 );
@@ -213,18 +220,10 @@ public class TestNewtCanvasSWTGLn extends UITestCase {
         runTestAGL( caps, new MultisampleDemoES2(true), false /* postAttach */, false /* animator */);
     }
 
-    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]);
+                duration = MiscUtils.atoi(args[++i],  duration);
             }
         }
         System.out.println("durationPerTest: "+duration);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
index 91902a8..ee5dc7f 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTAccessor03AWTGLn.java
@@ -83,10 +83,17 @@ public class TestSWTAccessor03AWTGLn extends UITestCase {
             return;
         }
         System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); 
-        Frame f0 = new Frame("Test - AWT 1st");
+        final Frame f0 = new Frame("Test - AWT 1st");
         f0.add(new java.awt.Label("AWT was here 1st"));
-        f0.pack();
-        f0.setVisible(true);
+        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);
         }
@@ -113,14 +120,18 @@ public class TestSWTAccessor03AWTGLn extends UITestCase {
         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() {
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 0000000..66911ef
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java
@@ -0,0 +1,342 @@
+/**
+ * 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.Assume;
+import org.junit.Test;
+
+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 junit.framework.Assert;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+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;
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+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 Display swtDisplay ;
+        private 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
+                {
+                    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, null);
+                final SWTNewtEventFactory swtNewtEventFactory = new SWTNewtEventFactory();
+                swtNewtEventFactory.attachDispatchListener(glc, glc, demo.gearsMouse, demo.gearsKeys);
+                glc.addGLEventListener( demo ) ;
+                glad = glc; 
+                newtDisplay = null;                
+            } else if( useNewtCanvasSWT ) {
+                final GLWindow glWindow = GLWindow.create( caps ) ;
+                glWindow.addGLEventListener( new GearsES2() ) ;
+                newtDisplay = glWindow.getScreen().getDisplay();
+                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/TestSWTJOGLGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
index 6d9e221..1822d2e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java
@@ -50,17 +50,18 @@ import org.junit.Test;
 import com.jogamp.nativewindow.swt.SWTAccessor;
 import com.jogamp.opengl.swt.GLCanvas;
 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>
- * <p>
- * Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used.
+ * Uses JOGL's new SWT GLCanvas,
+ * which 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/ 
@@ -71,7 +72,8 @@ import com.jogamp.opengl.util.texture.TextureIO;
 public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
 
     static int duration = 250;
-
+    static boolean doAnimation = true;
+    
     static final int iwidth = 640;
     static final int iheight = 480;
 
@@ -90,10 +92,13 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
             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 = new Composite( shell, SWT.NO_BACKGROUND );
                 composite.setLayout( new FillLayout() );
                 Assert.assertNotNull( composite );
             }});
@@ -105,10 +110,13 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
         Assert.assertNotNull( shell );
         Assert.assertNotNull( composite );
         try {
-            SWTAccessor.invoke(true, new Runnable() {
+            display.syncExec(new Runnable() {
                public void run() {
                 composite.dispose();
                 shell.dispose();
+               }});
+            SWTAccessor.invoke(true, new Runnable() {
+               public void run() {
                 display.dispose();
                }});
         }
@@ -140,13 +148,19 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
            public void dispose(final GLAutoDrawable drawable) { }
         });       
        
-        SWTAccessor.invoke(true, new Runnable() {
+        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;
         try {
@@ -160,7 +174,10 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
             throwable.printStackTrace();
             Assume.assumeNoException( throwable );
         }
-        SWTAccessor.invoke(true, new Runnable() {
+        
+        anim.stop();
+        
+        display.syncExec(new Runnable() {
            public void run() {
                canvas.dispose();
            } } );
@@ -171,6 +188,14 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
         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) {
         int i=0;
         try {
@@ -183,6 +208,8 @@ public class TestSWTJOGLGLCanvas01GLn 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);
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
index 276fb17..c82e7de 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1ImmModeSink.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1ImmModeSink.java
@@ -1,3 +1,30 @@
+/**
+ * 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;
@@ -68,8 +95,6 @@ class DemoGL2ES1ImmModeSink implements GLEventListener {
 
         gl.glMatrixMode( GL2ES1.GL_MODELVIEW );
         gl.glLoadIdentity();
-
-        gl.glViewport( 0, 0, width, height );        
     }
     
     @Override
@@ -79,15 +104,13 @@ class DemoGL2ES1ImmModeSink implements GLEventListener {
         gl.glClear( GL.GL_COLOR_BUFFER_BIT );
 
         // draw a triangle filling the window
-        gl.glLoadIdentity();
-        
         ims.glBegin(GL.GL_TRIANGLES);
         ims.glColor3f( 1, 0, 0 );
         ims.glVertex2f( 0, 0 );
         ims.glColor3f( 0, 1, 0 );
-        ims.glVertex2f( TestImmModeSinkES1NEWT.iWidth, 0 );
+        ims.glVertex2f( drawable.getWidth(), 0 );
         ims.glColor3f( 0, 0, 1 );
-        ims.glVertex2f( TestImmModeSinkES1NEWT.iWidth / 2, TestImmModeSinkES1NEWT.iHeight );
+        ims.glVertex2f( drawable.getWidth() / 2, drawable.getHeight() );
         ims.glEnd(gl, true);
     }
 
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
index b66a095..0df3686 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1Plain.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1Plain.java
@@ -1,3 +1,30 @@
+/**
+ * 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;
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 0000000..b38ae85
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES2ImmModeSink.java
@@ -0,0 +1,207 @@
+/**
+ * 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();        
+    }
+
+    static final String[] es2_prelude = { "#version 100\n", "precision mediump float;\n" };
+    static final String gl2_prelude = "#version 110\n";
+    
+    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);
+        
+        // Prelude shader code w/ GLSL profile specifics [ 1. pre-proc, 2. other ]
+        int fp0Pos;
+        if(gl.isGLES2()) {
+            vp0.insertShaderSource(0, 0, es2_prelude[0]);
+            fp0Pos = fp0.insertShaderSource(0, 0, es2_prelude[0]);
+        } else {
+            vp0.insertShaderSource(0, 0, gl2_prelude);
+            fp0Pos = fp0.insertShaderSource(0, 0, gl2_prelude);
+        }
+        if(gl.isGLES2()) {
+            fp0Pos = fp0.insertShaderSource(0, fp0Pos, es2_prelude[1]);
+        }        
+        
+        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/TestImmModeSinkES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES2NEWT.java
new file mode 100644
index 0000000..48f1df7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/TestImmModeSinkES2NEWT.java
@@ -0,0 +1,119 @@
+/**
+ * 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 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
+ */
+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 = getCaps(GLProfile.GL2ES2);
+        if(null == reqGLCaps) return;
+        doTest(reqGLCaps, new DemoGL2ES2ImmModeSink(false, false));
+    }
+    
+    @Test
+    public void test05ImmSinkGL2ES2_VBOOff_ShaderState() throws InterruptedException {
+        final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+        if(null == reqGLCaps) return;
+        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 c7e975f..0000000
--- 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, this.getClass().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/TestJPEGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java
new file mode 100644
index 0000000..bf8323e
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java
@@ -0,0 +1,124 @@
+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 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;
+
+public class TestJPEGImage01NEWT extends UITestCase {
+    
+    static boolean showFPS = false;
+    static long duration = 100; // ms
+    
+    public void testImpl(final boolean withAlpha, final InputStream istream) throws InterruptedException, IOException {
+        final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
+        final GLProfile glp = GLProfile.getGL2ES2();
+        final GLCapabilities caps = new GLCapabilities(glp);
+        if( withAlpha ) {
+            caps.setAlphaBits(1);
+        }
+        
+        final JPEGImage image = JPEGImage.read(istream);
+        Assert.assertNotNull(image);
+        System.err.println("JPEGImage: "+image);
+        
+        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 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 ) ;
+        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_RGB() 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(false, 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 0000000..1e27f5d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java
@@ -0,0 +1,151 @@
+/**
+ * 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;
+
+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 0000000..0df2756
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java
@@ -0,0 +1,267 @@
+/**
+ * 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;
+
+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 ) ;
+        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 ) ;
+            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 0000000..82867f9
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java
@@ -0,0 +1,281 @@
+/**
+ * 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;
+
+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.GL2GL3)) {
+            glp = GLProfile.getGL2GL3();
+        } 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 ) ;
+        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/TestPNGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java
new file mode 100644
index 0000000..81f64f0
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java
@@ -0,0 +1,62 @@
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+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 File out2F_f=new File(getSimpleTestName(".")+"-PNGImageTest2Flipped.png");
+        final File out2R_f=new File(getSimpleTestName(".")+"-PNGImageTest2Reversed.png");
+        final File out2RF_f=new File(getSimpleTestName(".")+"-PNGImageTest2ReversedFlipped.png");
+        final String url_s="jogl/util/data/av/test-ntsc01-160x90.png";
+        URLConnection urlConn = IOUtil.getResource(url_s, this.getClass().getClassLoader());
+        PNGImage image1 = PNGImage.read(urlConn.getInputStream());
+        System.err.println("PNGImage - Orig: "+image1);        
+        image1.write(out1_f, true); 
+        {
+            Assert.assertEquals(image1.getData(), PNGImage.read(out1_f.toURI().toURL().openStream()).getData());
+        }
+        
+        final PNGImage image2 = PNGImage.createFromData(image1.getWidth(), image1.getHeight(), 
+                                                        image1.getDpi()[0], image1.getDpi()[1], 
+                                                        image1.getBytesPerPixel(), false /* reverseChannels */, image1.isGLOriented(), image1.getData());
+        image2.write(out2_f, true);
+        {
+            Assert.assertEquals(image1.getData(), PNGImage.read(out2_f.toURI().toURL().openStream()).getData());
+        }
+        
+        // flipped
+        final PNGImage image2F = PNGImage.createFromData(image1.getWidth(), image1.getHeight(), 
+                                                         image1.getDpi()[0], image1.getDpi()[1], 
+                                                         image1.getBytesPerPixel(), false /* reverseChannels */, !image1.isGLOriented(), image1.getData());
+        image2F.write(out2F_f, true);
+        
+        // reversed channels
+        final PNGImage image2R = PNGImage.createFromData(image1.getWidth(), image1.getHeight(), 
+                                                         image1.getDpi()[0], image1.getDpi()[1], 
+                                                         image1.getBytesPerPixel(), true /* reverseChannels */, image1.isGLOriented(), image1.getData());
+        image2R.write(out2R_f, true);
+        
+        // reversed channels and flipped
+        final PNGImage image2RF = PNGImage.createFromData(image1.getWidth(), image1.getHeight(), 
+                                                         image1.getDpi()[0], image1.getDpi()[1], 
+                                                         image1.getBytesPerPixel(), true /* reverseChannels */, !image1.isGLOriented(), image1.getData());
+        image2RF.write(out2RF_f, true);
+    }
+    
+    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/TestPNGTextureFromFileAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java
index 7dbccd5..651eeb5 100644
--- 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
@@ -83,10 +83,12 @@ public class TestPNGTextureFromFileAWT extends UITestCase {
     public void initTest() throws IOException {
         grayTextureStream = TestPNGTextureFromFileAWT.class.getResourceAsStream( "grayscale_texture.png" );
         Assert.assertNotNull(grayTextureStream);
-        URLConnection testTextureUrlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-160x90.png", this.getClass().getClassLoader());
-        Assert.assertNotNull(testTextureUrlConn);
-        testTextureStream = testTextureUrlConn.getInputStream();
-        Assert.assertNotNull(testTextureStream);
+        {
+            URLConnection testTextureUrlConn = IOUtil.getResource(this.getClass(), "test-ntscN_3-01-160x90.png");
+            Assert.assertNotNull(testTextureUrlConn);
+            testTextureStream = testTextureUrlConn.getInputStream();
+            Assert.assertNotNull(testTextureStream);
+        }
     }
 
     @After
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
index e9ef9b9..773b839 100644
--- 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
@@ -61,22 +61,90 @@ public class TestPNGTextureFromFileNEWT extends UITestCase {
     static boolean showFPS = false;
     static long duration = 100; // ms
     InputStream grayTextureStream;
-    InputStream testTextureStream;
+    
+    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("jogl/util/data/av/test-ntsc01-160x90.png", this.getClass().getClassLoader());
-        Assert.assertNotNull(testTextureUrlConn);
-        testTextureStream = testTextureUrlConn.getInputStream();
-        Assert.assertNotNull(testTextureStream);
+        {
+            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;
-        testTextureStream = 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 {
@@ -91,8 +159,10 @@ public class TestPNGTextureFromFileNEWT extends UITestCase {
             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);
+        System.err.println("TextureData: "+texData);        
         
         final GLWindow glad = GLWindow.create(caps);
         glad.setTitle("TestPNGTextureGL2FromFileNEWT");
@@ -137,22 +207,60 @@ public class TestPNGTextureFromFileNEWT extends UITestCase {
     }
     
     @Test
-    public void testGrayPNGJLoaderGL2() throws InterruptedException, IOException {
+    public void testGray__GL2() throws InterruptedException, IOException {
         testImpl(true, grayTextureStream);        
     }    
     @Test
-    public void testGrayPNGJLoaderES2() throws InterruptedException, IOException {
+    public void testGray__ES2() throws InterruptedException, IOException {
         testImpl(false, grayTextureStream);        
     }
     
     @Test
-    public void testTestPNGJLoaderGL2() throws InterruptedException, IOException {
-        testImpl(true, testTextureStream);        
+    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 testTestPNGJLoaderES2() throws InterruptedException, IOException {
-        testImpl(false, testTextureStream);        
+    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++) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
index 2d7b3b0..c333846 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
@@ -29,17 +29,25 @@
 package com.jogamp.opengl.test.junit.jogl.util.texture;
 
 
+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;
@@ -54,7 +62,14 @@ import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+/**
+ * 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. 
+ */
 public class TestTexture01AWT extends UITestCase {
+    static long durationPerTest = 500;
     static GLProfile glp;
     static GLCapabilities caps;
     BufferedImage textureImage;
@@ -107,29 +122,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 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();
+            }            
+        });
 
-        Animator animator = new Animator(glCanvas);
-        frame.setVisible(true);
-        animator.start();
-
-        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 +198,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/util/texture/TestTexture01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java
similarity index 51%
copy from src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
copy to src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java
index 2d7b3b0..5948f59 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java
@@ -29,107 +29,113 @@
 package com.jogamp.opengl.test.junit.jogl.util.texture;
 
 
-import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener;
+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.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.awt.AWTTextureIO;
-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.AlphaComposite;
-import java.awt.Color;
 import java.awt.Frame;
-import java.awt.GradientPaint;
-import java.awt.Graphics2D;
 import java.awt.image.BufferedImage;
 
 import java.io.IOException;
 import org.junit.Assert;
-import org.junit.After;
 import org.junit.Assume;
-import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-public class TestTexture01AWT extends UITestCase {
+/**
+ * Demonstrates TextureData w/ AWT usage,
+ * i.e. reading out an animated GL framebuffer and displaying it 
+ * as an BufferedImage. 
+ */
+public class TestTexture02AWT extends UITestCase {
+    static long durationPerTest = 500;
     static GLProfile glp;
     static GLCapabilities caps;
-    BufferedImage textureImage;
 
     @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() {
-        // create base image
-        BufferedImage baseImage = new BufferedImage(256, 256, BufferedImage.TYPE_3BYTE_BGR);
-        Assert.assertNotNull(baseImage);
-        Graphics2D g = baseImage.createGraphics();
-        Assert.assertNotNull(g);
-        g.setPaint(new GradientPaint(0, 0, Color.CYAN,
-                                 baseImage.getWidth(), baseImage.getHeight(), Color.BLUE));
-        g.fillRect(0, 0, baseImage.getWidth(), baseImage.getHeight());
-        g.dispose();
-
-        // create texture image
-        int imageType = BufferedImage.TYPE_3BYTE_BGR;
-        textureImage = new BufferedImage(baseImage.getWidth(),
-                                         baseImage.getHeight(),
-                                         imageType);
-        Assert.assertNotNull(textureImage);
-        g = textureImage.createGraphics();
-        g.setComposite(AlphaComposite.Src);
-        g.drawImage(baseImage, 0, 0, null);
-        g.dispose();
-
-        baseImage.flush();
-        baseImage=null;
-    }
-
-    @After
-    public void cleanupTest() {
-        Assert.assertNotNull(textureImage);
-        textureImage.flush();
-        textureImage=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(512, 512);
-
-        // create texture    
-        TextureData textureData = AWTTextureIO.newTextureData(caps.getGLProfile(), textureImage, false);
-        glCanvas.addGLEventListener(new TextureDraw01GL2Listener(textureData));
+        final Frame frame1 = new Frame("GearsES2");
+        Assert.assertNotNull(frame1);
+        frame1.add(glCanvas);
+
+        glCanvas.addGLEventListener(new GearsES2(1));
+        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.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();
@@ -138,7 +144,12 @@ public class TestTexture01AWT extends UITestCase {
     }
 
     public static void main(String args[]) throws IOException {
-        String tstname = TestTexture01AWT.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
index 36dad45..7bad837 100644
--- 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
@@ -42,7 +42,6 @@ public class TestTextureSequence01AWT extends UITestCase {
         final Frame frame = new Frame("TestTextureSequence01AWT");
         Assert.assertNotNull(frame);
         frame.add(glc);
-        frame.setSize(width, height);
         
         final TextureSequenceDemo01 texSource = new TextureSequenceDemo01(useBuildInTexLookup);
         glc.addGLEventListener(new GLEventListener() {
@@ -63,7 +62,16 @@ public class TestTextureSequence01AWT extends UITestCase {
         QuitAdapter quitAdapter = new QuitAdapter();
         new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter).addTo(glc);
         new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter).addTo(glc);
-        frame.setVisible(true);
+        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) {
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
new file mode 100644
index 0000000..1c70093
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/bug745_qttdef_post_frame.jpg differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/grayscale_texture.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/grayscale_texture.png
old mode 100755
new mode 100644
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
new file mode 100644
index 0000000..8efe6af
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j1-baseline.jpg differ
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
new file mode 100644
index 0000000..aa5fbd0
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j2-progressive.jpg differ
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
new file mode 100644
index 0000000..048eb79
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/j3-baseline_gray.jpg differ
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
new file mode 100644
index 0000000..40a300f
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-cmyk-01.jpg differ
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
new file mode 100644
index 0000000..b90a909
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG3-01-160x90.png differ
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
new file mode 100644
index 0000000..db0ae01
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscIG4-01-160x90.png differ
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
new file mode 100644
index 0000000..e579c58
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_3-01-160x90.png differ
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
new file mode 100644
index 0000000..e42d22b
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscI_4-01-160x90.png differ
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
new file mode 100644
index 0000000..762ba3e
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscNG4-01-160x90.png differ
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
new file mode 100644
index 0000000..8e4fe9a
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-base.jpg differ
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
new file mode 100644
index 0000000..35556f9
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-60pct-yuv422h-prog.jpg differ
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
new file mode 100644
index 0000000..051a166
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpg differ
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
new file mode 100644
index 0000000..40b0fc8
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-prog.jpg differ
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
new file mode 100644
index 0000000..3df4743
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90.png differ
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
new file mode 100644
index 0000000..c233c34
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_4-01-160x90.png differ
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
new file mode 100644
index 0000000..32e7f00
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_3-01-160x90.png differ
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
new file mode 100644
index 0000000..55405ee
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscP_4-01-160x90.png differ
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
new file mode 100644
index 0000000..84c1984
Binary files /dev/null and b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/test-ycck-01.jpg differ
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java
index 29ec443..875e4fe 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/ManualScreenMode03NEWT.java
@@ -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;
@@ -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 {
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 4ebb7dd..d631934 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestCloseNewtAWT.java
@@ -45,6 +45,7 @@ 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;
 
 public class TestCloseNewtAWT extends UITestCase {
 
@@ -107,9 +108,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 c9450c2..e4867e3 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestDisplayLifecycle01NEWT.java
@@ -89,7 +89,7 @@ public class TestDisplayLifecycle01NEWT extends UITestCase {
         Assert.assertEquals(0,display.getReferenceCount());
         Assert.assertEquals(false,display.isNativeValid());
         Assert.assertNotNull(display.getEDTUtil());
-        Assert.assertEquals(false,display.getEDTUtil().isRunning());
+        Assert.assertEquals(true,display.getEDTUtil().isRunning());
         Assert.assertEquals(0,screen.getReferenceCount());
         Assert.assertEquals(false,screen.isNativeValid());
 
@@ -201,6 +201,8 @@ public class TestDisplayLifecycle01NEWT extends UITestCase {
         Assert.assertEquals(false,display.isNativeValid());
         Assert.assertNotNull(display.getEDTUtil());
         Assert.assertEquals(false,display.getEDTUtil().isRunning());
+        display.getEDTUtil().invoke(true, null);
+        Assert.assertEquals(true,display.getEDTUtil().isRunning());
         Assert.assertEquals(0,screen.getReferenceCount());
         Assert.assertEquals(false,screen.isNativeValid());
 
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus01SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/TestFocus01SwingAWTRobot.java
index 5d6218d..78be14d 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus01SwingAWTRobot.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestFocus01SwingAWTRobot.java
@@ -115,7 +115,8 @@ 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");
         newtCanvasAWT.addKeyListener(newtCanvasAWTKA);
@@ -126,8 +127,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");
@@ -146,7 +145,7 @@ 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));
 
@@ -167,7 +166,7 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
         
         System.err.println("FOCUS AWT  Button request");
         EventCountAdapterUtil.reset(eventCountAdapters);
-        AWTRobotUtil.assertRequestFocusAndWait(robot, button, button, buttonFA, frame1FA); // OSX sporadically button did not gain - major UI failure
+        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");
@@ -182,8 +181,13 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
         System.err.println("FOCUS NEWT Canvas/GLWindow request");
         EventCountAdapterUtil.reset(eventCountAdapters);
         AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonFA); // OSX sporadically button did not loose - minor UI failure
-        Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, 
-                AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA));
+        // 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());
@@ -207,6 +211,7 @@ public class TestFocus01SwingAWTRobot extends UITestCase {
             Assume.assumeNoException( throwable );
         }        
         glWindow1.destroy();
+        Assert.assertEquals(true,  AWTRobotUtil.waitForRealized(glWindow1, false));
     }
 
     static int atoi(String a) {
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java
index 0e87144..5b07c73 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java
@@ -72,15 +72,20 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
     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);
     }
@@ -126,7 +131,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);
@@ -143,7 +148,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);
@@ -152,8 +157,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);
@@ -183,7 +186,7 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
         Thread.sleep(100); // allow event sync
         System.err.println("FOCUS AWT  Button Outer request");
         EventCountAdapterUtil.reset(eventCountAdapters);
-        AWTRobotUtil.assertRequestFocusAndWait(robot, buttonNorthOuter, buttonNorthOuter, buttonNorthOuterFA, jFrame1FA); // OSX sporadically buttonNorthOuter did not gain - major UI failure
+        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());
@@ -199,9 +202,14 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
         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());
@@ -216,9 +224,9 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
         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, 
@@ -231,12 +239,15 @@ 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("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, 
-                AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA));
+        // 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, newtCanvasAWTFA.focusGained());
         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());
@@ -249,17 +260,15 @@ public class TestFocus02SwingAWTRobot extends UITestCase {
         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
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 0000000..ba69481
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowInvisiblePointer01NEWT.java
@@ -0,0 +1,114 @@
+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 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;
+
+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 0000000..ffbd9d1
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindowWarpPointer01NEWT.java
@@ -0,0 +1,171 @@
+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 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;
+
+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/TestGLWindows02NEWTAnimated.java b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java
index 6f4ced5..64c5e9c 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestGLWindows02NEWTAnimated.java
@@ -132,7 +132,7 @@ public class TestGLWindows02NEWTAnimated extends UITestCase {
         
         animator.remove(window);
         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 +142,24 @@ 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());
+        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);
         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 +184,13 @@ 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());
+        Assert.assertEquals(false, animator.isAnimating()); // zero drawables
+        Assert.assertEquals(true, animator.isPaused()); // zero drawables
 
         animator.add(window1);
         Assert.assertEquals(true, animator.isStarted());
@@ -214,8 +217,8 @@ 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());
+        Assert.assertEquals(false, animator.isAnimating()); // zero drawables
+        Assert.assertEquals(true, animator.isPaused()); // zero drawables
         Assert.assertTrue(animator.stop());
     }
 
@@ -250,8 +253,8 @@ public class TestGLWindows02NEWTAnimated extends UITestCase {
 
         Assert.assertTrue(animator.start());
         Assert.assertEquals(true, animator.isStarted());
-        Assert.assertEquals(false, animator.isAnimating());
-        Assert.assertEquals(false, animator.isPaused());
+        Assert.assertEquals(false, animator.isAnimating()); // zero drawables
+        Assert.assertEquals(true, animator.isPaused()); // zero drawables
 
         animator.add(window1);
         Assert.assertEquals(true, animator.isStarted());
@@ -275,21 +278,28 @@ 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());
+        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/TestScreenMode00NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java
index 577119b..f64cf2e 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00NEWT.java
@@ -35,18 +35,23 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+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.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.Rectangle;
 import javax.media.nativewindow.util.SurfaceSize;
+import javax.media.opengl.GLProfile;
+
+import jogamp.newt.MonitorDeviceImpl;
+import jogamp.newt.MonitorModeProps;
 
 public class TestScreenMode00NEWT extends UITestCase {
     static int screenIdx = 0;
@@ -59,6 +64,7 @@ public class TestScreenMode00NEWT extends UITestCase {
 
     @BeforeClass
     public static void initClass() {
+        GLProfile.initSingleton(); // hack to initialize GL for BCM_IV (Rasp.Pi)
         NativeWindowFactory.initSingleton();
         width  = 640;
         height = 480;
@@ -66,31 +72,46 @@ public class TestScreenMode00NEWT extends UITestCase {
 
     @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);
+        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);    
+        }
         
-        Assert.assertEquals(sm_out.hashCode(), sm_in.hashCode());
+        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
@@ -101,21 +122,37 @@ public class TestScreenMode00NEWT extends UITestCase {
         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());
+        List<MonitorMode> allMonitorModes = screen.getMonitorModes();
+        Assert.assertTrue(allMonitorModes.size()>0);
+        {
+            int i=0;
+            for(Iterator<MonitorMode> iMode=allMonitorModes.iterator(); iMode.hasNext(); i++) {
+                System.err.println("All["+i+"]: "+iMode.next());
+            }
+        }
+        
+        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;
+            for(Iterator<MonitorMode> iMode=modes.iterator(); iMode.hasNext(); i++) {
+                System.err.println("["+j+"]["+i+"]: "+iMode.next());
+            }
+            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);
         }
-        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();
 
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java
index 75a3126..fe5dd93 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode00bNEWT.java
@@ -36,11 +36,13 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 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;
 
@@ -81,23 +83,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 +111,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/TestScreenMode01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java
index f253f3b..a2ce7ce 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01NEWT.java
@@ -40,12 +40,13 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 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;
@@ -149,14 +150,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);
 
@@ -192,45 +195,53 @@ 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) {
+        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 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);
         
-        screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
-        Assert.assertNotNull(screenModes);
-        Assert.assertTrue(screenModes.size()>0);
+        monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+        Assert.assertNotNull(monitorModes);
+        Assert.assertTrue(monitorModes.size()>0);
 
-        ScreenMode sm = (ScreenMode) screenModes.get(0);
+        MonitorMode sm = (MonitorMode) monitorModes.get(0);
         System.err.println("[0] set current: "+sm);
-        screen.setCurrentScreenMode(sm);
-        Assert.assertEquals(sm, screen.getCurrentScreenMode());
-        Assert.assertNotSame(smOrig, screen.getCurrentScreenMode());
-
+        monitor.setCurrentMode(sm);
+        Assert.assertTrue(monitor.isModeChangedByUs());
+        Assert.assertEquals(sm, monitor.getCurrentMode());
+        Assert.assertNotSame(mmOrig, monitor.getCurrentMode());
+        Assert.assertEquals(sm, monitor.queryCurrentMode());        
+        
         Thread.sleep(waitTimeLong);
 
         // check reset ..
@@ -250,6 +261,7 @@ public class TestScreenMode01NEWT extends UITestCase {
         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());
 
@@ -258,15 +270,14 @@ public class TestScreenMode01NEWT extends UITestCase {
         Assert.assertEquals(true,display.isNativeValid());
         Assert.assertEquals(true,screen.isNativeValid());
 
-        smCurrent = screen.getCurrentScreenMode();
-        System.err.println("[1] current/orig: "+smCurrent);
+        mmCurrent = monitor.getCurrentMode();
+        System.err.println("[1] current/orig: "+mmCurrent);
         screen.destroy();
         Assert.assertEquals(false,screen.isNativeValid());
         Assert.assertEquals(false,display.isNativeValid());
 
-        Assert.assertNotNull(smCurrent);
-        Assert.assertEquals(smCurrent, smOrig);
-
+        Assert.assertNotNull(mmCurrent);
+        Assert.assertEquals(mmCurrent, mmOrig);
         
         cleanupGL();
     }
@@ -291,27 +302,30 @@ 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);
+        MonitorDevice monitor = window.getMainMonitor();
+        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());
@@ -321,8 +335,8 @@ public class TestScreenMode01NEWT extends UITestCase {
             System.err.println("[0] set FS pre X: "+window.isFullscreen());
         }
 
-        System.err.println("[0] set current: "+screenMode);
-        screen.setCurrentScreenMode(screenMode);
+        System.err.println("[0] set current: "+monitorMode);
+        monitor.setCurrentMode(monitorMode);
         
         if(!preFS) {
             System.err.println("[0] set FS post 0: "+window.isFullscreen());
@@ -350,6 +364,7 @@ public class TestScreenMode01NEWT extends UITestCase {
         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());
 
@@ -358,14 +373,14 @@ public class TestScreenMode01NEWT extends UITestCase {
         Assert.assertEquals(true,display.isNativeValid());
         Assert.assertEquals(true,screen.isNativeValid());
         
-        smCurrent = screen.getCurrentScreenMode();
-        System.err.println("[1] current/orig: "+smCurrent);
+        mmCurrent = monitor.getCurrentMode();
+        System.err.println("[1] current/orig: "+mmCurrent);
         screen.destroy();
         Assert.assertEquals(false,screen.isNativeValid());
         Assert.assertEquals(false,display.isNativeValid());
 
-        Assert.assertNotNull(smCurrent);
-        Assert.assertEquals(smCurrent, smOrig);
+        Assert.assertNotNull(mmCurrent);
+        Assert.assertEquals(mmCurrent, mmOrig);
         
         cleanupGL();
     }
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01aNEWT.java
similarity index 64%
copy from src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java
copy to src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01aNEWT.java
index 38612fa..c638058 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01aNEWT.java
@@ -29,7 +29,6 @@
 package com.jogamp.opengl.test.junit.newt;
 
 import java.io.IOException;
-import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLProfile;
 
@@ -39,12 +38,13 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 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.UITestCase;
 
@@ -56,7 +56,7 @@ import javax.media.nativewindow.util.Dimension;
  * 
  * @see TestScreenMode01NEWT#cleanupGL()
  */
-public class TestScreenMode01bNEWT extends UITestCase {
+public class TestScreenMode01aNEWT extends UITestCase {
     static GLProfile glp;
     static int width, height;
     
@@ -108,45 +108,64 @@ public class TestScreenMode01bNEWT extends UITestCase {
         Window window0 = createWindow(screen, caps, "win0", 0, 0, width, height);
         Assert.assertNotNull(window0);        
 
-        List<ScreenMode> screenModes = screen.getScreenModes();
-        if(screenModes.size()==1) {
+        List<MonitorMode> allMonitorModes = screen.getMonitorModes();
+        Assert.assertTrue(allMonitorModes.size()>0);
+        if(allMonitorModes.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 (all), 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);
+
+        MonitorDevice monitor = window0.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(window0);
+            return;
+        }
+        Assert.assertTrue(allMonitorModes.containsAll(monitorModes));
+                
+        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);
         
-        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());
+        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);
+
+        MonitorMode mm = monitorModes.get(0);
+        System.err.println("[0] set current: "+mm);
+        Assert.assertTrue(monitor.setCurrentMode(mm));
+        Assert.assertTrue(monitor.isModeChangedByUs());
+        Assert.assertEquals(mm, monitor.getCurrentMode());
+        Assert.assertNotSame(mmOrig, monitor.getCurrentMode());
+        Assert.assertEquals(mm, monitor.queryCurrentMode());
 
         Thread.sleep(waitTimeShort);
 
-        // check reset ..
+        // check manual reset ..
 
         Assert.assertEquals(true,display.isNativeValid());
         Assert.assertEquals(true,screen.isNativeValid());
@@ -154,7 +173,11 @@ public class TestScreenMode01bNEWT extends UITestCase {
         Assert.assertEquals(true,window0.isVisible());
 
         screen.addReference(); // keep it alive !
-        screen.setCurrentScreenMode(smOrig);
+        Assert.assertTrue(monitor.setCurrentMode(mmOrig));
+        Assert.assertFalse(monitor.isModeChangedByUs());
+        Assert.assertEquals(mmOrig, monitor.getCurrentMode());
+        Assert.assertNotSame(mm, monitor.getCurrentMode());
+        Assert.assertEquals(mmOrig, monitor.queryCurrentMode());
         
         destroyWindow(window0);
         Assert.assertEquals(false,window0.isVisible());
@@ -183,7 +206,7 @@ public class TestScreenMode01bNEWT extends UITestCase {
     }
 
     public static void main(String args[]) throws IOException {
-        String tstname = TestScreenMode01bNEWT.class.getName();
+        String tstname = TestScreenMode01aNEWT.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
index 38612fa..9108853 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01bNEWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -29,7 +29,6 @@
 package com.jogamp.opengl.test.junit.newt;
 
 import java.io.IOException;
-import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLProfile;
 
@@ -39,34 +38,36 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 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.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;
 
 /**
- * Documents remedy B) for NV RANDR/GL bug
- * 
- * @see TestScreenMode01NEWT#cleanupGL()
+ * Mode change on separate monitors ..
  */
 public class TestScreenMode01bNEWT extends UITestCase {
     static GLProfile glp;
     static int width, height;
     
-    static int waitTimeShort = 2000;
-    static int waitTimeLong = 2000;
+    static long waitTimeShort = 2000;
+    static long duration = 6000;
 
     @BeforeClass
     public static void initClass() {
-        width  = 100;
-        height = 100;
+        width  = 200;
+        height = 200;
         glp = GLProfile.getDefault();
     }
 
@@ -75,7 +76,7 @@ public class TestScreenMode01bNEWT extends UITestCase {
         Thread.sleep(waitTimeShort);
     }
     
-    static Window createWindow(Screen screen, GLCapabilities caps, String name, int x, int y, int width, int height) {
+    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);
@@ -85,7 +86,9 @@ public class TestScreenMode01bNEWT extends UITestCase {
         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;
     }
 
@@ -96,93 +99,150 @@ public class TestScreenMode01bNEWT extends UITestCase {
     }
     
     @Test
-    public void testScreenModeChange01() throws InterruptedException {
+    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();
+        }
+    }
+    
+    @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();
+        }
+    }
+        
+    void testScreenModeChangeImpl(final Screen screen, int xpos, int ypos) throws InterruptedException {
         Thread.sleep(waitTimeShort);
 
-        GLCapabilities caps = new GLCapabilities(glp);
+        final 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);
+        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());
 
-        List<ScreenMode> screenModes = screen.getScreenModes();
-        if(screenModes.size()==1) {
+        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 ScreenMode change support, sorry");
+            System.err.println("Your platform has no MonitorMode change support (all), 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 ..
+        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);
+
+        MonitorMode sm = (MonitorMode) monitorModes.get(0);
+        System.err.println("[1] set current: "+sm);
+        Assert.assertTrue(monitor.setCurrentMode(sm));
+        mmCurrent = monitor.getCurrentMode();
+        System.err.println("[1] current: "+mmCurrent);
+        Assert.assertTrue(monitor.isModeChangedByUs());
+        Assert.assertEquals(sm, monitor.getCurrentMode());
+        Assert.assertNotSame(mmOrig, monitor.getCurrentMode());
+        Assert.assertEquals(sm, monitor.queryCurrentMode());
+
+        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());
 
-        screen.addReference(); // keep it alive !
-        screen.setCurrentScreenMode(smOrig);
+        Assert.assertTrue(monitor.setCurrentMode(mmOrig));
+        Assert.assertFalse(monitor.isModeChangedByUs());
+        Assert.assertEquals(mmOrig, monitor.getCurrentMode());
+        Assert.assertNotSame(sm, monitor.getCurrentMode());
+        Assert.assertEquals(mmOrig, monitor.queryCurrentMode());
+        
+        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,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());                
+        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/TestScreenMode01cNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01cNEWT.java
new file mode 100644
index 0000000..30c06e9
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode01cNEWT.java
@@ -0,0 +1,249 @@
+/**
+ * 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.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.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.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 ..
+ */
+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() {
+        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) {
+        if(null!=window) {
+            window.destroy();
+        }
+    }
+    
+    @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();
+        }
+    }
+    
+    @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();
+        }
+    }
+        
+    @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();
+        }
+    }
+    
+    @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();
+        }
+    }
+    
+    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/TestScreenMode02NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java
index 1c9cb91..58bce4c 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestScreenMode02NEWT.java
@@ -39,14 +39,17 @@ 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.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;
@@ -102,48 +105,54 @@ public class TestScreenMode02NEWT 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) {
+        MonitorDevice monitor = window.getMainMonitor();
+        List<MonitorMode> monitorModes = monitor.getSupportedModes();
+        if(monitorModes.size()==1) {
             // no support ..
             System.err.println("Your platform has no ScreenMode change support, sorry");
             destroyWindow(window);
             return;
         }
-        Assert.assertTrue(screenModes.size()>0);
+        Assert.assertTrue(monitorModes.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) {
+        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, 90);
+        if(null==monitorModes || Platform.getOSType() == Platform.OSType.MACOS ) {
             // 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);
+        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);
+
+        MonitorMode sm = (MonitorMode) monitorModes.get(0);
         System.err.println("[0] set current: "+sm);
-        screen.setCurrentScreenMode(sm);
-        Assert.assertEquals(sm, screen.getCurrentScreenMode());
-        Assert.assertNotSame(smOrig, screen.getCurrentScreenMode());
+        monitor.setCurrentMode(sm);
+        Assert.assertTrue(monitor.isModeChangedByUs());
+        Assert.assertEquals(sm, monitor.getCurrentMode());
+        Assert.assertNotSame(mmOrig, monitor.getCurrentMode());
+        Assert.assertEquals(sm, monitor.queryCurrentMode());
 
         Thread.sleep(waitTimeLong);
 
@@ -159,6 +168,7 @@ public class TestScreenMode02NEWT 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());
 
@@ -167,11 +177,11 @@ public class TestScreenMode02NEWT extends UITestCase {
         Assert.assertEquals(true,display.isNativeValid());
         Assert.assertEquals(true,screen.isNativeValid());
 
-        smCurrent = screen.getCurrentScreenMode();
-        System.err.println("[1] current/orig: "+smCurrent);
+        mmCurrent = monitor.getCurrentMode();
+        System.err.println("[1] current/orig: "+mmCurrent);
 
-        Assert.assertNotNull(smCurrent);
-        Assert.assertEquals(smCurrent, smOrig);
+        Assert.assertNotNull(mmCurrent);
+        Assert.assertEquals(mmCurrent, mmOrig);
 
         screen.destroy();
 
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 d63f0d2..acaa279 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol01AWT.java
@@ -46,13 +46,14 @@ 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;
 
 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 +75,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 +90,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 +113,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 +137,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 +152,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 +163,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 1657fcb..8d32bee 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol02NEWT.java
@@ -52,7 +52,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 +69,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 +84,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 65068e9..45b4121 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindowClosingProtocol03NewtAWT.java
@@ -46,17 +46,19 @@ 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;
 
 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 +83,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/event/BaseNewtEventModifiers.java b/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java
new file mode 100644
index 0000000..a959a56
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/BaseNewtEventModifiers.java
@@ -0,0 +1,781 @@
+/**
+ * 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.Test ;
+
+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.
+ */
+
+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_NUMBER ) { 
+                _numButtonsToTest = com.jogamp.newt.event.MouseEvent.BUTTON_NUMBER ;
+            }
+
+            // 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 0000000..1504c94
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersAWTCanvas.java
@@ -0,0 +1,103 @@
+/**
+ * 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 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.
+ */
+
+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 0000000..71191c8
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNEWTWindowAWT.java
@@ -0,0 +1,84 @@
+/**
+ * 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 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.
+ */
+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 0000000..e0bc847
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasAWT.java
@@ -0,0 +1,118 @@
+/**
+ * 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 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.
+ */
+
+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 0000000..349d200
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtEventModifiersNewtCanvasSWTAWT.java
@@ -0,0 +1,180 @@
+/**
+ * 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 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.
+ */
+
+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/TestNewtKeyCodeModifiersAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java
similarity index 59%
rename from src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodeModifiersAWT.java
rename to src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java
index b067883..0f79d9b 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodeModifiersAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodeModifiersAWT.java
@@ -26,7 +26,7 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.newt;
+package com.jogamp.opengl.test.junit.newt.event;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -47,6 +47,8 @@ import javax.swing.JFrame;
 
 import java.io.IOException;
 
+import jogamp.nativewindow.jawt.JAWTUtil;
+
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -61,6 +63,11 @@ 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>
  */
 public class TestNewtKeyCodeModifiersAWT extends UITestCase {
     static int width, height;
@@ -88,7 +95,7 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase {
     public void releaseTest() {        
     }
     
-    @Test
+    @Test(timeout=180000) // TO 3 min
     public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
         GLWindow glWindow = GLWindow.create(glCaps);
         glWindow.setSize(width, height);
@@ -99,12 +106,14 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase {
         glWindow.destroy();
     }
         
-    @Test
-    public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException {
+    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());
@@ -129,83 +138,103 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase {
             throwable.printStackTrace();
             Assume.assumeNoException( throwable );
         }        
-        glWindow.destroy();
+        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, int modifierKey, int modifierMask) {
+    static void testKeyCodeModifier(Robot robot, NEWTKeyAdapter keyAdapter, short modifierKey, int modifierMask, short keyCode, 
+                                    char keyCharOnly, char keyCharMod) {        
         keyAdapter.reset();
-        AWTRobotUtil.keyPress(0, robot, true, KeyEvent.VK_P, 10);   // press P
-        AWTRobotUtil.keyPress(0, robot, false, KeyEvent.VK_P, 100); // release+typed P
-        robot.waitForIdle();        
-        for(int j=0; j < 10 && keyAdapter.getQueueSize() < 3; j++) { // wait until events are collected
+        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.keyPress(0, robot, true, modifierKey, 10);     // press MOD
-        AWTRobotUtil.keyPress(0, robot, true, KeyEvent.VK_P, 10);   // press P
-        AWTRobotUtil.keyPress(0, robot, false, KeyEvent.VK_P, 10);  // release+typed P 
-        AWTRobotUtil.keyPress(0, robot, false, modifierKey, 100);   // release+typed MOD
-        robot.waitForIdle();        
-        for(int j=0; j < 10 && keyAdapter.getQueueSize() < 3+6; j++) { // wait until events are collected
+        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+6, 0);        
+        NEWTKeyUtil.validateKeyAdapterStats(keyAdapter,
+                                            3 /* press-SI */, 3 /* release-SI */, 
+                                            0 /* press-AR */, 0 /* release-AR */ );
         
-        final List<EventObject> queue = keyAdapter.getQueued();        
+        final List<EventObject> queue = keyAdapter.getQueued();
         int i=0;
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, 0, KeyEvent.VK_P);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, 0, KeyEvent.VK_P);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, 0, KeyEvent.VK_P);
+        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);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED, modifierMask, KeyEvent.VK_P);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, modifierMask, KeyEvent.VK_P);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, modifierMask, KeyEvent.VK_P);                
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, modifierMask, modifierKey);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED, modifierMask, modifierKey);                
+        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 int m1k = KeyEvent.VK_ALT;
-        final int m1m = InputEvent.ALT_MASK;
-        final int m2k = KeyEvent.VK_CONTROL;
-        final int m2m = InputEvent.CTRL_MASK;
-        final int m3k = KeyEvent.VK_SHIFT;
-        final int m3m = InputEvent.SHIFT_MASK;
+        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.keyPress(0, robot, true, m1k, 10);     // press MOD1
-        AWTRobotUtil.keyPress(0, robot, true, m2k, 10);     // press MOD2
-        AWTRobotUtil.keyPress(0, robot, true, m3k, 10);     // press MOD3
-        AWTRobotUtil.keyPress(0, robot, true, KeyEvent.VK_P, 10);   // press P
+        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.keyPress(0, robot, false, KeyEvent.VK_P, 100);  // release+typed P        
-        AWTRobotUtil.keyPress(0, robot, false, m3k, 10);   // release+typed MOD
-        AWTRobotUtil.keyPress(0, robot, false, m2k, 10);   // release+typed MOD
-        AWTRobotUtil.keyPress(0, robot, false, m1k, 10);   // release+typed MOD
+        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);
         
-        robot.waitForIdle();        
-        for(int j=0; j < 10 && keyAdapter.getQueueSize() < 3*4; j++) { // wait until events are collected
+        for(int j=0; j < 100 && keyAdapter.getQueueSize() < 4+4; j++) { // wait until events are collected
             robot.delay(100);
         }
-        NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, 3*4, 0);        
+        NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, 
+                                            4 /* press-SI */, 4 /* release-SI */, 
+                                            0 /* press-AR */, 0 /* release-AR */ );
         
         final List<EventObject> queue = keyAdapter.getQueued();        
         int i=0;
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED,  m1m,         m1k);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED,  m1m|m2m,     m2k);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED,  m1m|m2m|m3m, m3k);
-        
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_PRESSED,  m1m|m2m|m3m, KeyEvent.VK_P);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m|m3m, KeyEvent.VK_P);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED,    m1m|m2m|m3m, KeyEvent.VK_P);
+        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_RELEASED, m1m|m2m|m3m, m3k);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED,    m1m|m2m|m3m, m3k);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m|m2m,     m2k);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED,    m1m|m2m,     m2k);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_RELEASED, m1m,         m1k);
-        NEWTKeyUtil.validateKeyEvent((KeyEvent) queue.get(i++), KeyEvent.EVENT_KEY_TYPED,    m1m,         m1k);                
+        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 {
@@ -213,7 +242,6 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase {
         robot.setAutoWaitForIdle(true);
 
         GLEventListener demo1 = new RedSquareES2();
-        TestListenerCom01AWT.setDemoFields(demo1, glWindow, false);
         glWindow.addGLEventListener(demo1);
 
         // NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
@@ -234,9 +262,11 @@ public class TestNewtKeyCodeModifiersAWT extends UITestCase {
         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);
-        testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_CONTROL, InputEvent.CTRL_MASK);
-        testKeyCodeModifier(robot, glWindow1KA, KeyEvent.VK_ALT, InputEvent.ALT_MASK);
+        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);
         
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodesAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java
similarity index 62%
rename from src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodesAWT.java
rename to src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java
index e786eaf..333a21b 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyCodesAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyCodesAWT.java
@@ -26,7 +26,7 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.newt;
+package com.jogamp.opengl.test.junit.newt.event;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -48,10 +48,13 @@ import javax.swing.JFrame;
 
 import java.io.IOException;
 
+import jogamp.nativewindow.jawt.JAWTUtil;
+
 import org.junit.BeforeClass;
 import org.junit.Test;
 
 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;
@@ -88,7 +91,7 @@ public class TestNewtKeyCodesAWT extends UITestCase {
     public void releaseTest() {        
     }
     
-    @Test
+    @Test(timeout=180000) // TO 3 min
     public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
         GLWindow glWindow = GLWindow.create(glCaps);
         glWindow.setSize(width, height);
@@ -99,19 +102,21 @@ public class TestNewtKeyCodesAWT extends UITestCase {
         glWindow.destroy();
     }
         
-    @Test
-    public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException {
+    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.setSize(width, height);
                 frame1.setVisible(true);
             } } );
         
@@ -131,33 +136,54 @@ public class TestNewtKeyCodesAWT extends UITestCase {
         }        
         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(0x008, 0x008, "bs"),
-      // new CodeSeg(0x009, 0x009, "tab"), // TAB functions as focus traversal key
-      new CodeSeg(0x00a, 0x00a, "cr"),
-      new CodeSeg(0x010, 0x012, "shift, ctrl, alt"),
-      new CodeSeg(0x01B, 0x01B, "esc"),
-      new CodeSeg(0x020, 0x024, "space, up, down, end, home"),
-      new CodeSeg(0x025, 0x028, "cursor"),
-      new CodeSeg(0x02C, 0x02F, ", - . /"),
-      new CodeSeg(0x030, 0x039, "0 - 9"),
-      new CodeSeg(0x03B, 0x03B, ";"),
-      new CodeSeg(0x03D, 0x03D, "="),
-      new CodeSeg(0x041, 0x05A, "a - z"),
-      new CodeSeg(0x05B, 0x05D, "[ \\ ]"),
-      // new CodeSeg(0x060, 0x06B, "numpad1"), // can be mapped to normal keycodes
-      // new CodeSeg(0x06D, 0x06F, "numpad2"), // can be mapped to normal keycodes
-      new CodeSeg(0x07F, 0x07F, "del"),
-      // new CodeSeg(0x090, 0x091, "num lock, scroll lock"),
-      // new CodeSeg(0x070, 0x07B, "F1 - F12"),
-      // new CodeSeg(0x09A, 0x09D, "prt ins hlp meta"),
-      new CodeSeg(0x0C0, 0x0C0, "back quote"),
-      new CodeSeg(0x0DE, 0x0DE, "quote"),
-      // new CodeSeg(0x0E0, 0x0E3, "cursor kp"),
-      // new CodeSeg(0x080, 0x08F, "dead-1"),
-      // new CodeSeg(0x096, 0x0A2, "& ^ \" < > { }"), 
-      // new CodeSeg(0x200, 0x20D, "extra-2"), // @ ; ..
+      // 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, NEWTKeyAdapter keyAdapter) {
@@ -167,14 +193,27 @@ public class TestNewtKeyCodesAWT extends UITestCase {
             keyAdapter.reset();
             final CodeSeg codeSeg = codeSegments[i];
             // System.err.println("*** Segment "+codeSeg.description);
-            for(int c=codeSeg.min; c<=codeSeg.max; c++) {
+            int eventCount = 0;
+            for(short c=codeSeg.min; c<=codeSeg.max; c++) {                
+                AWTRobotUtil.waitForIdle(robot);
                 // System.err.println("*** KeyCode 0x"+Integer.toHexString(c));
-                AWTRobotUtil.keyPress(0, robot, true, c, 10);
-                AWTRobotUtil.keyPress(0, robot, false, c, 100);
-                robot.waitForIdle();
+                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++;
             }
-            final int codeCount = codeSeg.max - codeSeg.min + 1;
-            for(int j=0; j < 10 && keyAdapter.getQueueSize() < 3 * codeCount; j++) { // wait until events are collected
+            AWTRobotUtil.waitForIdle(robot);
+            for(int j=0; j < 20 && keyAdapter.getQueueSize() < eventCount; j++) { // wait until events are collected
                 robot.delay(100);
             }
             final ArrayList<EventObject> events = new ArrayList<EventObject>(keyAdapter.getQueued());
@@ -188,7 +227,6 @@ public class TestNewtKeyCodesAWT extends UITestCase {
         robot.setAutoWaitForIdle(true);
 
         GLEventListener demo1 = new RedSquareES2();
-        TestListenerCom01AWT.setDemoFields(demo1, glWindow, false);
         glWindow.addGLEventListener(demo1);
 
         // NEWTFocusAdapter glWindow1FA = new NEWTFocusAdapter("GLWindow1");
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventAutoRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java
similarity index 84%
rename from src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventAutoRepeatAWT.java
rename to src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java
index 7b6fe05..8b8a5ac 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventAutoRepeatAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventAutoRepeatAWT.java
@@ -26,7 +26,7 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.newt;
+package com.jogamp.opengl.test.junit.newt.event;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -68,20 +68,19 @@ import com.jogamp.opengl.test.junit.util.*;
  * <ol>
  *   <li>{@link #EVENT_KEY_PRESSED}</li>
  *   <li>{@link #EVENT_KEY_RELEASED}</li>
- *   <li>{@link #EVENT_KEY_TYPED}</li>
  * </ol>
  * </p>
  * <p>
  * Auto-Repeat shall behave as follow:
  * <pre>
-    D = pressed, U = released, T = typed
+    D = pressed, U = released
     0 = normal, 1 = auto-repeat
 
-    D(0), [ U(1), T(1), D(1), U(1) T(1) ..], U(0) T(0)
+    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/T triple.
+ * you just get one long pressed key D/U tuple.
  */
 public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
     static int width, height;
@@ -109,7 +108,7 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
     public void releaseTest() {        
     }
     
-    @Test
+    @Test(timeout=180000) // TO 3 min
     public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
         GLWindow glWindow = GLWindow.create(glCaps);
         glWindow.setSize(width, height);
@@ -120,7 +119,7 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
         glWindow.destroy();
     }
         
-    @Test
+    @Test(timeout=180000) // TO 3 min
     public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException {
         GLWindow glWindow = GLWindow.create(glCaps);
         
@@ -155,19 +154,19 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
     
     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][3];
-        EventObject[][] last = new EventObject[loops][3];
+        EventObject[][] first = new EventObject[loops][2];
+        EventObject[][] last = new EventObject[loops][2];
         
         keyAdapter.reset();
         int firstIdx = 0;
         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);
-            robot.waitForIdle();
             AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_A, 500); // 1s .. no AR anymore
-            robot.waitForIdle();            
-            final int minCodeCount = firstIdx + 3;
-            final int desiredCodeCount = firstIdx + 6;
+            AWTRobotUtil.waitForIdle(robot);
+            final int minCodeCount = firstIdx + 2;
+            final int desiredCodeCount = firstIdx + 4;
             for(int j=0; j < 10 && keyAdapter.getQueueSize() < desiredCodeCount; j++) { // wait until events are collected
                 robot.delay(100);
             }
@@ -176,20 +175,18 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
             final List<EventObject> keyEvents = keyAdapter.getQueued();
             first[i][0] = (KeyEvent) keyEvents.get(firstIdx+0);
             first[i][1] = (KeyEvent) keyEvents.get(firstIdx+1);
-            first[i][2] = (KeyEvent) keyEvents.get(firstIdx+2);
-            firstIdx = keyEvents.size() - 3;
+            firstIdx = keyEvents.size() - 2;
             last[i][0] = (KeyEvent) keyEvents.get(firstIdx+0);
             last[i][1] = (KeyEvent) keyEvents.get(firstIdx+1);
-            last[i][2] = (KeyEvent) keyEvents.get(firstIdx+2);
             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);
-            robot.waitForIdle();
             AWTRobotUtil.keyPress(0, robot, false, java.awt.event.KeyEvent.VK_B, 250);
-            robot.waitForIdle();
-            for(int j=0; j < 10 && keyAdapter.getQueueSize() < firstIdx+3; j++) { // wait until events are collected
+            AWTRobotUtil.waitForIdle(robot);
+            for(int j=0; j < 20 && keyAdapter.getQueueSize() < firstIdx+3; j++) { // wait until events are collected
                 robot.delay(100);
             }
             firstIdx = keyEvents.size();
@@ -201,9 +198,19 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
         final boolean hasAR = 0 < keyAdapter.getKeyPressedCount(true) ;
         
         {
-            final int expTotal = keyEvents.size();
-            final int expAR = hasAR ? expTotal - 3 * 2 * loops : 0; // per loop: 3 for non AR events and 3 for non AR 'B'
-            NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, expTotal, expAR);
+            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 ) {
@@ -216,7 +223,7 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
             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() );
@@ -228,24 +235,14 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
             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) first[i][2];
-            Assert.assertTrue("3rd Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() );
-            Assert.assertTrue("3rd Shall be TYPED, but is "+e, KeyEvent.EVENT_KEY_TYPED == e.getEventType() );
-            Assert.assertTrue("3rd Shall be AR, but is "+e, 0 != ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) );
-            
             e = (KeyEvent) last[i][0];
-            Assert.assertTrue("last-2 Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() );
-            Assert.assertTrue("last-2 Shall be PRESSED, but is "+e, KeyEvent.EVENT_KEY_PRESSED == e.getEventType() );
-            Assert.assertTrue("last-2 Shall be AR, but is "+e, 0 != ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) );
-            
-            e = (KeyEvent) last[i][1];
             Assert.assertTrue("last-1 Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() );
-            Assert.assertTrue("last-1 Shall be RELEASED, but is "+e, KeyEvent.EVENT_KEY_RELEASED == e.getEventType() );
-            Assert.assertTrue("last-1 Shall not be AR, but is "+e, 0 == ( InputEvent.AUTOREPEAT_MASK & e.getModifiers() ) );
+            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][2];
+            e = (KeyEvent) last[i][1];
             Assert.assertTrue("last-0 Shall be A, but is "+e, KeyEvent.VK_A == e.getKeyCode() );
-            Assert.assertTrue("last-0 Shall be TYPED, but is "+e, KeyEvent.EVENT_KEY_TYPED == e.getEventType() );
+            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() ) );
         }
     }
@@ -255,7 +252,6 @@ public class TestNewtKeyEventAutoRepeatAWT extends UITestCase {
         robot.setAutoWaitForIdle(true);
 
         GLEventListener demo1 = new RedSquareES2();
-        TestListenerCom01AWT.setDemoFields(demo1, glWindow, false);
         glWindow.addGLEventListener(demo1);
 
         NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventOrderAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java
similarity index 83%
rename from src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventOrderAWT.java
rename to src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java
index cf50161..d0c3813 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyEventOrderAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyEventOrderAWT.java
@@ -26,7 +26,7 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.newt;
+package com.jogamp.opengl.test.junit.newt.event;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -45,6 +45,8 @@ import javax.swing.JFrame;
 
 import java.io.IOException;
 
+import jogamp.nativewindow.jawt.JAWTUtil;
+
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -63,7 +65,6 @@ import com.jogamp.opengl.test.junit.util.*;
  * <ol>
  *   <li>{@link #EVENT_KEY_PRESSED}</li>
  *   <li>{@link #EVENT_KEY_RELEASED}</li>
- *   <li>{@link #EVENT_KEY_TYPED}</li>
  * </ol>
  * </p>
  */
@@ -93,7 +94,7 @@ public class TestNewtKeyEventOrderAWT extends UITestCase {
     public void releaseTest() {        
     }
     
-    @Test
+    @Test(timeout=180000) // TO 3 min
     public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
         GLWindow glWindow = GLWindow.create(glCaps);
         glWindow.setSize(width, height);
@@ -104,12 +105,14 @@ public class TestNewtKeyEventOrderAWT extends UITestCase {
         glWindow.destroy();
     }
         
-    @Test
-    public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException {
+    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());
@@ -137,37 +140,60 @@ public class TestNewtKeyEventOrderAWT extends UITestCase {
         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);
-            robot.waitForIdle();
             // 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);
-            robot.waitForIdle();
             // 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);
-            robot.waitForIdle();
             // 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);
-            robot.waitForIdle();            
         }
+        AWTRobotUtil.waitForIdle(robot);
         robot.delay(250);
         // dumpKeyEvents(keyAdapter.getQueued());
         
         NEWTKeyUtil.validateKeyEventOrder(keyAdapter.getQueued());
         
-        NEWTKeyUtil.validateKeyAdapterStats(keyAdapter, 6*3*loops, 0);        
+        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 {
@@ -175,7 +201,6 @@ public class TestNewtKeyEventOrderAWT extends UITestCase {
         robot.setAutoWaitForIdle(true);
 
         GLEventListener demo1 = new RedSquareES2();
-        TestListenerCom01AWT.setDemoFields(demo1, glWindow, false);
         glWindow.addGLEventListener(demo1);
 
         NEWTKeyAdapter glWindow1KA = new NEWTKeyAdapter("GLWindow1");
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyPressReleaseUnmaskRepeatAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java
similarity index 86%
rename from src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyPressReleaseUnmaskRepeatAWT.java
rename to src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java
index c275139..e0d2ae2 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/TestNewtKeyPressReleaseUnmaskRepeatAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/event/TestNewtKeyPressReleaseUnmaskRepeatAWT.java
@@ -26,7 +26,7 @@
  * or implied, of JogAmp Community.
  */
  
-package com.jogamp.opengl.test.junit.newt;
+package com.jogamp.opengl.test.junit.newt.event;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -45,6 +45,8 @@ import javax.swing.JFrame;
 
 import java.io.IOException;
 
+import jogamp.nativewindow.jawt.JAWTUtil;
+
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -87,7 +89,7 @@ public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase {
     public void releaseTest() {        
     }
     
-    @Test
+    @Test(timeout=180000) // TO 3 min
     public void test01NEWT() throws AWTException, InterruptedException, InvocationTargetException {
         GLWindow glWindow = GLWindow.create(glCaps);
         glWindow.setSize(width, height);
@@ -98,12 +100,14 @@ public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase {
         glWindow.destroy();
     }
         
-    @Test
-    public void test02NewtCanvasAWT() throws AWTException, InterruptedException, InvocationTargetException {
+    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());
@@ -131,12 +135,29 @@ public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase {
         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();
-        TestListenerCom01AWT.setDemoFields(demo1, glWindow, false);
         glWindow.addGLEventListener(demo1);
 
         SimpleKeyPressRelease simpleKeyPressRelease = new SimpleKeyPressRelease();
@@ -194,11 +215,6 @@ public class TestNewtKeyPressReleaseUnmaskRepeatAWT extends UITestCase {
                 System.err.println(seq+": "+e);
             }
         }
-
-        @Override
-        public void keyTyped(KeyEvent e) {
-        }
-        
     }
 
     public static void main(String args[]) throws IOException {
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 3313ec6..0ae94d7 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 15393e8..9d08d8f 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
@@ -47,7 +47,10 @@ public class NewtAWTReparentingKeyAdapter extends KeyAdapter {
         this.glWindow = glWindow;
     }
     
-    public void keyTyped(KeyEvent e) {
+    public void keyReleased(KeyEvent e) {
+        if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+            return;
+        }            
         if(e.getKeyChar()=='i') {
             System.err.println(glWindow);
         } else if(e.getKeyChar()=='d') {
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 6b7b155..15c324e 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
@@ -382,6 +382,7 @@ public class TestParenting01NEWT extends UITestCase {
                     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());
 
@@ -406,6 +407,7 @@ public class TestParenting01NEWT extends UITestCase {
                     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());
 
@@ -566,8 +568,10 @@ public class TestParenting01NEWT extends UITestCase {
                     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());
@@ -579,8 +583,10 @@ public class TestParenting01NEWT extends UITestCase {
                     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());
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 de29db4..f8f9751 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
@@ -98,11 +98,11 @@ 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);
            }
         });
@@ -132,18 +132,24 @@ public class TestParenting01aAWT 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());
@@ -168,11 +174,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);
            }
         });
@@ -212,11 +218,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);
            }
         });
@@ -256,10 +262,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);
            }
         });
@@ -320,11 +326,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);
            }
         });
@@ -386,10 +392,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 +406,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);
            }
         });
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 d98a540..906aeee 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
@@ -89,10 +89,10 @@ public class TestParenting01bAWT 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);               
            }
         });
@@ -103,10 +103,10 @@ 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.setSize(width, height);
+               frame2.setLocation(640, 480);
                frame2.setVisible(true);               
            }
         });
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 dfd0787..baa4c46 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
@@ -98,11 +98,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,19 +126,25 @@ 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());
@@ -160,10 +166,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 +180,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 4b02be8..1dd80e3 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
@@ -165,10 +165,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.err.println("Demos: 1 - Visible");
         SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
+               jFrame1.setSize(width, height);
+               jFrame1.validate();
                jFrame1.setVisible(true);
            }
         });
@@ -199,6 +200,8 @@ public class TestParenting01cSwingAWT extends UITestCase {
                 } });
         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.
@@ -208,14 +211,18 @@ public class TestParenting01cSwingAWT extends UITestCase {
                     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();
@@ -292,10 +299,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);
            }
         });
@@ -311,10 +318,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);
            }
         });
@@ -322,6 +329,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);
@@ -385,7 +394,9 @@ public class TestParenting01cSwingAWT extends UITestCase {
                     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();
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 da689ce..204d98d 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
@@ -118,11 +118,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 +148,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 +165,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!");
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 b33a40f..4f88034 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
@@ -133,11 +133,11 @@ 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.setLocation(0, 0);
+                frame1.setSize(fSize);
                 frame1.validate();                
                 frame1.setVisible(true);
             }});
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
index 09b6d04..0af42ec 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting04AWT.java
@@ -100,10 +100,10 @@ public class TestParenting04AWT 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);
                frame1.validate();
            }
@@ -123,10 +123,10 @@ public class TestParenting04AWT 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(width+50, 0);
         SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
+               frame2.setSize(width, height);
+               frame2.setLocation(width+50, 0);
                frame2.setVisible(true);
                frame2.validate();
            }
@@ -159,6 +159,8 @@ public class TestParenting04AWT extends UITestCase {
                            }
                            canvas1.setNEWTChild(glWindow2); // put g2 -> w1. free g1 of w1
                            canvas2.setNEWTChild(glWindow1); // put g1 -> w2
+                           frame1.invalidate();
+                           frame2.invalidate();
                            frame1.validate();
                            frame2.validate();
                        }
@@ -176,6 +178,8 @@ public class TestParenting04AWT extends UITestCase {
                            }
                            canvas1.setNEWTChild(glWindow1);
                            canvas2.setNEWTChild(glWindow2);
+                           frame1.invalidate();
+                           frame2.invalidate();
                            frame1.validate();
                            frame2.validate();
                        }
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java
index d6f1f81..d340fc2 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingFocusTraversal01AWT.java
@@ -146,7 +146,10 @@ public class TestParentingFocusTraversal01AWT extends UITestCase {
         glWindow1.addGLEventListener(demo1);
         glWindow1.addKeyListener(new NewtAWTReparentingKeyAdapter(frame1, newtCanvasAWT1, glWindow1));
         glWindow1.addKeyListener(new KeyAdapter() {
-            public void keyTyped(KeyEvent e) {
+            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) {
@@ -183,14 +186,15 @@ 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.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));
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 0000000..1d186a4
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestTranslucentChildWindowBug632NEWT.java
@@ -0,0 +1,132 @@
+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 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;
+
+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 373c83f..2d668c2 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
@@ -137,10 +137,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);
             }});
@@ -157,7 +157,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();
     }
 
@@ -174,20 +177,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/AWTKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java
index 837ba5d..776c3c7 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTKeyAdapter.java
@@ -36,7 +36,7 @@ import java.util.List;
 public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEventCountAdapter {
 
     String prefix;
-    int keyPressed, keyReleased, keyTyped;
+    int keyPressed, keyReleased;
     boolean pressed;
     List<EventObject> queue = new ArrayList<EventObject>();
     boolean verbose = true;
@@ -53,7 +53,7 @@ public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEvent
     }
     
     public synchronized int getCount() {
-        return keyTyped;
+        return keyReleased;
     }
 
     public synchronized int getKeyPressedCount(boolean autoRepeatOnly) {
@@ -64,10 +64,6 @@ public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEvent
         return keyReleased; 
     }
     
-    public synchronized int getKeyTypedCount(boolean autoRepeatOnly) {
-        return keyTyped; 
-    }
-    
     public synchronized List<EventObject> getQueued() {
         return queue;
     }
@@ -77,7 +73,6 @@ public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEvent
     }
     
     public synchronized void reset() {
-        keyTyped = 0;
         keyPressed = 0;
         keyReleased = 0;
         pressed = false;
@@ -102,14 +97,6 @@ public class AWTKeyAdapter extends java.awt.event.KeyAdapter implements KeyEvent
         }
     }
 
-    public synchronized void keyTyped(java.awt.event.KeyEvent e) {
-        keyTyped++;
-        queue.add(e);
-        if( verbose ) {
-            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+"]"; }
 }
 
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 e64b320..a760bbb 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/AWTRobotUtil.java
@@ -29,21 +29,24 @@
 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.nativewindow.NativeWindowFactory;
 import javax.media.opengl.GLDrawable;
 import javax.media.opengl.awt.GLCanvas;
 
 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;
@@ -55,6 +58,58 @@ public class AWTRobotUtil {
     public static final int TIME_SLICE   = TIME_OUT / POLL_DIVIDER ;
     public static Integer AWT_CLICK_TO = null; 
     
+    static Object awtEDTAliveSync = new Object();
+    static volatile boolean awtEDTAliveFlag = false;    
+    
+    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(new Runnable() {
+                @Override
+                public void run() {
+                    awtEDTAliveFlag = true;
+                }                            
+            });
+            for (int wait=0; wait<POLL_DIVIDER && !awtEDTAliveFlag; wait++) {
+                try {
+                    Thread.sleep(TIME_SLICE);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+            return awtEDTAliveFlag;
+        }
+    }
+    /** 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();
@@ -63,52 +118,71 @@ 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) 
+    public static int[] getCenterLocation(Object obj, boolean onTitleBarIfWindow) 
         throws InterruptedException, InvocationTargetException {
-        Component comp = null;
-        com.jogamp.newt.Window win = null;
-
         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 ) ;
         }
-
-        return new java.awt.Point(x0, y0);
+        x0 = (int) ( p0.getX() + r0.getWidth() / 2.0 + .5 ) ;
+        return new int[] { 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() }; 
+    }
+    
     /**
      * toFront, call setVisible(true) and toFront(),
      * after positioning the mouse in the middle of the window via robot.
@@ -127,9 +201,9 @@ public class AWTRobotUtil {
             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() );
+        int[] p0 = getCenterLocation(window, false);
+        System.err.println("toFront: robot pos: "+p0[0]+"x"+p0[1]);
+        robot.mouseMove( p0[0], p0[1] );
         robot.delay(ROBOT_DELAY);
 
         int wait=0;
@@ -170,20 +244,34 @@ 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);
 
-        robot.mouseMove( (int) p0.getX(), (int) p0.getY() );
+        robot.mouseMove( p0[0], p0[1] );
         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);
+
+        robot.mouseMove( p0[0], p0[1] );
+        robot.delay(ROBOT_DELAY);
+    }
+    
     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");
+                    (Integer) java.awt.Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
                 if(null == AWT_CLICK_TO) { 
                     AWT_CLICK_TO = new Integer(500);
                 }
@@ -209,51 +297,65 @@ public class AWTRobotUtil {
      */
     public static void requestFocus(Robot robot, Object obj, boolean onTitleBarIfWindow) 
         throws AWTException, InterruptedException, InvocationTargetException {
-    
-        final Component comp;
-        final com.jogamp.newt.Window win;
-
-        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 {
+        if(null != robot) {
             final int mouseButton = java.awt.event.InputEvent.BUTTON1_MASK;    
             centerMouse(robot, obj, onTitleBarIfWindow);
     
-            robot.waitForIdle();
+            waitForIdle(robot);
             robot.mousePress(mouseButton);
             robot.mouseRelease(mouseButton);
             final int d = getClickTimeout(obj) + 1;
             robot.delay( d );                
-            System.err.println("requestFocus: click, d: "+d+" ms");
+            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);
         }
@@ -265,17 +367,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);
         }
@@ -330,15 +432,15 @@ public class AWTRobotUtil {
             } 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);
@@ -347,9 +449,18 @@ public class AWTRobotUtil {
         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, KeyEventCountAdapter counter) throws InterruptedException, AWTException, InvocationTargetException 
-    {
+    {        
         int tc = 0;
         int j;
         final long t0 = System.currentTimeMillis();
@@ -358,24 +469,25 @@ public class AWTRobotUtil {
         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);
             }
-            if(DEBUG) { System.err.println(i+":"+j+" KC1.1: "+counter); }
-            robot.waitForIdle();
-            robot.keyPress(keyCode);
-            robot.delay(10);
-            robot.keyRelease(keyCode);
-            robot.delay(100);
-            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 ) ;
     }
 
@@ -383,11 +495,23 @@ public class AWTRobotUtil {
     public static int keyPress(int i, Robot robot, boolean press, int keyCode, int msDelay) {
         final long t0 = System.currentTimeMillis();        
         if(press) {
-            robot.keyPress(keyCode);
+            awtRobotKeyPress(robot, keyCode, msDelay);
         } else {
-            robot.keyRelease(keyCode);
+            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);
         }
-        robot.delay(msDelay);
         
         return (int) ( System.currentTimeMillis() - t0 ) ;
     }
@@ -469,9 +593,9 @@ public class AWTRobotUtil {
                 if(DEBUG) { System.err.println(i+":"+j+" MC1.0: "+counter+" - regain focus"); }
                 requestFocus(null, obj);
             }
-            final int c0 = null != counter ? counter.getCount() : 0;
+            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); }
@@ -528,16 +652,16 @@ public class AWTRobotUtil {
      */
     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.isVisible(); wait++) {
+                Thread.sleep(TIME_SLICE);
+            }
         } else {
             throw new RuntimeException("Neither AWT nor NEWT: "+obj);
         }
@@ -562,8 +686,18 @@ public class AWTRobotUtil {
      */
     public static boolean waitForRealized(Object obj, boolean realized) throws InterruptedException {
         int wait;
-        if (obj instanceof Component) {
-            Component comp = (Component) obj;
+        if(obj instanceof com.jogamp.newt.Screen) {
+            com.jogamp.newt.Screen screen = (com.jogamp.newt.Screen) obj;
+            for (wait=0; wait<POLL_DIVIDER && realized != screen.isNativeValid(); wait++) {
+                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);
+            }
+        } else if (NativeWindowFactory.isAWTAvailable() && obj instanceof java.awt.Component) {
+            java.awt.Component comp = (java.awt.Component) obj;
             for (wait=0; wait<POLL_DIVIDER && realized != comp.isDisplayable(); wait++) {
                 Thread.sleep(TIME_SLICE);
             }
@@ -586,11 +720,6 @@ public class AWTRobotUtil {
                     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);
-            }
         } else {
             throw new RuntimeException("Neither AWT nor NEWT: "+obj);
         }
@@ -603,16 +732,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));
                 } });
@@ -632,12 +764,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;
@@ -651,53 +786,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/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java b/src/test/com/jogamp/opengl/test/junit/util/GLEventListenerCounter.java
similarity index 64%
copy from src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
copy to src/test/com/jogamp/opengl/test/junit/util/GLEventListenerCounter.java
index f77f113..b121a4c 100644
--- a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/GLEventListenerCounter.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -25,33 +25,41 @@
  * authors and should not be interpreted as representing official policies, either expressed
  * or implied, of JogAmp Community.
  */
- 
-package jogamp.opengl;
+package com.jogamp.opengl.test.junit.util;
 
-import java.util.List;
-import java.util.ArrayList;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
 
-public abstract class DesktopGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
-    private static List<String> glueLibNames;
-    static {
-        glueLibNames = new ArrayList<String>();
-
-        glueLibNames.add("jogl_desktop");
+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;            
     }
-
-    public DesktopGLDynamicLibraryBundleInfo() {
-        super();
+    
+    @Override
+    public void init(GLAutoDrawable drawable) {
+        initCount++;
     }
 
     @Override
-    public final List<String> getGlueLibNames() {
-        return glueLibNames;
+    public void dispose(GLAutoDrawable drawable) {
+        disposeCount++;            
     }
-    
+
     @Override
-    public boolean useToolGetProcAdressFirst(String funcName) {
-        return true;
+    public void display(GLAutoDrawable drawable) {
+        displayCount++;
     }
-    
-}
 
+    @Override
+    public void reshape(GLAutoDrawable d, int x, int y, int width, int height) {
+        reshapeCount++;
+    }        
+}
\ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java
index 832f5ae..1d6d97a 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/KeyEventCountAdapter.java
@@ -31,8 +31,6 @@ package com.jogamp.opengl.test.junit.util;
 public interface KeyEventCountAdapter extends  InputEventCountAdapter {
     public int getKeyPressedCount(boolean autoRepeatOnly);
     
-    public int getKeyReleasedCount(boolean autoRepeatOnly);
-    
-    public int getKeyTypedCount(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 c230f0a..d6e9743 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java
@@ -33,6 +33,15 @@ import java.lang.reflect.*;
 import java.nio.FloatBuffer;
 
 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);
@@ -51,6 +60,31 @@ 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( (int)hex & 0x000000FF );
+    }
+    
+    public static String toHexString(short hex) {
+        return "0x" + Integer.toHexString( (int)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;
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 f19169b..d143b3c 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyAdapter.java
@@ -39,8 +39,8 @@ import com.jogamp.newt.event.KeyEvent;
 public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
 
     String prefix;
-    int keyPressed, keyReleased, keyTyped;
-    int keyPressedAR, keyReleasedAR, keyTypedAR;
+    int keyPressed, keyReleased;
+    int keyPressedAR, keyReleasedAR;
     boolean pressed;
     List<EventObject> queue = new ArrayList<EventObject>();
     boolean verbose = true;
@@ -57,7 +57,7 @@ public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
     }
     
     public synchronized int getCount() {
-        return keyTyped;
+        return keyReleased;
     }
 
     public synchronized int getKeyPressedCount(boolean autoRepeatOnly) {
@@ -68,10 +68,6 @@ public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
         return autoRepeatOnly ? keyReleasedAR: keyReleased; 
     }
     
-    public synchronized int getKeyTypedCount(boolean autoRepeatOnly) {
-        return autoRepeatOnly ? keyTypedAR: keyTyped; 
-    }
-    
     public synchronized List<EventObject> getQueued() {
         return queue;
     }
@@ -81,10 +77,8 @@ public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
     }
 
     public synchronized void reset() {
-        keyTyped = 0;
         keyPressed = 0;
         keyReleased = 0;
-        keyTypedAR = 0;
         keyPressedAR = 0;
         keyReleasedAR = 0;
         pressed = false;
@@ -99,7 +93,7 @@ public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
         }
         queue.add(e);
         if( verbose ) {
-            System.err.println("NEWT AWT PRESSED ["+pressed+"]: "+prefix+", "+e);
+            System.err.println("KEY NEWT PRESSED ["+pressed+"]: "+prefix+", "+e);
         }
     }
     
@@ -111,22 +105,10 @@ public class NEWTKeyAdapter extends KeyAdapter implements KeyEventCountAdapter {
         }
         queue.add(e);
         if( verbose ) {
-            System.err.println("NEWT AWT RELEASED ["+pressed+"]: "+prefix+", "+e);
+            System.err.println("KEY NEWT RELEASED ["+pressed+"]: "+prefix+", "+e);
         }
     }
      
-    @Override
-    public synchronized void keyTyped(KeyEvent e) {
-        keyTyped++;
-        if( 0 != ( e.getModifiers() & InputEvent.AUTOREPEAT_MASK ) ) {
-            keyTypedAR++;
-        }
-        queue.add(e);
-        if( verbose ) {
-            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+", keyReleased "+keyReleased+"]"; }
 }
 
diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java
index e090ed4..9909309 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTKeyUtil.java
@@ -38,28 +38,28 @@ import com.jogamp.newt.event.KeyEvent;
 
 public class NEWTKeyUtil {
     public static class CodeSeg {
-        public final int min;
-        public final int max;
+        public final short min;
+        public final short max;
         public final String description;
         
         public CodeSeg(int min, int max, String description) {
-            this.min = min;
-            this.max = max;
+            this.min = (short)min;
+            this.max = (short)max;
             this.description = description;
         }
     }
     public static class CodeEvent {
-        public final int code;
+        public final short code;
         public final String description;
         public final KeyEvent event;
         
-        public CodeEvent(int code, String description, 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)+" != "+event+" // "+description;
+            return "Code 0x"+Integer.toHexString( (int)code & 0x0000FFFF )+" != "+event+" // "+description;
         }
     }
             
@@ -90,46 +90,56 @@ public class NEWTKeyUtil {
     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++) {
-            final int c = codeSeg.min + i;
-            final int j = i*3+0; // KEY_PRESSED
-            final KeyEvent e = (KeyEvent) ( j < keyEvents.size() ? keyEvents.get(j) : null );
-            if( null == e || c != e.getKeyCode() ) {
+            // 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 = 3*codeCount == keyEvents.size() && 0 == missCodes.size();
+        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, int eventType, int modifier, int keyCode) {
-        if(0 <= keyCode) {
-            Assert.assertTrue("KeyEvent code mismatch, expected 0x"+Integer.toHexString(keyCode)+", has "+e, keyCode == e.getKeyCode());
-        }
+    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 <= modifier) {
-            Assert.assertTrue("KeyEvent modifier mismatch, expected 0x"+Integer.toHexString(modifier)+", has "+e, modifier == e.getModifiers());
+        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 int getNextKeyEventType(int et) {
+    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_TYPED;
-            case KeyEvent.EVENT_KEY_TYPED:
-                return KeyEvent.EVENT_KEY_PRESSED;
+                return KeyEvent.EVENT_KEY_PRESSED;                
             default:
-                Assert.assertTrue("Invalid event type "+et, false);
+                Assert.assertTrue("Invalid event "+e, false);
                 return 0;
-        }        
+        }
     }
     
     public static void validateKeyEventOrder(List<EventObject> keyEvents) {
@@ -141,45 +151,59 @@ public class NEWTKeyUtil {
                 eet = KeyEvent.EVENT_KEY_PRESSED;
             }
             final int et = e.getEventType();
-            Assert.assertEquals("Key event not in proper order", eet, et);
-            eet = getNextKeyEventType(et);
+            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 expTotalCount number of key press/release/types events
-     * @param expARCount number of key press/release/types Auto-Release events
+     * @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 expTotalCount, int expARCount) {
-        final int keyPressed = keyAdapter.getKeyPressedCount(false);
+    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 keyReleased = keyAdapter.getKeyReleasedCount(false);
+        final int keyReleasedALL = keyAdapter.getKeyReleasedCount(false);
         final int keyReleasedAR = keyAdapter.getKeyReleasedCount(true);
-        final int keyTyped = keyAdapter.getKeyTypedCount(false);
-        final int keyTypedAR = keyAdapter.getKeyTypedCount(true);
-        final int keyPressedNR = keyPressed-keyPressedAR;
-        final int keyReleasedNR = keyReleased-keyReleasedAR;
-        final int keyTypedNR = keyTyped-keyTypedAR;
-        System.err.println("Total Press "+keyPressed  +", Release "+keyReleased  +", Typed "+keyTyped);
-        System.err.println("AutoR Press "+keyPressedAR+", Release "+keyReleasedAR+", Typed "+keyTypedAR);
-        System.err.println("No AR Press "+keyPressedNR+", Release "+keyReleasedNR+", Typed "+keyTypedNR);
+        
+        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.getQueued();
-        Assert.assertEquals("Key event count not multiple of 3", 0, keyEvents.size()%3);
-        Assert.assertEquals("Key event count not 3 * press_release_count", expTotalCount, keyEvents.size());        
-        Assert.assertEquals("Key press count failure", expTotalCount/3, keyPressed);
-        Assert.assertEquals("Key press count failure (AR)", expARCount/3, keyPressedAR);
-        Assert.assertEquals("Key released count failure", expTotalCount/3, keyReleased);
-        Assert.assertEquals("Key released count failure (AR)", expARCount/3, keyReleasedAR);
-        Assert.assertEquals("Key typed count failure", expTotalCount/3, keyTyped);
-        Assert.assertEquals("Key typed count failure (AR)", expARCount/3, keyTypedAR);
         
-        // should be true - always, reaching this point - duh!
-        Assert.assertEquals( ( expTotalCount - expARCount ) / 3, keyPressedNR);
-        Assert.assertEquals( ( expTotalCount - expARCount ) / 3, keyReleasedNR);
-        Assert.assertEquals( ( expTotalCount - expARCount ) / 3, keyTypedNR);
-    }        
+        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/QuitAdapter.java b/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java
index 42d68da..b5864e3 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/QuitAdapter.java
@@ -32,21 +32,32 @@ 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 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 b028df3..82a80ff 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
@@ -28,7 +28,10 @@
  
 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.util.Iterator;
 import java.util.List;
 
@@ -59,7 +62,7 @@ public abstract class UITestCase {
     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
 
     private static volatile SingletonInstance singletonInstance;
@@ -141,6 +144,14 @@ public abstract class UITestCase {
         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) {
@@ -166,7 +177,7 @@ public abstract class UITestCase {
             }
             final String dblb = caps.getDoubleBuffered() ? "dbl" : "one";
             final String F_pfmt = sinkHasAlpha ? "rgba" : "rgb_";
-            final String pfmt = caps.getAlphaBits() > 0 ? "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() ;
@@ -184,9 +195,9 @@ public abstract class UITestCase {
     /**
      * Takes a snapshot of the drawable's current front framebuffer. Example filenames: 
      * <pre>
-     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgb_-D24-St00-Sa00_default-0400x0300.png
-     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgb_-D24-St00-Sa00_default-0200x0150.png
-     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgb_-D24-St00-Sa00_default-0200x0150.png
+     * 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>
diff --git a/www/index.html b/www/index.html
index e01abd5..a1643af 100644
--- a/www/index.html
+++ b/www/index.html
@@ -50,6 +50,7 @@
                     <h3>Presentations</h3>
                     <ul>
                         <li><a href="../../doc/gpunurbs2011/graphicon2011-slides.pdf">NURBS @ GPU</a></li>
+                        <li><a href="../../doc/siggraph2012/">Siggraph 2012</a></li>
                         <li><a href="../../doc/siggraph2011/jogamp-siggraph2011.pdf">Siggraph 2011</a></li>
                         <li><a href="../../doc/siggraph2010/jogamp-siggraph2010.pdf">Siggraph 2010</a></li>
                         <li><a href="BOF-3908-JOGL-slides.pdf"> JavaOne 2007 BOF Slides</a></li>
@@ -102,477 +103,596 @@
                     <p>
                         The following are a few examples of projects and products using
                         JOGL. To have your project featured here, please email the
-                        <a href="../../wiki/index.php/Maintainer_and_Contacts">project maintainers</a>.
+                        <a href="../../wiki/index.php/Maintainer_and_Contacts">project maintainers</a>.<br/>
+                        
+                        <i>Sections:</i> <a href="#feat_apps">Applications</a>, <a href="#feat_utils">Utilities</a>, <a href="#feat_games">Games</a> and
+                        <a href="#feat_old">Old</a>.
                     </p>
-                    
-                    <table border="0" cellpadding="0" cellspacing="1" width="100%">
+                    <table border="0" cellpadding="5" cellspacing="1" width="100%">
                         <tbody>
                             <tr>
-                                <td valign="top" width="100%">
-                                    <table border="0" cellpadding="5" cellspacing="1" width="100%">
+                                <th colspan="1"><a id="feat_apps">Applications (Content, Simulations, CAD, Scientific, ..)</a></th>
+                            </tr>
+                            <tr>
+                                <td >
+                                    <table border="0" cellspacing="15">
                                         <tbody>
                                             <tr>
+                                                <td width="50%">
+                                                    <a href="http://processing.org/"><img src="media/processing.jpg" width="160" height="158" align="left" alt="Processing"></img>
+                                                        Processing</a> is an open
+                                                    source programming language and environment for people who want to
+                                                    program images, animation, and sound. It is used by students, artists,
+                                                    designers, architects, researchers, and hobbyists for learning,
+                                                    prototyping, and production. Processing is developed by artists and
+                                                    designers as an alternative to proprietary software tools in the same
+                                                    domain. It uses JOGL for its hardware accelerated 3D rendering
+                                                    support.
+                                                </td>
+                                                <td width="50%">
+                                                    <a href="http://projects.hepforge.org/frog/ "><img src="media/Frog-Craft3_2.160w.png"
+                                                                                                        width="160" height="120" align="left" alt="FROG"></img>FROG</a>
+                                                    is a fast OpenGL event display tool mainly developed for visualization of data
+                                                    in the field of high energy physics. FROG is mostly used to visualized/animate data
+                                                    from proton/proton collision produced in the CMS experiment at the LHC, CERN, Switzerland.
+                                                    Animations produced by this tools are frequently used to share the progress of the
+                                                    CMS experiment with the media of the world
+                                                    (animations are often visible on scientific website or even on TV).
+
+                                                    FROG has recently been ported to Java and is now using JOGL
+                                                    and also offers an
+                                                    <a href="http://projects.hepforge.org/frog/Downloads/jfrog/jfrog_web.jnlp ">online demonstration</a>.
+                                                </td>
+                                            </tr>
+
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://c3d.com"><img src="media/c3d-studio.jpg"
+                                                                                                        width="160" height="107" align="left" alt="C3D"></img>C3D</a>'s
+                                                    <a href="http://c3d.com/index.php?option=com_content&view=section&layout=blog&id=5&Itemid=65">product palette</a>
+                                                    includes <i>C3D Studio</i> and <i>C3D Viewer</i>.
+                                                    <a href="http://c3d.com/index.php?option=com_content&view=article&id=46:c3dstudio&catid=34:generalproducts&Itemid=65">C3D Studio</a>
+                                                    is a 3D based visual framework for developing visual project control solutions for construction projects.
+                                                    C3D Studio provides a dynamic link between the 3D model of the project and the back-end data.
+                                                    <a href="http://c3d.com/index.php?option=com_content&view=article&id=47:c3dviewer&catid=34:generalproducts&Itemid=65">C3D Viewer</a>
+                                                    is the visualization tool for the 3D Model and related data. The user can either manually load 3D models and connect
+                                                    them to data sources, or execute Studio designed rich clients ( timelines) Where 3D and related data are loaded,
+                                                    linked and displayed for navigation and updates.
+                                                </td>
+
                                                 <td >
-                                                    <table border="0" cellspacing="15">
-                                                        <tbody>
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://processing.org/"><img src="media/processing.jpg" width="160" height="158" align="left" alt="Processing"></img>
-                                                                        Processing</a> is an open
-                                                                    source programming language and environment for people who want to
-                                                                    program images, animation, and sound. It is used by students, artists,
-                                                                    designers, architects, researchers, and hobbyists for learning,
-                                                                    prototyping, and production. Processing is developed by artists and
-                                                                    designers as an alternative to proprietary software tools in the same
-                                                                    domain. It uses JOGL for its hardware accelerated 3D rendering
-                                                                    support.
-                                                                </td>
-                                                                <td width="50%">
-                                                                    <a href="http://projects.hepforge.org/frog/ "><img src="media/Frog-Craft3_2.160w.png"
-                                                                                                                       width="160" height="120" align="left" alt="FROG"></img>FROG</a>
-                                                                    is a fast OpenGL event display tool mainly developed for visualization of data 
-                                                                    in the field of high energy physics. FROG is mostly used to visualized/animate data 
-                                                                    from proton/proton collision produced in the CMS experiment at the LHC, CERN, Switzerland.
-                                                                    Animations produced by this tools are frequently used to share the progress of the 
-                                                                    CMS experiment with the media of the world 
-                                                                    (animations are often visible on scientific website or even on TV).
-
-                                                                    FROG has recently been ported to Java and is now using JOGL
-                                                                    and also offers an
-                                                                    <a href="http://projects.hepforge.org/frog/Downloads/jfrog/jfrog_web.jnlp ">online demonstration</a>.
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://c3d.com"><img src="media/c3d-studio.jpg"
-                                                                                                                       width="160" height="107" align="left" alt="C3D"></img>C3D</a>'s                                              <a href="http://c3d.com/index.php?option=com_content&view=section&layout=blog&id=5&Itemid=65">product palette</a> includes <i>C3D Studio</i> and <i>C3D Viewer</i>.<a href="http://c3d.com/index.php?option=com_content&view=article&id=46:c3dst [...]
-                                                                </td>
-
-                                                                <td >
-                                                                    <a href="http://www3.math.tu-berlin.de/jreality/index.php?article_id=1"><img src="media/jreality-logo-discreteksurfaces.png"
-                                                                                                                   width="160" height="105" align="left" alt="jReality"></img>jReality</a> 
-                                                                    is a Java based, open-source, full-featured 3D scene graph package designed for 3D visualization and specialized in mathematical visualization. It provides several backends, including a JOGL one for Java based OpenGL rendering. JReality is thread-safe, has a flexible shading model based on an attribute-inheritance mechanism in the scene graph, device-independent user interaction and support for 3D audio (JACK). It has a  [...]
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://www.scilab.org/"><img src="media/scilab.png" width="160"  height="159" align="left" alt="Scilab"></img>
-                                                                        Scilab</a> is a free scientific software
-                                                                    package for numerical computations providing a powerful open computing
-                                                                    environment for engineering and scientific applications. It has
-                                                                    sophisticated data structures, an interpreter and a high level
-                                                                    programming language. It also integrates a 2-D and 3-D plotting module
-                                                                    designed to visually represent and understand complex data. Fully
-                                                                    integrated within the Scilab's Swing UI, the plotting module is based
-                                                                    on JOGL, allowing it to take advantage of the OpenGL accelerated
-                                                                    graphics.
-                                                                </td>
-
-                                                                <td width="50%">
-                                                                    <a href="http://www.brightideassoftware.com/Pebbles/PebblesHome.aspx">
-                                                                        <img src="media/pebbles.png" width="200" align="left" alt="OneStone Pebbles"></img>
-                                                                        OneStone® Pebbles</a> are a new series of calculus visualization tools developed
-                                                                    by <a href="http://www.brightideassoftware.com/">Bright Ideas Software®</a>.
-                                                                    Each 'Pebble' in the series is a stand-alone
-                                                                    program designed to illustrate a specific topic in the calculus
-                                                                    syllabus. While the topic of each Pebble is different, the experience
-                                                                    of using each remains as constant as possible, and features several
-                                                                    elements identified as contributing to the development of a deeper
-                                                                    understanding of dynamic covariant relationships. The Pebbles use JOGL
-                                                                    for their interactive 3D rendering. Try the
-                                                                    <a href="http://www.brightideassoftware.com/Pebbles/CurveFamilies.aspx"> Curve Families</a> and
-                                                                    <a href="http://www.brightideassoftware.com/Pebbles/SurfacesOfRevolution.aspx">Surfaces of Revolution</a> examples!
-                                                                </td>
-
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://code.google.com/p/jzy3d/">
-                                                                        <img src="http://martin.pernollet.free.fr/cv/projects/jzy3d/demo_ring_surface.jpg" width="160" height="120" align="left" alt="Jzy3D"></img>
-                                                                        Jzy3d</a>
-                                                                    stands for Java Easy 3d, and allows a rapid display of 3d scientific 
-                                                                    data. User can define z=f(x,y) functions binded to (customizable) 
-                                                                    colormaps, as well as rendering predefined simple 3d shapes 
-                                                                    programmaticaly or from csv files.
-                                                                    One can moreover add pre/post renderers for adding java2d layers 
-                                                                    to the 3d scene.  Jzy3d provides a simple bridge to AWT, SWT, or 
-                                                                    Swing, and has already been integrated in Eclipse RCP 
-                                                                    and Swing applications. The API releases one of the burden
-                                                                    of working with OpenGL, 
-                                                                    3d polygon ordering and transparency management.
-                                                                </td>
-
-                                                                <td width="50%">
-                                                                    <a href="http://gephi.org/"><img src="media/gephi.jpg" width="160" height="102" align="left" alt="Gephi"></img>
-                                                                        Gephi</a> is a tool for people that have to explore and understand graphs. Like Photoshop but for data, the user interacts with the representation, manipulate the structures, shapes and colors to reveal hidden properties. The goal is to help data analysts to make hypothesis, intuitively discover patterns, isolate structure singularities or faults during data sourcing. It is a complementary tool to traditional statist [...]
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://jebgl.com/"><img src="media/JebGL_logo.160w.png"
-                                                                                                                   width="160" height="87" align="left" alt="JebGL"></img>JebGL</a> 
-                                                                    is a piece of Javascript which lets you run your WebGL apps in browsers lacking WebGL support without having to modify your existing code! Behind the scenes JebGL uses a fallback Java applet to emulate the WebGL canvas if needed, and the Java applet runs hardware accelerated on all platforms using JOGL. 
-                                                                    JebGL is open source, released under the MIT license.  
-                                                                </td>
-
-                                                                <td width="50%">
-                                                                    <a href="http://brandonborkholder.github.com/glg2d/"><img src="media/glg2d-demo.png" width="200" align="left" alt="GLG2D"></img>
-                                                                        GLG2D</a> is a Graphics2D implementation that uses OpenGL to implement basic Java2D drawing functionality. We currently use the fixed function pipeline, with the GL2 profile for most functionality. But a shader implementation is in the pipeline (so to speak). See <a href="http://brandonborkholder.github.com/glg2d/implementationstatus.html">implementation status</a> for which features are fully implemented.
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://www.everplanes.com/"><img src="media/EverplanesLogo_160x160.png" width="122" height="122" align="left" alt="Everplanes"></img>
-                                                                        Everplanes</a> is a game of exploration, building, survival and strategy. 
-                                                                        It introduces new gameplay, resources and challenges in the updates. 
-                                                                        Each time the game is started, it automatically downloads the latest updates.
-                                                                        The game includes a built-in server for LAN or Internet play. 
-                                                                        You can run an open server, or configure various levels of access control. 
-                                                                        Everplanes features a built-in server browser and also includes global chat facility.
-                                                                        Everplanes is available for Mac OS X 10.4+, Windows XP/Vista/7 and Linux.
-                                                                </td>
-                                                                <td width="50%">
-                                                                    <a href="http://www.codefrontiers.com/page/elflight-engine/"><img src="media/elflightengine-160x122.png" width="160" height="122" align="left" alt="Elflight Engine"></img>
-                                                                        The Elflight Engine</a> is a games engine designed for the web.
-                                                                        It supports hardware accelerated 3D games and applications in a web browser,
-                                                                        with the ability to import assets from major 3D packages such as Maya and 3D Studio.
-                                                                        The focus of the engine's architecture is minimal startup time, fast streaming, local
-                                                                        caching and collaborative real-time editing. The Elflight Engine is multi-user and so
-                                                                        lends itself to the development of virtual worlds and MMOs.
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <b>On the brink ...</b>
-                                                                </td>
-                                                                <td width="50%">
-                                                                    <b>.. to use JOGL Version 2.</b>
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://worldwind.arc.nasa.gov/java/"><img src="media/worldwind.jpg"
-                                                                                                                       width="160" align="left" alt="World Wind"></img>NASA World Wind
-                                                                        Java</a> provides next-generation 3-D virtual globe technology for
-                                                                    applications written in the Java programming language. It supplies a
-                                                                    suite of open-source components that developers include in their own
-                                                                    applications, providing virtual globe functionality to any application
-                                                                    that can benefit from it. World Wind Java's components perform as well
-                                                                    as, or better than, any other known implementation and utilize the
-                                                                    OpenGL API for 3-D graphics via JOGL. See WWJ Technical Lead Tom
-                                                                    Gaskins' <a href="http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-3489&yr=2007&track=2">JavaOne
-                                                                        2007</a> presentation on World Wind Java and the DiSTI Corporation's
-                                                                    <a href="http://www.disti.com/Products/demonstrations/java.html">F-16 flight simulator</a>
-                                                                    built using World Wind Java.
-                                                                </td>
-
-                                                                <td width="50%">
-                                                                    <a href="http://www.geogebra.org/"><img src="media/geogebra-screenshot-tangents.png" width="200" align="left" alt="GeoGebra"></img>GeoGebra</a> is free and multi-platform dynamic mathematics software for all levels of education that joins geometry, algebra, tables, graphing, statistics and calculus in one easy-to-use package. It has received several educational software awards in Europe and the USA. <a href="http://www.g [...]
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <b>Older projects ...</b>
-                                                                </td>
-                                                                <td width="50%">
-                                                                    <b>.. may use JOGL Version 1.</b>
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://volumeviewer.kenai.com/">
-                                                                        <img src="http://volumeviewer.kenai.com/thumbnail.png" width="160" height="120" align="left" alt="Volume Viewer"></img>Volume Viewer</a>
-                                                                    is an open source renderer for 3D volumetric data. It provides tools for coloring your model,
-                                                                    cutting away pieces, and viewing it from any angle. It can cast shadows within the model for extra realism.
-                                                                    You can even upload your own volumetric data and view it in real time.
-                                                                </td>
-                                                                <td >
-                                                                    <a href="http://bytonic.de/html/jake2.html">
-                                                                        <img src="media/jake2.jpg" width="160" height="128" align="left" alt="Jake2"></img>Jake2</a> is a port
-                                                                    of id Software's GPL'd Quake II engine from C to Java done by <a
-                                                                        href="http://bytonic.de/">bytonic software</a>. You can run the game
-                                                                    via <a href="http://bytonic.de/html/jake2_webstart.html">Java Web
-                                                                        Start</a> with <b>no manual installation</b> on all of JOGL's
-                                                                    supported platforms.
-                                                                </td>
-
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://www.fusion-laboratory.de/"><img
-                                                                            src="media/fusion-laboratory.jpg" width="160" height="160" align="left"
-                                                                            alt="Fusion Laboratory"></img>The Fusion Framework</a> enables Swing
-                                                                    components to be extended with 3D content via JOGL. In general the 3D
-                                                                    content will show up in layers on top of the corresponding Swing
-                                                                    component. Many utility functions are integrated to help the developer
-                                                                    build components. For example, the 3D content may be calibrated to the
-                                                                    corresponding component's bounds. In addition, the system provides a
-                                                                    simple scenegraph, Swing-like mouse interaction, and low-level
-                                                                    animation support, as well as GLSL shaders and .obj file loading. The
-                                                                    demo page contains several Java Web Start applications which
-                                                                    demonstrate the abilities of the framework; please fill out the web
-                                                                    form to help evaluate the components' usefulness.
-                                                                </td>
-
-                                                                <td width="50%">
-                                                                    <a href="http://3d-alignment.eu"><img src="media/strap.jpg" width="160" height="118" align="left" alt="STRAP"></img></a>
-                                                                    With <a href="http://3d-alignment.eu">STRAP</a> you can align your proteins by
-                                                                    sequence and 3D-structure.  STRAP simultaneously displays
-                                                                    3d-structures, amino acid sequence alignment and nucleotide sequences.
-                                                                    It has powerful annotation features.
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://www.artofillusion.org/"><img src="media/artofillusion.jpg" width="160" height="117" align="left" alt="Art Of Illusion"></img>
-                                                                        Art of Illusion</a> is a free, open source 3D modelling and rendering
-                                                                    studio. Many of its capabilities rival those found in commercial
-                                                                    programs. Some of the highlights include subdivision surface based
-                                                                    modelling tools, skeleton based animation, and a graphical language
-                                                                    for designing procedural textures and materials. It uses JOGL for
-                                                                    real-time OpenGL rendering in its modeling views.
-                                                                </td>
-
-                                                                <td width="50%">
-                                                                    <a href="http://impact.sourceforge.net/"><img src="media/impact.jpg" width="160" height="129" align="left" alt="Impact"></img>
-                                                                        Impact</a> is a
-                                                                    complete finite element suite including preprocessor, solver and
-                                                                    postprocessor which is useable for simulating dynamic events such as
-                                                                    car crashes or stamping of metal sheets. The suite allows 3D
-                                                                    modelling, solving and viewing of simulation results, all in OpenGL
-                                                                    accelerated graphics through the use of JOGL.
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://www.sculpteo.com"><img src="media/sculpteo_3_robot_72dpi_sm.jpg" width="160" height="120" align="left" alt="Sculpteo"></img>
-                                                                        Sculpteo</a> offers a 3D printing service, fast and available for everyone.
-                                                                    Starting from a 3D design, Sculpteo makes a specific object : interior decoration, characters, robots, miniatures, models, mechanic objects...
-                                                                </td>
-                                                                <td width="50%">
-                                                                    <a href="http://www.fenggui.org/"><img src="media/fenggui.jpg" width="160" height="127" align="left" alt="FengGUI"></img>
-                                                                        FengGUI</a> is a graphical
-                                                                    user interface (GUI) application programming interface (API) based on
-                                                                    OpenGL. FengGUI provides all typical GUI components like buttons,
-                                                                    sliders, trees, text areas, frames, tabs, etc. which are required to
-                                                                    build a complete GUI system. Since it is based on OpenGL, FengGUI fits
-                                                                    well in multimedia and game environments.
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://mbt.sdsc.edu/"><img src="media/mbt.jpg" width="160" height="122" align="left" alt="Molecular Biology Toolkit"></img></a>The
-                                                                    <a href="http://mbt.sdsc.edu/">Molecular Biology Toolkit</a> is a
-                                                                    Java-based protein visualization and analysis toolkit. The toolkit
-                                                                    provides classes for efficiently loading, managing and manipulating
-                                                                    protein structure and sequence data. The MBT also provides a rich set
-                                                                    of graphical 3D and 2D visualization components which can be easily
-                                                                    "plugged together" to produce applications having sophisticated
-                                                                    graphical user interfaces. Some MBT-based visualization tools are <a
-                                                                        href="http://www.pdb.org/">ProteinWorkshop</a> (<a
-                                                                        href="http://spdc.sdsc.edu/iedb/protein_workshop/viewer7.php">webstart
-                                                                        demo</a>), <a href="http://www.immuneepitope.org/">EpitopeViewer</a>
-                                                                    (<a href="http://spdc.sdsc.edu/iedb/epitopeViewer/viewer_jogl333.php">webstart demo</a>), and <a href="http://sirius.sdsc.edu/">Sirius</a>.
-                                                                </td>
-
-                                                                <td width="50%">
-                                                                    <a href="http://www.specknet.org/dev/specksim"><img src="media/specksim.jpg" width="160" height="117" align="left" alt="SpeckSim"></img>
-                                                                        SpeckSim</a> is a
-                                                                    behaviour-level simulator for networks of small, resource-constrained
-                                                                    devices with sensing, computation and communication
-                                                                    capabilities. Intended as a testbed for distributed algorithms, the
-                                                                    main design goal was ease of extension. To this end, almost all aspect
-                                                                    of the simulator can be customised: Node behaviour, communication
-                                                                    characteristics, placement and motion; visualisation rendering and
-                                                                    interaction and statistic generation.
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://www.insightmachines.com/en/vehicleDynamicsEngine.shtml">
-                                                                        <img src="media/vehicle.jpg" width="160" height="160" align="left" alt="Vehicle Dynamics Engine Demo"></img>Vehicle Dynamics Engine Demo</a>
-                                                                    is a Java Web Start demonstration of a 3D physics engine developed by
-                                                                    <a href="http://www.insightmachines.com/">Insight Machines</a>. The
-                                                                    engine is designed especially for car games. The demo uses JOGL and
-                                                                    employs such techniques like shadow casting using the stencil buffer.
-                                                                </td>
-
-                                                                <td width="50%">
-
-                                                                    <a href="http://chronotext.org/"><img src="media/chronotext.jpg" width="160" height="120" align="left" alt="chronotext"></img>
-                                                                        chronotext</a> is a series
-                                                                    of visual design experiments involving animated text and 3D objects
-                                                                    and surfaces. Several examples can be run on-line via <a
-                                                                        href="http://chronotext.org/scriptorium/behind/index.htm">Java Web
-                                                                        Start</a>. See the <a href="http://www.chronotext.org/mapping/">latest
-                                                                        experiments</a> of mapping text on to real 3D surfaces.
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://www.avengina.org/"><img src="media/avengina.jpg" alt="Avengina" align="left" height="99" width="160"></img>Avengina</a> is a
-                                                                    realtime 3D graphics engine which is designed for the execution as a
-                                                                    Java applet. Alternatively it can be launched as a Java Webstart
-                                                                    application outside the browserwindow. The software provides the
-                                                                    possibility to exhibit texts and images in virtual
-                                                                    galleries. Regarding the control and behaviour of the avatar it's
-                                                                    redolent of a game engine. The graphics rendering system bases on
-                                                                    per-pixel lighting and supports normal mapping, specular lighting and
-                                                                    stencil volume shadows. Avengina uses JOGL for realtime rendering.
-                                                                </td>
-
-                                                                <td >
-                                                                    <a href="http://netbeans-opengl-pack.dev.java.net/">
-                                                                        <img src="media/NetBeansOpenGLPackLogo160.png" width="160" height="159" align="left" alt="NOGL Pack logo"></img>
-                                                                        The NetBeans OpenGL Pack</a> provides an easy to use OpenGL development
-                                                                    environment integrated into NetBeans. It supplies modules like an GLSL
-                                                                    shader editor, hardware compiler/linker integration and tools for
-                                                                    displaying hardware information. The pack ships ready to run JOGL (JSR
-                                                                    231) demo projects and all OpenGL samples of the OpenGL Programming
-                                                                    Guide (also known as the Red Book).
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://www.nascar.com/trackpass/about/raceview/"><img src="media/raceview.jpg" width="160" height="92" align="left" alt="RaceView"></img>
-                                                                        RaceView</a> from NASCAR / NEXTEL, part of the <a
-                                                                        href="http://www.nascar.com/trackpass/">TrackPass</a> package, puts
-                                                                    you in the race. Control the virtual camera angle, listen to the
-                                                                    driver and team, and see crucial statistics and times, all in real
-                                                                    time as the race goes on. RaceView uses JOGL for its 3D rendering.
-                                                                </td>
-
-                                                                <td width="50%">
-                                                                    <a href="http://www.insparia.com/"><img src="media/insparia.jpg" width="160" height="160" align="left" alt="Insparia"></img>
-                                                                        Insparia</a> was created to help people
-                                                                    easily visualize, construct and track information about a 3d
-                                                                    environment online. Shape and texture importing as well as a robust
-                                                                    renderer will be available in the final commercial version.  Insparia
-                                                                    uses JOGL to allow the user to construct and interact with their 3d
-                                                                    environment in real-time. Please note that Insparia is in alpha
-                                                                    testing. Feedback is appreciated.
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <b>Discontinued ..</b>
-                                                                </td>
-                                                                <td width="50%">
-                                                                    <b>.. projects</b>
-                                                                </td>
-                                                            </tr>
-                                                            <tr>
-                                                                <td width="50%">
-                                                                    <a href="http://www.madlix.com"><img src="media/madlix.png" width="160"
-                                                                                                         height="160" align="left" alt="Madlix"></img>MADLIX</a> lets users insert
-                                                                    3D-content in web pages, blogs, Google pages, community presentations
-                                                                    and more. MADLIX is JOGL-powered and runs smoothly inside all
-                                                                    Java-enabled browsers, with no need for custom plug-ins or application
-                                                                    installation. The <a href="http://www.madlix.com">on-line gallery</a>
-                                                                    features high-quality content ready for insertion. MADLIX is
-                                                                    accompanied by the MADLIX exporter tool enabling 3D artists to
-                                                                    directly export their 3D artwork from Autodesk Maya to the MADLIX
-                                                                    gallery. The exporter features pre-view functionality as well as a
-                                                                    standalone viewer, supporting the MADLIX file format and the open
-                                                                    standard file format COLLADA.
-
-                                                                </td>
-                                                                <td width="50%">
-                                                                    <a href="https://zg3d.dev.java.net/"><img src="media/zg3d.png" width="160" height="160" align="left" alt="ZG3D"></img>
-                                                                        ZG3D</a> is an open source project that uses
-                                                                    JOGL for visualizing 3D geometries with the emphasis of plotting
-                                                                    scientific data in a web application. Geometry objects in an XML file
-                                                                    or string can be dynamically loaded and removed. An HTML document may
-                                                                    call ZG3D functions through JavaScript and may define JavaScript
-                                                                    functions to receive messages from ZG3D, which makes it very easy and
-                                                                    flexible to embed interactive 3D web visualization. The software is
-                                                                    developed at the <a
-                                                                        href="http://www-cger.nies.go.jp/index.html">Center for Global
-                                                                        Environmental Research</a>, Japan, for the advanced data visualization
-                                                                    of the <a href="http://db.cger.nies.go.jp/g3db/ggtu/trajectory.html">Global Greenhouse Gases Database</a>.
-                                                                </td>
-                                                            </tr>
-
-                                                            <tr>
-                                                                <td  width="50%">
-                                                                    <a href="http://www.simulation.com/products/glstudio/glstudio.html"><img
-                                                                            src="media/glstudio.jpg" width="160" height="135" align="left" alt="GL Studio"></img>
-                                                                        GL Studio</a> is an object oriented rapid application
-                                                                    development tool that allows a user to graphically combine
-                                                                    photographs, 3D models and behavior logic to create advanced 2D and 3D
-                                                                    human machine interfaces.  GL Studio generates Java or C++ source code
-                                                                    which can then be integrated into the user’s application as a user
-                                                                    interface. <a
-                                                                        href="http://www.simulation.com/products/glstudio/java/java.html">Java
-                                                                        code</a> generated with GL Studio can be deployed using
-                                                                    javax.swing.JPanel, java.awt.Canvas and JavaBeans. GL Studio uses
-                                                                    OpenGL for rendering and GL Studio for Java uses the JOGL API.
-
-                                                                </td>
-
-                                                                <td width="50%">
-                                                                    <a href="http://www.vlsolutions.com/">
-                                                                        <img src="media/vldocking.jpg" width="160" height="113" align="left" alt="VLDocking"></img>VLDocking</a> is
-                                                                    a set of Java components that helps the Swing developer to build
-                                                                    applications with Docking capabilities, and even raise existing
-                                                                    applications to higher standards. It supports docking via drag and
-                                                                    drop, enhanced toolbars, closable tabs, and more. It fully supports
-                                                                    heavyweight components such as JOGL's GLCanvas in a docking
-                                                                    environment.
-                                                                </td>
-                                                            </tr>
-
-                                                            <!--- abandoned JOGL ..
-                                                            <tr>
-                                                                <td >
-                                                                    <a href="http://openendedgroup.com/field"><img src="media/field.png"
-                                                                                                                   width="160" height="159" align="left" alt="Field"></img>Field</a> is an
-                                                                    open-source development environment for digital art and experimental
-                                                                    code writing. Built around the needs of programmers that manipulate
-                                                                    images, make animations and compose music, Field seeks to tie
-                                                                    text-based programming with ad hoc visual metaphors. Field uses Python
-                                                                    and other programming languages and wants to be integrated into your
-                                                                    own personal code-base. And it comes with special support for the <a
-                                                                        href="http://processing.org/">Processing</a> environment. Field uses
-                                                                    JOGL for its UI and its built-in drawing system; it provides a
-                                                                    JOGL-based scene-graph library for 3D visualization.
-                                                                </td>
-                                                            </tr>
-                                                                <td width="50%">
-                                                                    <a href="http://www.eclipse.org/gef3d/"><img src="http://wiki.eclipse.org/images/thumb/b/be/Gef3d_sample_ecore3D.png/800px-Gef3d_sample_ecore3D.png" width="160" height="94" align="left" alt="GEF3d"></img>
-                                                                        GEF3D</a> is an Eclipse GEF extension bringing 3D to diagram editing.
-                                                                    That is with GEF3D you can create 3D diagrams, 2D diagrams and combine
-                                                                    3D with 2D diagrams. GEF3D extends GEF by providing 3D enabled draw and
-                                                                    controller classes. Instead of drawing 2D figures, you can now draw 3D figures.
-                                                                    Existing GEF-based 2D editors can be embedded into 3D editors with minimal effort.
-                                                                </td>
-                                                            -->
-
-                                                        </tbody>
-                                                    </table>
+                                                    <a href="http://www3.math.tu-berlin.de/jreality/index.php?article_id=1"><img src="media/jreality-logo-discreteksurfaces.png"
+                                                                                                    width="160" height="105" align="left" alt="jReality"></img>jReality</a>
+                                                    is a Java based, open-source, full-featured 3D scene graph package designed for 3D visualization and specialized in mathematical visualization.
+                                                    It provides several backends, including a JOGL one for Java based OpenGL rendering. JReality is thread-safe,
+                                                    has a flexible shading model based on an attribute-inheritance mechanism in the scene graph, device-independent user interaction and support
+                                                    for 3D audio (JACK). It has a plugin system for assembling custom viewers,
+                                                    <a href="http://www3.math.tu-berlin.de/jreality/phpbb/">an active forum</a> and a growing set of
+                                                    <a href="http://www3.math.tu-berlin.de/jreality/mediawiki/index.php/Developer_Tutorial">tutorial examples</a>
+                                                    to help developers interested in using jReality to solve their Java 3D problems.
+                                                    For further information please look <a href="http://www3.math.tu-berlin.de/jreality/index.php?article_id=29">here</a>.
+                                                </td>
+                                            </tr>
+
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.scilab.org/"><img src="media/scilab.png" width="160"  height="159" align="left" alt="Scilab"></img>
+                                                        Scilab</a> is a free scientific software
+                                                    package for numerical computations providing a powerful open computing
+                                                    environment for engineering and scientific applications. It has
+                                                    sophisticated data structures, an interpreter and a high level
+                                                    programming language. It also integrates a 2-D and 3-D plotting module
+                                                    designed to visually represent and understand complex data. Fully
+                                                    integrated within the Scilab's Swing UI, the plotting module is based
+                                                    on JOGL, allowing it to take advantage of the OpenGL accelerated
+                                                    graphics.
+                                                </td>
+
+                                                <td width="50%">
+                                                    <a href="http://www.brightideassoftware.com/Pebbles/PebblesHome.aspx">
+                                                        <img src="media/pebbles.png" width="160" align="left" alt="OneStone Pebbles"></img>
+                                                        OneStone® Pebbles</a> are a new series of calculus visualization tools developed
+                                                    by <a href="http://www.brightideassoftware.com/">Bright Ideas Software®</a>.
+                                                    Each 'Pebble' in the series is a stand-alone
+                                                    program designed to illustrate a specific topic in the calculus
+                                                    syllabus. While the topic of each Pebble is different, the experience
+                                                    of using each remains as constant as possible, and features several
+                                                    elements identified as contributing to the development of a deeper
+                                                    understanding of dynamic covariant relationships. The Pebbles use JOGL
+                                                    for their interactive 3D rendering. Try the
+                                                    <a href="http://www.brightideassoftware.com/Pebbles/CurveFamilies.aspx"> Curve Families</a> and
+                                                    <a href="http://www.brightideassoftware.com/Pebbles/SurfacesOfRevolution.aspx">Surfaces of Revolution</a> examples!
+                                                </td>
+
+                                            </tr>
+
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.geogebra.org/"><img src="media/geogebra-screenshot-tangents.png" width="160" align="left" alt="GeoGebra"></img>GeoGebra</a>
+                                                    is free and multi-platform dynamic mathematics software for all levels of education that joins geometry, algebra,
+                                                    tables, graphing, statistics and calculus in one easy-to-use package.
+                                                    It has received several educational software awards in Europe and the USA.
+                                                    <a href="http://www.geogebra.org/forum/viewtopic.php?f=52&t=19846">GeoGebra 5.0</a> has experimental 3D support utilizing JOGL.
+                                                    Misc resources: <a href="https://dev.geogebra.org/trac">Developer Wiki</a>, <a href="http://dev.geogebra.org/svn">SVN Repository</a>.
+                                                </td>
+
+                                                <td width="50%">
+                                                    <a href="http://gephi.org/"><img src="media/gephi.jpg" width="160" height="102" align="left" alt="Gephi"></img>
+                                                        Gephi</a> is a tool for people that have to explore and understand graphs. Like Photoshop but for data,
+                                                        the user interacts with the representation, manipulate the structures, shapes and colors to reveal hidden properties.
+                                                        The goal is to help data analysts to make hypothesis, intuitively discover patterns, isolate structure singularities or
+                                                        faults during data sourcing. It is a complementary tool to traditional statistics,
+                                                        as visual thinking with interactive interfaces is now recognized to facilitate reasoning.
+                                                        This is a software for Exploratory Data Analysis, a paradigm appeared in the Visual Analytics field of research.
+                                                </td>
+                                            </tr>
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://code.google.com/p/jzy3d/">
+                                                        <img src="http://martin.pernollet.free.fr/cv/projects/jzy3d/demo_ring_surface.jpg" width="160" height="120" align="left" alt="Jzy3D"></img>
+                                                        Jzy3d</a>
+                                                    stands for Java Easy 3d, and allows a rapid display of 3d scientific
+                                                    data. User can define z=f(x,y) functions binded to (customizable)
+                                                    colormaps, as well as rendering predefined simple 3d shapes
+                                                    programmaticaly or from csv files.
+                                                    One can moreover add pre/post renderers for adding java2d layers
+                                                    to the 3d scene.  Jzy3d provides a simple bridge to AWT, SWT, or
+                                                    Swing, and has already been integrated in Eclipse RCP
+                                                    and Swing applications. The API releases one of the burden
+                                                    of working with OpenGL,
+                                                    3d polygon ordering and transparency management.
+                                                </td>
+                                                <td width="50%">
+                                                    <a href="http://volumeviewer.kenai.com/">
+                                                        <img src="http://volumeviewer.kenai.com/thumbnail.png" width="160" height="120" align="left" alt="Volume Viewer"></img>Volume Viewer</a>
+                                                    is an open source renderer for 3D volumetric data. It provides tools for coloring your model,
+                                                    cutting away pieces, and viewing it from any angle. It can cast shadows within the model for extra realism.
+                                                    You can even upload your own volumetric data and view it in real time.
+                                                </td>
+                                            </tr>
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.insparia.com/"><img src="media/insparia.jpg" width="160" height="160" align="left" alt="Insparia"></img>
+                                                        Insparia</a> was created to help people
+                                                    easily visualize, construct and track information about a 3d
+                                                    environment online. Shape and texture importing as well as a robust
+                                                    renderer will be available in the final commercial version.  Insparia
+                                                    uses JOGL to allow the user to construct and interact with their 3d
+                                                    environment in real-time. Please note that Insparia is in alpha
+                                                    testing. Feedback is appreciated.
+                                                </td>
+                                                <td width="50%">
                                                 </td>
                                             </tr>
                                         </tbody>
                                     </table>
                                 </td>
                             </tr>
+                            <tr>
+                                <th colspan="1"><a id="feat_utils">Utilities, Libraries, Building blocks</a></th>
+                            </tr>
+                            <tr>
+                                <td >
+                                    <table border="0" cellspacing="15">
+                                        <tbody>
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://jmonkeyengine.org/"><img src="media/jmonkeyengine.png"
+                                                                                                    width="160" align="left" alt="jMonkeyEngine"></img>jMonkeyEngine</a>
+                                                is a game engine made for developers who want to create 3D games following modern technology standards.
+                                                The framework is programmed entirely in Java aimed at wide accessibility and quick deployment to desktop, web, and mobile platforms.<br/>
+                                                Currently <a href="../../wiki/index.php/Maintainer_and_Contacts#Julien_Gouesse">Julien Gouesse</a>
+                                                develops a <a href="http://jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/jogl-support-jogl2-that-is/">JOGL backend for jME3</a>
+                                                with support of the jME team. <i>NEWT support</i> is also underway, which will allow jME3 to run <i>on mobile devices</i> as long
+                                                proper <a href="http://jogamp.org/jogl/doc/Overview-OpenGL-Evolution-And-JOGL.html">JOGL/OpenGL</a>
+                                                <a href="http://jogamp.org/jogl/doc/bouml/html-svg/fig128069.svg">profile separation</a> is being used.
+                                                </td>
+
+                                                <td width="50%">
+                                                    <a href="http://ardor3d.com/"><img src="media/ardor3d.png"
+                                                                                                    width="160" align="left" alt="Ardor3D"></img>Ardor3D</a>
+                                                    is a professionally oriented, open source, Java based 3D engine brought to you by <a href="http://www.ardorlabs.com/">Ardor Labs</a>.<br/>
+                                                    <a href="../../wiki/index.php/Maintainer_and_Contacts#Julien_Gouesse">Julien Gouesse</a> started the new JOGL backend development,
+                                                    which is now merged into the official trunk.
+                                                </td>
+                                            </tr>
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://en.wikipedia.org/wiki/Java_3D"><img src="media/Java3d.png" width="160" align="left" alt="Ardor3D"></img>Java3D</a>
+                                                    <a href="http://gouessej.wordpress.com/2012/08/01/java-3d-est-de-retour-java-3d-is-back/">is back</a>.
+                                                    It is maintained by <a href="../../wiki/index.php/Maintainer_and_Contacts#Harvey_Harrison">Harvey Harrison</a> and initially ported to
+                                                    our current JOGL version by <a href="../../wiki/index.php/Maintainer_and_Contacts#Julien_Gouesse">Julien Gouesse</a>.<br/>
+                                                    Source available via this <a href="https://github.com/hharrison/java3d-core">git repository</a>
+                                                    and JAR files can <a href="https://github.com/hharrison/java3d-core/downloads">be downloaded here</a>.
+                                                    Our <a href="http://forum.jogamp.org/java3d-f3728156.html">forum</a> may help you with your questions.
+                                                </td>
+                                                
+                                                <td width="50%">
+                                                    <a href="http://www.dyn4j.org/"><img src="media/dyn4j.png"
+                                                                                                    width="160" align="left" alt="dyn4j"></img>dyn4j</a>
+                                                is a 100% Java 2D collision detection and physics engine. Designed to be fast, stable, extensible, and easy to use.
+                                                dyn4j is free for use in commercial and non-commercial applications and licensed under the New BSD License.
+                                                The project comprises hundreds of JUnit test cases, Sandbox: a GUI test application, two example applications (ExampleGraphics2D and ExampleJOGL),
+                                                Javadocs, wiki, forum, and more!
+                                                </td>
+                                            </tr>
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://brandonborkholder.github.com/glg2d/"><img src="media/glg2d-demo.png" width="160" align="left" alt="GLG2D"></img>
+                                                        GLG2D</a> is a Graphics2D implementation that uses OpenGL to implement basic Java2D drawing functionality.
+                                                        We currently use the fixed function pipeline, with the GL2 profile for most functionality.
+                                                        But a shader implementation is in the pipeline (so to speak).
+                                                        See <a href="http://brandonborkholder.github.com/glg2d/implementationstatus.html">implementation status</a>
+                                                        for which features are fully implemented.
+                                                </td>
+                                                <td width="50%">
+                                                    <a href="http://nifty-gui.lessvoid.com/"><img src="media/nifty-logo-new.png" width="160" align="left" alt="Nifty GUI"></img>
+                                                        Nifty GUI</a> is a Java Library that supports the building of interactive user interfaces for games or similar applications.
+                                                        The configuration of the GUI is stored in xml files with little supporting Java code.
+                                                        In short Nifty helps you to layout stuff, display it in a cool way and interact with it :)<br/>
+                                                        Source code is available in this <a href="https://github.com/void256/nifty-gui">git repository</a>.
+                                                        JOGL is one renderer backend besides others.
+                                                </td>
+                                            </tr>
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://jebgl.com/"><img src="media/JebGL_logo.160w.png"
+                                                                                                    width="160" height="87" align="left" alt="JebGL"></img>JebGL</a>
+                                                    is a piece of Javascript which lets you run your WebGL apps in browsers lacking WebGL support without having to modify your existing code!
+                                                    Behind the scenes JebGL uses a fallback Java applet to emulate the WebGL canvas if needed, and the Java applet runs hardware accelerated
+                                                    on all platforms using JOGL.
+                                                    JebGL is open source, released under the MIT license.
+                                                </td>
+
+                                                <td width="50%">
+                                                </td>
+                                            </tr>
+                                        </tbody>
+                                    </table>
+                                </td>
+                            </tr>
+                            <tr>
+                                <th colspan="1"><a id="feat_games">Games</a></th>
+                            </tr>
+                            <tr>
+                                <td >
+                                    <table border="0" cellspacing="15">
+                                        <tbody>
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://store.steampowered.com/app/108200/"><img src="media/ticket2ride_picture4.jpg"
+                                                                                                        width="160" align="left" alt="Ticket to Ride"></img>Ticket to Ride</a>
+                                                        and <a href="http://store.steampowered.com/app/108210/">Memoir '44</a> are boardgames published by
+                                                        <a href="http://www.daysofwonder.com/">Days of Wonder</a>.
+                                                        They also make digital versions of these games since 2006. These are available on all desktops computers (Windows, MacOS and Linux),
+                                                        thanks to the use of Java and JOGL.
+                                                        This has proven to be the best solution to create the same gaming experience on all desktop computers with a single code base.
+                                                        The games are available on Steam. Days of Wonder is currently porting their engine to JOGL2, allowing the inclusion of Android devices.
+                                                </td>
+
+                                                <td width="50%">
+                                                    <a href="http://www.everplanes.com/"><img src="media/EverplanesLogo_160x160.png" width="122" height="122" align="left" alt="Everplanes"></img>
+                                                        Everplanes</a> is a game of exploration, building, survival and strategy.
+                                                        It introduces new gameplay, resources and challenges in the updates.
+                                                        Each time the game is started, it automatically downloads the latest updates.
+                                                        The game includes a built-in server for LAN or Internet play.
+                                                        You can run an open server, or configure various levels of access control.
+                                                        Everplanes features a built-in server browser and also includes global chat facility.
+                                                        Everplanes is available for Mac OS X 10.4+, Windows XP/Vista/7 and Linux.
+                                                </td>
+                                            </tr>
+
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.codefrontiers.com/page/elflight-engine/"><img src="media/elflightengine-160x122.png" width="160" height="122" align="left" alt="Elflight Engine"></img>
+                                                        The Elflight Engine</a> is a games engine designed for the web.
+                                                        It supports hardware accelerated 3D games and applications in a web browser,
+                                                        with the ability to import assets from major 3D packages such as Maya and 3D Studio.
+                                                        The focus of the engine's architecture is minimal startup time, fast streaming, local
+                                                        caching and collaborative real-time editing. The Elflight Engine is multi-user and so
+                                                        lends itself to the development of virtual worlds and MMOs.
+                                                </td>
+
+                                                <td width="50%">
+                                                    <a href="http://bytonic.de/html/jake2.html">
+                                                        <img src="media/jake2.jpg" width="160" height="128" align="left" alt="Jake2"></img>Jake2</a> is a port
+                                                    of id Software's GPL'd Quake II engine from C to Java done by <a
+                                                        href="http://bytonic.de/">bytonic software</a>.<br/>
+                                                    Jake2 has been ported to the current JOGL version for desktop OpenGL and mobile OpenGL ES1 and ES2 use
+                                                    including dropping AWT in favor of NEWT.
+                                                        You can run the game <a href="http://jogamp.org/deployment/test/jake2/">online</a>
+                                                        with <b>no manual installation</b> on all of JOGL's supported platforms.<br/>
+                                                    You can find the current source code in this
+                                                    <a href="http://jogamp.org/git/?p=users/sgothel/jake2.git;a=summary">git repository</a>.
+                                                </td>
+                                            </tr>
+                                        </tbody>
+                                    </table>
+                                </td>
+                            </tr>
+                            <tr>
+                                <th colspan="1"><a id="feat_old">Older projects ...</a></th>
+                            </tr>
+                            <tr>
+                                <td >
+                                    <table border="0" cellspacing="15">
+                                        <tbody>
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.fusion-laboratory.de/"><img
+                                                            src="media/fusion-laboratory.jpg" width="160" height="160" align="left"
+                                                            alt="Fusion Laboratory"></img>The Fusion Framework</a> enables Swing
+                                                    components to be extended with 3D content via JOGL. In general the 3D
+                                                    content will show up in layers on top of the corresponding Swing
+                                                    component. Many utility functions are integrated to help the developer
+                                                    build components. For example, the 3D content may be calibrated to the
+                                                    corresponding component's bounds. In addition, the system provides a
+                                                    simple scenegraph, Swing-like mouse interaction, and low-level
+                                                    animation support, as well as GLSL shaders and .obj file loading. The
+                                                    demo page contains several Java Web Start applications which
+                                                    demonstrate the abilities of the framework; please fill out the web
+                                                    form to help evaluate the components' usefulness.
+                                                </td>
+
+                                                <td width="50%">
+                                                    <a href="http://worldwind.arc.nasa.gov/java/"><img src="media/worldwind.jpg"
+                                                                                                        width="160" align="left" alt="World Wind"></img>NASA World Wind
+                                                        Java</a> provides next-generation 3-D virtual globe technology for
+                                                    applications written in the Java programming language. It supplies a
+                                                    suite of open-source components that developers include in their own
+                                                    applications, providing virtual globe functionality to any application
+                                                    that can benefit from it. World Wind Java's components perform as well
+                                                    as, or better than, any other known implementation and utilize the
+                                                    OpenGL API for 3-D graphics via JOGL. See WWJ Technical Lead Tom
+                                                    Gaskins' <a href="http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-3489&yr=2007&track=2">JavaOne
+                                                        2007</a> presentation on World Wind Java and the DiSTI Corporation's
+                                                    <a href="http://www.disti.com/Products/demonstrations/java.html">F-16 flight simulator</a>
+                                                    built using World Wind Java.
+                                                </td>
+                                            </tr>
+
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.artofillusion.org/"><img src="media/artofillusion.jpg" width="160" height="117" align="left" alt="Art Of Illusion"></img>
+                                                        Art of Illusion</a> is a free, open source 3D modelling and rendering
+                                                    studio. Many of its capabilities rival those found in commercial
+                                                    programs. Some of the highlights include subdivision surface based
+                                                    modelling tools, skeleton based animation, and a graphical language
+                                                    for designing procedural textures and materials. It uses JOGL for
+                                                    real-time OpenGL rendering in its modeling views.
+                                                </td>
+
+                                                <td width="50%">
+                                                    <a href="http://3d-alignment.eu"><img src="media/strap.jpg" width="160" height="118" align="left" alt="STRAP"></img></a>
+                                                    With <a href="http://3d-alignment.eu">STRAP</a> you can align your proteins by
+                                                    sequence and 3D-structure.  STRAP simultaneously displays
+                                                    3d-structures, amino acid sequence alignment and nucleotide sequences.
+                                                    It has powerful annotation features.
+                                                </td>
+                                            </tr>
+
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.sculpteo.com"><img src="media/sculpteo_3_robot_72dpi_sm.jpg" width="160" height="120" align="left" alt="Sculpteo"></img>
+                                                        Sculpteo</a> offers a 3D printing service, fast and available for everyone.
+                                                    Starting from a 3D design, Sculpteo makes a specific object : interior decoration, characters, robots, miniatures, models, mechanic objects...
+                                                </td>
+                                                <td width="50%">
+                                                    <a href="http://www.fenggui.org/"><img src="media/fenggui.jpg" width="160" height="127" align="left" alt="FengGUI"></img>
+                                                        FengGUI</a> is a graphical
+                                                    user interface (GUI) application programming interface (API) based on
+                                                    OpenGL. FengGUI provides all typical GUI components like buttons,
+                                                    sliders, trees, text areas, frames, tabs, etc. which are required to
+                                                    build a complete GUI system. Since it is based on OpenGL, FengGUI fits
+                                                    well in multimedia and game environments.
+                                                </td>
+                                            </tr>
+
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://mbt.sdsc.edu/"><img src="media/mbt.jpg" width="160" height="122" align="left" alt="Molecular Biology Toolkit"></img></a>The
+                                                    <a href="http://mbt.sdsc.edu/">Molecular Biology Toolkit</a> is a
+                                                    Java-based protein visualization and analysis toolkit. The toolkit
+                                                    provides classes for efficiently loading, managing and manipulating
+                                                    protein structure and sequence data. The MBT also provides a rich set
+                                                    of graphical 3D and 2D visualization components which can be easily
+                                                    "plugged together" to produce applications having sophisticated
+                                                    graphical user interfaces. Some MBT-based visualization tools are <a
+                                                        href="http://www.pdb.org/">ProteinWorkshop</a> (<a
+                                                        href="http://spdc.sdsc.edu/iedb/protein_workshop/viewer7.php">webstart
+                                                        demo</a>), <a href="http://www.immuneepitope.org/">EpitopeViewer</a>
+                                                    (<a href="http://spdc.sdsc.edu/iedb/epitopeViewer/viewer_jogl333.php">webstart demo</a>), and <a href="http://sirius.sdsc.edu/">Sirius</a>.
+                                                </td>
+
+                                                <td width="50%">
+                                                    <a href="http://impact.sourceforge.net/"><img src="media/impact.jpg" width="160" height="129" align="left" alt="Impact"></img>
+                                                        Impact</a> is a
+                                                    complete finite element suite including preprocessor, solver and
+                                                    postprocessor which is useable for simulating dynamic events such as
+                                                    car crashes or stamping of metal sheets. The suite allows 3D
+                                                    modelling, solving and viewing of simulation results, all in OpenGL
+                                                    accelerated graphics through the use of JOGL.
+                                                </td>
+                                            </tr>
+
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.insightmachines.com/en/vehicleDynamicsEngine.shtml">
+                                                        <img src="media/vehicle.jpg" width="160" height="160" align="left" alt="Vehicle Dynamics Engine Demo"></img>Vehicle Dynamics Engine Demo</a>
+                                                    is a Java Web Start demonstration of a 3D physics engine developed by
+                                                    <a href="http://www.insightmachines.com/">Insight Machines</a>. The
+                                                    engine is designed especially for car games. The demo uses JOGL and
+                                                    employs such techniques like shadow casting using the stencil buffer.
+                                                </td>
+
+                                                <td width="50%">
+
+                                                    <a href="http://chronotext.org/"><img src="media/chronotext.jpg" width="160" height="120" align="left" alt="chronotext"></img>
+                                                        chronotext</a> is a series
+                                                    of visual design experiments involving animated text and 3D objects
+                                                    and surfaces. Several examples can be run on-line via <a
+                                                        href="http://chronotext.org/scriptorium/behind/index.htm">Java Web
+                                                        Start</a>. See the <a href="http://www.chronotext.org/mapping/">latest
+                                                        experiments</a> of mapping text on to real 3D surfaces.
+                                                </td>
+                                            </tr>
+
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.avengina.org/"><img src="media/avengina.jpg" alt="Avengina" align="left" height="99" width="160"></img>Avengina</a> is a
+                                                    realtime 3D graphics engine which is designed for the execution as a
+                                                    Java applet. Alternatively it can be launched as a Java Webstart
+                                                    application outside the browserwindow. The software provides the
+                                                    possibility to exhibit texts and images in virtual
+                                                    galleries. Regarding the control and behaviour of the avatar it's
+                                                    redolent of a game engine. The graphics rendering system bases on
+                                                    per-pixel lighting and supports normal mapping, specular lighting and
+                                                    stencil volume shadows. Avengina uses JOGL for realtime rendering.
+                                                </td>
+
+                                                <td >
+                                                    <a href="http://netbeans-opengl-pack.dev.java.net/">
+                                                        <img src="media/NetBeansOpenGLPackLogo160.png" width="160" height="159" align="left" alt="NOGL Pack logo"></img>
+                                                        The NetBeans OpenGL Pack</a> provides an easy to use OpenGL development
+                                                    environment integrated into NetBeans. It supplies modules like an GLSL
+                                                    shader editor, hardware compiler/linker integration and tools for
+                                                    displaying hardware information. The pack ships ready to run JOGL (JSR
+                                                    231) demo projects and all OpenGL samples of the OpenGL Programming
+                                                    Guide (also known as the Red Book).
+                                                </td>
+                                            </tr>
+
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.nascar.com/trackpass/about/raceview/"><img src="media/raceview.jpg" width="160" height="92" align="left" alt="RaceView"></img>
+                                                        RaceView</a> from NASCAR / NEXTEL, part of the <a
+                                                        href="http://www.nascar.com/trackpass/">TrackPass</a> package, puts
+                                                    you in the race. Control the virtual camera angle, listen to the
+                                                    driver and team, and see crucial statistics and times, all in real
+                                                    time as the race goes on. RaceView uses JOGL for its 3D rendering.
+                                                </td>
+
+                                                <td width="50%">
+                                                </td>
+                                            </tr>
+
+                                        </tbody>
+                                    </table>
+                                </td>
+                            </tr>
+                            <tr>
+                                <th colspan="1">Discontinued projects</th>
+                            </tr>
+                            <tr>
+                                <td >
+                                    <table border="0" cellspacing="15">
+                                        <tbody>
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.specknet.org/dev/specksim"><img src="media/specksim.jpg" width="160" height="117" align="left" alt="SpeckSim"></img>
+                                                        SpeckSim</a> is a
+                                                    behaviour-level simulator for networks of small, resource-constrained
+                                                    devices with sensing, computation and communication
+                                                    capabilities. Intended as a testbed for distributed algorithms, the
+                                                    main design goal was ease of extension. To this end, almost all aspect
+                                                    of the simulator can be customised: Node behaviour, communication
+                                                    characteristics, placement and motion; visualisation rendering and
+                                                    interaction and statistic generation.
+                                                </td>
+                                                <td width="50%">
+                                                </td>
+                                            </tr>
+                                            <tr>
+                                                <td width="50%">
+                                                    <a href="http://www.madlix.com"><img src="media/madlix.png" width="160"
+                                                                                            height="160" align="left" alt="Madlix"></img>MADLIX</a> lets users insert
+                                                    3D-content in web pages, blogs, Google pages, community presentations
+                                                    and more. MADLIX is JOGL-powered and runs smoothly inside all
+                                                    Java-enabled browsers, with no need for custom plug-ins or application
+                                                    installation. The <a href="http://www.madlix.com">on-line gallery</a>
+                                                    features high-quality content ready for insertion. MADLIX is
+                                                    accompanied by the MADLIX exporter tool enabling 3D artists to
+                                                    directly export their 3D artwork from Autodesk Maya to the MADLIX
+                                                    gallery. The exporter features pre-view functionality as well as a
+                                                    standalone viewer, supporting the MADLIX file format and the open
+                                                    standard file format COLLADA.
+
+                                                </td>
+                                                <td width="50%">
+                                                    <a href="https://zg3d.dev.java.net/"><img src="media/zg3d.png" width="160" height="160" align="left" alt="ZG3D"></img>
+                                                        ZG3D</a> is an open source project that uses
+                                                    JOGL for visualizing 3D geometries with the emphasis of plotting
+                                                    scientific data in a web application. Geometry objects in an XML file
+                                                    or string can be dynamically loaded and removed. An HTML document may
+                                                    call ZG3D functions through JavaScript and may define JavaScript
+                                                    functions to receive messages from ZG3D, which makes it very easy and
+                                                    flexible to embed interactive 3D web visualization. The software is
+                                                    developed at the <a
+                                                        href="http://www-cger.nies.go.jp/index.html">Center for Global
+                                                        Environmental Research</a>, Japan, for the advanced data visualization
+                                                    of the <a href="http://db.cger.nies.go.jp/g3db/ggtu/trajectory.html">Global Greenhouse Gases Database</a>.
+                                                </td>
+                                            </tr>
+
+                                            <tr>
+                                                <td  width="50%">
+                                                    <a href="http://www.simulation.com/products/glstudio/glstudio.html"><img
+                                                            src="media/glstudio.jpg" width="160" height="135" align="left" alt="GL Studio"></img>
+                                                        GL Studio</a> is an object oriented rapid application
+                                                    development tool that allows a user to graphically combine
+                                                    photographs, 3D models and behavior logic to create advanced 2D and 3D
+                                                    human machine interfaces.  GL Studio generates Java or C++ source code
+                                                    which can then be integrated into the user’s application as a user
+                                                    interface. <a
+                                                        href="http://www.simulation.com/products/glstudio/java/java.html">Java
+                                                        code</a> generated with GL Studio can be deployed using
+                                                    javax.swing.JPanel, java.awt.Canvas and JavaBeans. GL Studio uses
+                                                    OpenGL for rendering and GL Studio for Java uses the JOGL API.
+
+                                                </td>
+
+                                                <td width="50%">
+                                                    <a href="http://www.vlsolutions.com/">
+                                                        <img src="media/vldocking.jpg" width="160" height="113" align="left" alt="VLDocking"></img>VLDocking</a> is
+                                                    a set of Java components that helps the Swing developer to build
+                                                    applications with Docking capabilities, and even raise existing
+                                                    applications to higher standards. It supports docking via drag and
+                                                    drop, enhanced toolbars, closable tabs, and more. It fully supports
+                                                    heavyweight components such as JOGL's GLCanvas in a docking
+                                                    environment.
+                                                </td>
+                                            </tr>
+
+                                            <!--- abandoned JOGL ..
+                                            <tr>
+                                                <td >
+                                                    <a href="http://openendedgroup.com/field"><img src="media/field.png"
+                                                                                                    width="160" height="159" align="left" alt="Field"></img>Field</a> is an
+                                                    open-source development environment for digital art and experimental
+                                                    code writing. Built around the needs of programmers that manipulate
+                                                    images, make animations and compose music, Field seeks to tie
+                                                    text-based programming with ad hoc visual metaphors. Field uses Python
+                                                    and other programming languages and wants to be integrated into your
+                                                    own personal code-base. And it comes with special support for the <a
+                                                        href="http://processing.org/">Processing</a> environment. Field uses
+                                                    JOGL for its UI and its built-in drawing system; it provides a
+                                                    JOGL-based scene-graph library for 3D visualization.
+                                                </td>
+                                            </tr>
+                                                <td width="50%">
+                                                    <a href="http://www.eclipse.org/gef3d/"><img src="http://wiki.eclipse.org/images/thumb/b/be/Gef3d_sample_ecore3D.png/800px-Gef3d_sample_ecore3D.png" width="160" height="94" align="left" alt="GEF3d"></img>
+                                                        GEF3D</a> is an Eclipse GEF extension bringing 3D to diagram editing.
+                                                    That is with GEF3D you can create 3D diagrams, 2D diagrams and combine
+                                                    3D with 2D diagrams. GEF3D extends GEF by providing 3D enabled draw and
+                                                    controller classes. Instead of drawing 2D figures, you can now draw 3D figures.
+                                                    Existing GEF-based 2D editors can be embedded into 3D editors with minimal effort.
+                                                </td>
+                                            -->
+
+                                        </tbody>
+                                    </table>
+                                </td>
+                            </tr>
                         </tbody>
                     </table>
                 </div>
diff --git a/www/media/Java3d.png b/www/media/Java3d.png
new file mode 100644
index 0000000..ea7ea1b
Binary files /dev/null and b/www/media/Java3d.png differ
diff --git a/www/media/ardor3d.png b/www/media/ardor3d.png
new file mode 100644
index 0000000..9be4474
Binary files /dev/null and b/www/media/ardor3d.png differ
diff --git a/www/media/dyn4j.png b/www/media/dyn4j.png
new file mode 100644
index 0000000..3fd7bf6
Binary files /dev/null and b/www/media/dyn4j.png differ
diff --git a/www/media/jmonkeyengine.png b/www/media/jmonkeyengine.png
new file mode 100644
index 0000000..a3e2a2a
Binary files /dev/null and b/www/media/jmonkeyengine.png differ
diff --git a/www/media/nifty-logo-new.png b/www/media/nifty-logo-new.png
new file mode 100644
index 0000000..c8390ce
Binary files /dev/null and b/www/media/nifty-logo-new.png differ
diff --git a/www/media/ticket2ride_picture4.jpg b/www/media/ticket2ride_picture4.jpg
new file mode 100644
index 0000000..e7d5737
Binary files /dev/null and b/www/media/ticket2ride_picture4.jpg differ

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/libjogl2-java.git



More information about the pkg-java-commits mailing list