[libjogl2-java] 53/58: Imported Upstream version 2.1.5

Tony Mancill tmancill at moszumanska.debian.org
Thu Sep 4 03:59:30 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 5698a919a8fabf1eed536ec27f5228c3fce3e5ef
Author: tony mancill <tmancill at debian.org>
Date:   Fri Aug 29 18:47:15 2014 -0700

    Imported Upstream version 2.1.5
---
 doc/HowToBuild.html                                |  13 +-
 doc/Platforms.txt                                  |  28 ++
 make/config/jogl/gl-common-gpubufferonly.cfg       |   1 +
 make/config/jogl/gl-common.cfg                     |   1 +
 .../jogl/gl4bc-common-cpubufferJavaCode.java       |   4 +
 make/config/jogl/glx-CustomCCode.c                 |  69 ++++-
 make/config/jogl/glx-CustomJavaCode.java           |  19 ++
 make/config/jogl/glx-x11.cfg                       |   2 +
 make/config/jogl/glxext.cfg                        |   2 +-
 make/scripts/make.jogl.all.macosx-clang.sh         |   1 +
 make/scripts/tests-win.bat                         |   6 +-
 make/scripts/tests-x64-dbg.bat                     |   5 +-
 make/scripts/tests.sh                              |  27 +-
 .../com/jogamp/graph/curve/opengl/RenderState.java |   6 +-
 .../com/jogamp/graph/curve/opengl/Renderer.java    |   8 +
 .../com/jogamp/opengl/util/GLDrawableUtil.java     |  21 ++
 .../com/jogamp/opengl/util/GLPixelBuffer.java      |  14 +-
 .../jogamp/opengl/util/GLPixelStorageModes.java    |  70 ++---
 .../com/jogamp/opengl/util/GLReadBufferUtil.java   |  35 ++-
 .../com/jogamp/opengl/util/PNGPixelRect.java       |  80 +++++-
 .../com/jogamp/opengl/util/TileRendererBase.java   |  15 +-
 .../com/jogamp/opengl/util/av/GLMediaPlayer.java   |   8 +-
 .../opengl/util/awt/AWTGLReadBufferUtil.java       |  46 +++-
 .../com/jogamp/opengl/util/texture/TextureIO.java  |  40 ++-
 .../opengl/util/texture/TextureSequence.java       |  12 +-
 src/jogl/classes/javax/media/opengl/GLBase.java    |  14 +-
 src/jogl/classes/javax/media/opengl/GLContext.java |  13 +-
 src/jogl/classes/javax/media/opengl/GLProfile.java | 141 +++++++---
 .../classes/javax/media/opengl/awt/GLCanvas.java   |   4 +-
 .../classes/javax/media/opengl/awt/GLJPanel.java   | 127 ++++++---
 .../jogamp/graph/curve/opengl/RenderStateImpl.java |   4 -
 .../jogamp/opengl/GLBufferObjectTracker.java       |   4 +-
 src/jogl/classes/jogamp/opengl/GLContextImpl.java  |  14 +-
 src/jogl/classes/jogamp/opengl/GLDrawableImpl.java |   4 +-
 .../classes/jogamp/opengl/GLFBODrawableImpl.java   |   4 +-
 src/jogl/classes/jogamp/opengl/GLStateTracker.java |  16 +-
 .../jogamp/opengl/openal/av/ALAudioSink.java       | 286 ++++++++++++++-------
 .../jogamp/opengl/util/av/GLMediaPlayerImpl.java   |   4 +-
 .../jogamp/opengl/util/av/impl/FFMPEGNatives.java  |  43 ++--
 .../opengl/util/av/impl/FFMPEGv08Natives.java      |  34 +--
 .../opengl/util/av/impl/FFMPEGv09Natives.java      |  34 +--
 .../opengl/util/av/impl/FFMPEGv10Natives.java      |  34 +--
 .../jogamp/opengl/util/jpeg/JPEGDecoder.java       | 167 +++++-------
 .../x11/glx/X11GLXGraphicsConfiguration.java       |  39 ++-
 .../glx/X11GLXGraphicsConfigurationFactory.java    |   8 +-
 src/jogl/native/libav/ffmpeg_impl_template.c       | 131 +++++++---
 src/jogl/native/libav/ffmpeg_tool.h                |   1 -
 .../com/jogamp/nativewindow/awt/JAWTWindow.java    |  49 ++--
 .../media/nativewindow/NativeWindowFactory.java    |  23 +-
 .../media/nativewindow/util/PixelFormatUtil.java   |   3 +-
 .../jogamp/nativewindow/SurfaceUpdatedHelper.java  |  25 +-
 .../classes/jogamp/nativewindow/awt/AWTMisc.java   |  19 +-
 .../classes/jogamp/nativewindow/jawt/JAWTUtil.java |  95 ++++---
 .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java |   4 +-
 .../classes/com/jogamp/newt/opengl/GLWindow.java   |  40 +--
 .../classes/com/jogamp/newt/swt/NewtCanvasSWT.java |  32 ++-
 src/newt/classes/jogamp/newt/DisplayImpl.java      |   3 +-
 src/newt/classes/jogamp/newt/WindowImpl.java       |  46 ++--
 src/newt/native/MacWindow.m                        |  20 +-
 .../opengl/test/android/MovieCubeActivity0.java    |  47 ++--
 .../test/junit/graph/TextRendererGLELBase.java     | 195 ++++++++++++++
 .../test/junit/jogl/acore/GLReadBuffer00Base.java  | 117 +++++++++
 .../jogl/acore/TestGLReadBuffer01GLCanvasAWT.java  | 252 ++++++++++++++++++
 .../jogl/acore/TestGLReadBuffer01GLJPanelAWT.java  | 254 ++++++++++++++++++
 .../jogl/acore/TestGLReadBuffer01GLWindowNEWT.java | 195 ++++++++++++++
 .../junit/jogl/acore/TestMapBufferRead01NEWT.java  |  82 ++++--
 .../jogl/demos/es2/TextureSequenceCubeES2.java     |   6 +-
 .../junit/jogl/demos/es2/av/CrossFadePlayer.java   | 211 +++++++++++++++
 .../test/junit/jogl/demos/es2/av/MovieCube.java    | 127 ++++++++-
 .../test/junit/jogl/demos/es2/av/MovieSimple.java  | 136 +++++++---
 .../junit/newt/parenting/TestParenting01NEWT.java  |  83 +++++-
 .../jogamp/opengl/test/junit/util/UITestCase.java  |  76 +++---
 72 files changed, 3008 insertions(+), 791 deletions(-)

diff --git a/doc/HowToBuild.html b/doc/HowToBuild.html
index 1cb3bad..8b5d27e 100644
--- a/doc/HowToBuild.html
+++ b/doc/HowToBuild.html
@@ -94,8 +94,19 @@
                                         <li>libxcursor-dev</li>
                                         <li>Optional: Your card vendor's proprietary driver</li>
                                     </ul>
+                                    One liner install command:
                                     <pre>
-apt-get install git gcc libgl1-mesa-dev libglu1-mesa-dev xorg-dev libice-dev libsm-dev libx11-dev libxext-dev libxxf86vm-dev libxinerama-dev libxrandr-dev libxrender-dev libxcursor-dev
+apt-get install git-all gcc libgl1-mesa-dev libglu1-mesa-dev xorg-dev libice-dev libsm-dev libx11-dev libxext-dev libxxf86vm-dev libxinerama-dev libxrandr-dev libxrender-dev libxcursor-dev libc6-dev g++ libstdc++6 libstdc++6-4.7-dev
+                                    </pre>
+                                    Optional: Add <i>kernel</i> build utilities:
+                                    <pre>
+apt-get install kernel-package build-essential 
+                                    </pre>
+                                    Optional: Add <i>multiarch</i> i386 next to amd64, requires Debian 7.00 or later:
+                                    <pre>
+dpkg --add-architecture i386
+apt-get update
+apt-get install ia32-libs ia32-libs-gtk gcc-multilib lib32gcc1 lib32gomp1 lib32itm1 lib32quadmath0 libc6-i386 libc6-dev-i386 g++-multilib lib32stdc++6
                                     </pre>
                                 </li>
                                 <li> <b>OpenSuSE</b> 10.2 or later
diff --git a/doc/Platforms.txt b/doc/Platforms.txt
index 7fbb65b..00200ae 100644
--- a/doc/Platforms.txt
+++ b/doc/Platforms.txt
@@ -60,3 +60,31 @@
             - PowerVR (ES2) 32bit only
 
 (*) Regular tested component / platform
+
+virtualbox-4.3_4.3.8-92456
+  - Host Debian 8 (Jessie)
+    - Host GPU: NV w/ NV proprietary driver
+
+  - Guest Debian 7 (Wheezy)
+    - Mesa 8.0.5 LLVM: 
+        - Onscreen: OK
+        - FBO: OK
+        - FBO.MSAA: NO (gl-error, failure)
+        - PBuffer: OK
+        - Bitmap: OK
+
+    - 3D Accel (Chromium 1.9): 
+        - Onscreen: OK
+        - FBO: NO
+        - FBO.MSAA: NO (gl-error, failure)
+        - PBuffer: NO
+        - Bitmap: NO
+
+  - Guest Debian 8 (Jessie)
+    - Mesa 9.2.2 Gallium LLVM
+        - Onscreen: OK
+        - FBO: OK
+        - FBO.MSAA: NO (properly reporting: N/A)
+        - PBuffer: OK
+        - Bitmap: OK
+
diff --git a/make/config/jogl/gl-common-gpubufferonly.cfg b/make/config/jogl/gl-common-gpubufferonly.cfg
index 14671f3..9370d95 100644
--- a/make/config/jogl/gl-common-gpubufferonly.cfg
+++ b/make/config/jogl/gl-common-gpubufferonly.cfg
@@ -44,6 +44,7 @@ BufferObjectOnly glDrawElementsInstancedBaseVertex
 BufferObjectOnly glDrawElementsInstancedBaseVertexBaseInstance
 BufferObjectOnly glDrawRangeElements
 BufferObjectOnly glDrawRangeElementsBaseVertex
+BufferObjectOnly glMultiDrawArraysIndirect
 
 BufferObjectOnly glDrawArraysIndirect
 BufferObjectOnly glDrawElementsIndirect
diff --git a/make/config/jogl/gl-common.cfg b/make/config/jogl/gl-common.cfg
index 74ead04..d5c4531 100644
--- a/make/config/jogl/gl-common.cfg
+++ b/make/config/jogl/gl-common.cfg
@@ -651,6 +651,7 @@ BufferObjectKind Element glDrawRangeElementsBaseVertex
 
 BufferObjectKind Indirect glDrawArraysIndirect
 BufferObjectKind Indirect glDrawElementsIndirect
+BufferObjectKind Indirect glMultiDrawArraysIndirect
 
 # There are no PBOs in the embedded OpenGL variants right now
 BufferObjectKind UnpackPixel glBitmap
diff --git a/make/config/jogl/gl4bc-common-cpubufferJavaCode.java b/make/config/jogl/gl4bc-common-cpubufferJavaCode.java
index a29f540..39dc9f6 100644
--- a/make/config/jogl/gl4bc-common-cpubufferJavaCode.java
+++ b/make/config/jogl/gl4bc-common-cpubufferJavaCode.java
@@ -7,6 +7,10 @@
       @param indirect a direct or array-backed {@link java.nio.Buffer}   */
   public void glDrawElementsIndirect(int mode, int type, Buffer indirect);
 
+  /** Entry point to C language function: <code> void {@native glMultiDrawArraysIndirect}(GLenum mode, const void *  indirect, GLsizei drawcount, GLsizei stride); </code> <br>Part of <code>GL_VERSION_4_3</code>, <code>GL_ARB_multi_draw_indirect</code>
+      @param indirect a direct or array-backed {@link java.nio.Buffer}   */
+  public void glMultiDrawArraysIndirect(int mode, Buffer indirect, int drawcount, int stride);
+
   /** Entry point to C language function: <code> void {@native glDrawElementsInstancedBaseInstance}(GLenum mode, GLsizei count, GLenum type, const void *  indices, GLsizei instancecount, GLuint baseinstance); </code> <br>Part of <code>GL_VERSION_4_2</code>, <code>GL_ARB_base_instance</code>
       @param indices a direct or array-backed {@link java.nio.Buffer}   */
   public void glDrawElementsInstancedBaseInstance(int mode, int count, int type, Buffer indices, int instancecount, int baseinstance);
diff --git a/make/config/jogl/glx-CustomCCode.c b/make/config/jogl/glx-CustomCCode.c
index 5c73dfe..b077c65 100644
--- a/make/config/jogl/glx-CustomCCode.c
+++ b/make/config/jogl/glx-CustomCCode.c
@@ -12,6 +12,8 @@
 #define RTLD_DEFAULT NULL
 #endif
 
+#include <string.h>
+
 /* We expect glXGetProcAddressARB to be defined */
 extern void (*glXGetProcAddressARB(const GLubyte *procname))();
 
@@ -124,7 +126,7 @@ Java_jogamp_opengl_x11_glx_GLX_dispatch_1glXChooseFBConfig(JNIEnv *env, jclass _
   int * _attribList_ptr = NULL;
   int * _nitems_ptr = NULL;
   GLXFBConfig *  _res;
-  int count;
+  int count, i;
   jobject jbyteSource;
   jobject jbyteCopy;
     if ( NULL != attribList ) {
@@ -139,6 +141,71 @@ Java_jogamp_opengl_x11_glx_GLX_dispatch_1glXChooseFBConfig(JNIEnv *env, jclass _
   count = _nitems_ptr[0];
   if (NULL == _res) return NULL;
 
+  /**
+   * Bug 961: Validate returned 'GLXFBConfig *', i.e. remove NULL pointer. 
+   * Note: sizeof(GLXFBConfig) == sizeof(void*), a.k.a a pointer
+   */
+  // fprintf(stderr, "glXChooseFBConfig.0: Count %d\n", count);
+  i=0;
+  while( i < count ) {
+    if( NULL == _res[i] ) {
+       if( 0 < count-i-1 ) {
+         memmove(_res+i, _res+i+1, (count-i-1)*sizeof(GLXFBConfig)); 
+       }
+       count--;
+    } else {
+       i++;
+    }
+  }
+  // fprintf(stderr, "glXChooseFBConfig.X: Count %d\n", count);
+  _initClazzAccess(env);
+
+  jbyteSource = (*env)->NewDirectByteBuffer(env, _res, count * sizeof(GLXFBConfig));
+  jbyteCopy   = (*env)->CallStaticObjectMethod(env, clazzBuffers, cstrBuffers, jbyteSource);
+  (*env)->DeleteLocalRef(env, jbyteSource);
+  XFree(_res);
+
+  return jbyteCopy;
+}
+
+/*   Java->C glue code:
+ *   Java package: jogamp.opengl.x11.glx.GLX
+ *    Java method: com.jogamp.common.nio.PointerBuffer dispatch_glXGetFBConfigs(long dpy, int screen, java.nio.IntBuffer nelements)
+ *     C function: GLXFBConfig *  glXGetFBConfigs(Display *  dpy, int screen, int *  nelements);
+ */
+JNIEXPORT jobject JNICALL 
+Java_jogamp_opengl_x11_glx_GLX_dispatch_1glXGetFBConfigs(JNIEnv *env, jclass _unused, jlong dpy, jint screen, jobject nelements, jint nelements_byte_offset, jlong procAddress) {
+  typedef GLXFBConfig *  (APIENTRY*_local_PFNGLXGETFBCONFIGSPROC)(Display *  dpy, int screen, int *  nelements);
+  _local_PFNGLXGETFBCONFIGSPROC ptr_glXGetFBConfigs;
+  int * _nelements_ptr = NULL;
+  GLXFBConfig *  _res;
+  int count, i;
+  jobject jbyteSource;
+  jobject jbyteCopy;
+    if ( NULL != nelements ) {
+        _nelements_ptr = (int *) (((char*) (*env)->GetDirectBufferAddress(env, nelements)) + nelements_byte_offset);
+    }
+  ptr_glXGetFBConfigs = (_local_PFNGLXGETFBCONFIGSPROC) (intptr_t) procAddress;
+  assert(ptr_glXGetFBConfigs != NULL);
+  _res = (* ptr_glXGetFBConfigs) ((Display *) (intptr_t) dpy, (int) screen, (int *) _nelements_ptr);
+  count = _nelements_ptr[0];
+  if (NULL == _res) return NULL;
+
+  /**
+   * Bug 961: Validate returned 'GLXFBConfig *', i.e. remove NULL pointer. 
+   * Note: sizeof(GLXFBConfig) == sizeof(void*), a.k.a a pointer
+   */
+  i=0;
+  while( i < count ) {
+    if( NULL == _res[i] ) {
+       if( 0 < count-i-1 ) {
+         memmove(_res+i, _res+i+1, (count-i-1)*sizeof(GLXFBConfig));
+       }
+       count--;
+    } else {
+       i++;
+    }
+  }
   _initClazzAccess(env);
 
   jbyteSource = (*env)->NewDirectByteBuffer(env, _res, count * sizeof(GLXFBConfig));
diff --git a/make/config/jogl/glx-CustomJavaCode.java b/make/config/jogl/glx-CustomJavaCode.java
index 4cce05d..5a3ea39 100644
--- a/make/config/jogl/glx-CustomJavaCode.java
+++ b/make/config/jogl/glx-CustomJavaCode.java
@@ -60,6 +60,25 @@
       @param nitems a direct only {@link java.nio.IntBuffer}   */
   private static native ByteBuffer dispatch_glXChooseFBConfig(long dpy, int screen, Object attribList, int attribList_byte_offset, Object nitems, int nitems_byte_offset, long procAddress);
 
+  /** Entry point to C language function: <code> GLXFBConfig *  glXGetFBConfigs(Display *  dpy, int screen, int *  nelements); </code> <br>Part of <code>GLX_VERSION_1_3</code>
+      @param nelements a direct only {@link java.nio.IntBuffer}   */
+  public static PointerBuffer glXGetFBConfigs(long dpy, int screen, IntBuffer nelements)  {
+
+    if (!Buffers.isDirect(nelements))
+      throw new GLException("Argument \"nelements\" is not a direct buffer");
+    final long __addr_ = glxProcAddressTable._addressof_glXGetFBConfigs;
+    if (__addr_ == 0) {
+      throw new GLException(String.format("Method \"%s\" not available", "glXGetFBConfigs"));
+    }
+    final ByteBuffer _res = dispatch_glXGetFBConfigs(dpy, screen, nelements, Buffers.getDirectBufferByteOffset(nelements), __addr_);
+    if (_res == null) return null;
+    return PointerBuffer.wrap(Buffers.nativeOrder(_res));
+  }
+
+  /** Entry point to C language function: <code> GLXFBConfig *  glXGetFBConfigs(Display *  dpy, int screen, int *  nelements); </code> <br>Part of <code>GLX_VERSION_1_3</code>
+      @param nelements a direct only {@link java.nio.IntBuffer}   */
+  private static native ByteBuffer dispatch_glXGetFBConfigs(long dpy, int screen, Object nelements, int nelements_byte_offset, long procAddress);
+
 
   /** Entry point to C language function: <code> XVisualInfo *  glXChooseVisual(Display *  dpy, int screen, int *  attribList); </code> <br>Part of <code>GLX_VERSION_1_X</code>
       @param attribList a direct only {@link java.nio.IntBuffer}   */
diff --git a/make/config/jogl/glx-x11.cfg b/make/config/jogl/glx-x11.cfg
index 5955e0a..1c138c8 100644
--- a/make/config/jogl/glx-x11.cfg
+++ b/make/config/jogl/glx-x11.cfg
@@ -44,9 +44,11 @@ Ignore glXCreateContextAttribsARB
 Ignore glXGetVisualFromFBConfigSGIX
 ManuallyImplement glXGetVisualFromFBConfig
 ManuallyImplement glXChooseFBConfig
+ManuallyImplement glXGetFBConfigs
 ManuallyImplement glXChooseVisual
 ForceProcAddressGen glXGetVisualFromFBConfig
 ForceProcAddressGen glXChooseFBConfig
+ForceProcAddressGen glXGetFBConfigs
 ForceProcAddressGen glXChooseVisual
 
 # Ignore everything not in the GLX core (up through GLX 1.4)
diff --git a/make/config/jogl/glxext.cfg b/make/config/jogl/glxext.cfg
index c73753e..d158d24 100644
--- a/make/config/jogl/glxext.cfg
+++ b/make/config/jogl/glxext.cfg
@@ -60,6 +60,7 @@ CustomJavaCode GLXExtImpl  private X11GLXContext _context;
 Ignore glXGetVisualFromFBConfig
 Ignore glXGetVisualFromFBConfigSGIX
 Ignore glXChooseFBConfig
+Ignore glXGetFBConfigs
 Ignore glXChooseVisual
 Ignore glXCreateContext
 Ignore glXDestroyContext
@@ -81,7 +82,6 @@ Ignore glXQueryExtensionsString
 Ignore glXQueryServerString
 Ignore glXGetClientString
 Ignore glXGetCurrentDisplay
-Ignore glXChooseFBConfig
 Ignore glXGetFBConfigAttrib
 Ignore glXGetFBConfigs
 Ignore glXGetVisualFromFBConfig
diff --git a/make/scripts/make.jogl.all.macosx-clang.sh b/make/scripts/make.jogl.all.macosx-clang.sh
index b5f21c9..6b25396 100755
--- a/make/scripts/make.jogl.all.macosx-clang.sh
+++ b/make/scripts/make.jogl.all.macosx-clang.sh
@@ -25,5 +25,6 @@ export GLUEGEN_PROPERTIES_FILE="../../gluegen/make/lib/gluegen-xcode_clang.prope
 export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
 
 ant \
+    -Dc.compiler.debug=true \
     -Drootrel.build=build-macosx \
     $* 2>&1 | tee make.jogl.all.macosx.log
diff --git a/make/scripts/tests-win.bat b/make/scripts/tests-win.bat
index 5642cca..df5ec49 100755
--- a/make/scripts/tests-win.bat
+++ b/make/scripts/tests-win.bat
@@ -50,7 +50,7 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedConte
 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT0 %*
 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT1 %*
 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT2 %*
-scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT3 %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT3 %*
 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2AWT3 %*
 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2AWT3b %*
 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextWithJTabbedPaneAWT %*
@@ -97,6 +97,9 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.anim.TestAnimat
 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.anim.TestAWTCardLayoutAnimatorStartStopBug532 %*
 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.anim.Bug898AnimatorFromEDTAWT %*
 
+scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLJPanelAWT %*
+REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLWindowNEWT %*
+
 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 %*
@@ -107,6 +110,7 @@ REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayout
 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.awt.TestGLJPanelResize01AWT %*
 
 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
diff --git a/make/scripts/tests-x64-dbg.bat b/make/scripts/tests-x64-dbg.bat
index ce2df92..b3ebc03 100755
--- a/make/scripts/tests-x64-dbg.bat
+++ b/make/scripts/tests-x64-dbg.bat
@@ -55,7 +55,7 @@ REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLC
 REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.GLJPanel" "-Djogl.debug.TileRenderer" "-Djogl.debug.TileRenderer.PNG"
 REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.GLJPanel" "-Djogl.debug.TileRenderer"
 REM set D_ARGS="-Djogl.gljpanel.noverticalflip"
-set D_ARGS="-Dnewt.debug=all"
+REM set D_ARGS="-Dnewt.debug=all"
 REM set D_ARGS="-Dnewt.debug.Window"
 REM set D_ARGS="-Dnewt.debug.Window.KeyEvent"
 REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Window.KeyEvent" "-Dnewt.debug.EDT"
@@ -74,6 +74,9 @@ REM set D_ARGS="-Dnewt.debug.Screen"
 REM set D_ARGS="-Dnewt.debug.Screen" "-Dnewt.debug.Window"
 REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" "-Dnewt.test.Window.reparent.incompatible=true"
 
+REM set D_ARGS="-Djogamp.debug.ReflectionUtil" "-Djogamp.debug.ReflectionUtil.forNameStats"
+REM set D_ARGS="-Djogamp.debug.ReflectionUtil.forNameStats"
+
 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"
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 85eb142..18f488b 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -63,6 +63,14 @@ fi
 #export INTEL_DEBUG="buf bat"
 #export INTEL_STRICT_CONFORMANCE=1 
 
+# export ALSOFT_LOGLEVEL=[0..4]
+# export ALSOFT_LOGLEVEL=3
+# export ALSOFT_LOGLEVEL=3
+#export ALSOFT_TRAP_ERROR=true
+#export ALSOFT_TRAP_AL_ERROR=true
+#export ALSOFT_TRAP_ALC_ERROR=true
+#export ALSOFT_LOGFILE=openal-soft.log
+
 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
@@ -96,6 +104,9 @@ function jrun() {
     #D_ARGS="-Dnativewindow.debug=all -Dnewt.debug.Window"
     #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock"
 
+    #D_ARGS="-Djogamp.debug.ReflectionUtil -Djogamp.debug.ReflectionUtil.forNameStats"
+    #D_ARGS="-Djogamp.debug.ReflectionUtil.forNameStats"
+
     #D_ARGS="-Dnativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG"
     #D_ARGS="-Dnativewindow.debug.X11Util.ATI_HAS_NO_MULTITHREADING_BUG"
     #D_ARGS="-Djogl.disable.opengles"
@@ -206,6 +217,7 @@ function jrun() {
     #D_ARGS="-Dnewt.debug.Window"
     #D_ARGS="-Xprof"
     #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel"
+    #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel -Djogl.debug.GLJPanel.Viewport"
     #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel -Djogl.gljpanel.noglsl"
     #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel -Djogl.gljpanel.noglsl -Djogl.gljpanel.awtverticalflip"
     #D_ARGS="-Djogl.debug.GLJPanel -Djogl.debug.DebugGL"
@@ -216,6 +228,7 @@ function jrun() {
     #D_ARGS="-Dnativewindow.debug.NativeWindow"
     #D_ARGS="-Dnativewindow.osx.calayer.bugfree"
     #D_ARGS="-Dnativewindow.debug.ToolkitLock"
+    #D_ARGS="-Djogl.debug.graph.curve"
     #D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLCode -Djogl.debug.TraceGL"
     #D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLState"
     #D_ARGS="-Djogamp.debug.TempJarCache -Djogamp.debug.JarUtil -Djogamp.debug.IOUtil"
@@ -232,7 +245,7 @@ function jrun() {
     #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer -Djogl.debug.TileRenderer.PNG"
     #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer"
     #D_ARGS="-Djogl.debug.PNG -Dnewt.debug.Display.PointerIcon"
-    #D_ARGS="-Djogl.debug.JPEGImage"
+    #D_ARGS="-Djogl.debug.JPEGImage -Djogamp.debug.Bitstream"
     #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"
@@ -240,9 +253,10 @@ function jrun() {
     #X_ARGS="-Xrs"
     #X_ARGS="-Dsun.awt.disableMixing=true"
     #D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer"
-    #D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.AudioSink"
+    #D_ARGS="-Djogl.debug.AudioSink"
+    #D_ARGS="-Djogl.debug.AudioSink.trace"
     #D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.GLMediaPlayer.Native"
-    D_ARGS="-Djogl.debug.GLMediaPlayer"
+    #D_ARGS="-Djogl.debug.GLMediaPlayer"
     #D_ARGS="-Djogl.debug.GLMediaPlayer.StreamWorker.delay=25 -Djogl.debug.GLMediaPlayer"
     #D_ARGS="-Djogl.debug.GLMediaPlayer.Native"
 
@@ -355,7 +369,8 @@ function testawtswt() {
 #
 #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 $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.CrossFadePlayer $*
 
 #
 # performance tests
@@ -482,6 +497,10 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.anim.TestAnimatorGLJPanel01AWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.acore.anim.Bug898AnimatorFromEDTAWT $*
 
+#testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLJPanelAWT $*
+testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLCanvasAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLWindowNEWT $*
+
 #
 # NEWT
 #
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
index 6a8fb6a..9b0f32e 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java
@@ -42,7 +42,7 @@ public abstract class RenderState {
     private static final String thisKey = "jogamp.graph.curve.RenderState" ;
 
     public static RenderState createRenderState(ShaderState st, Vertex.Factory<? extends Vertex> pointFactory) {
-        return new RenderStateImpl(st, pointFactory);
+        return new RenderStateImpl(st, pointFactory, null);
     }
 
     public static RenderState createRenderState(ShaderState st, Vertex.Factory<? extends Vertex> pointFactory, PMVMatrix pmvMatrix) {
@@ -61,8 +61,8 @@ public abstract class RenderState {
     protected RenderState(ShaderState st, Vertex.Factory<? extends Vertex> vertexFactory, PMVMatrix pmvMatrix) {
         this.st = st;
         this.vertexFactory = vertexFactory;
-        this.pmvMatrix = pmvMatrix;
-        this.gcu_PMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, pmvMatrix.glGetPMvMatrixf());
+        this.pmvMatrix = null != pmvMatrix ? pmvMatrix : new PMVMatrix();
+        this.gcu_PMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, this.pmvMatrix.glGetPMvMatrixf());
         st.ownUniform(gcu_PMVMatrix);
     }
 
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 8783906..0292866 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
@@ -241,6 +241,14 @@ public abstract class Renderer {
         }
     }
 
+    /** No PMVMatrix operation is performed here. PMVMatrix will be updated if gl is not null. */
+    public boolean reshapeNotify(GL2ES2 gl, int width, int height) {
+        this.vp_width = width;
+        this.vp_height = height;
+        updateMatrix(gl);
+        return true;
+    }
+
     public boolean reshapePerspective(GL2ES2 gl, float angle, int width, int height, float near, float far) {
         this.vp_width = width;
         this.vp_height = height;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
index ec6d54d..cf88e7b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
@@ -30,6 +30,8 @@ package com.jogamp.opengl.util;
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.opengl.GLAnimatorControl;
 import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLBase;
+import javax.media.opengl.GLCapabilitiesImmutable;
 import javax.media.opengl.GLContext;
 import javax.media.opengl.GLDrawable;
 import javax.media.opengl.GLEventListener;
@@ -168,4 +170,23 @@ public class GLDrawableUtil {
     if(bIsPaused) { bAnim.resume(); }
   }
 
+  /**
+   * Determines whether the chosen {@link GLCapabilitiesImmutable}
+   * requires a {@link GLDrawable#swapBuffers() swap-buffers}
+   * before reading pixels.
+   * <p>
+   * Usually one uses the {@link GLBase#getDefaultReadBuffer() default-read-buffer}
+   * in which case {@link GLDrawable#swapBuffers() swap-buffers} shall happen <b>after</b> calling reading pixels, the default.
+   * </p>
+   * <p>
+   * However, <i>multisampling</i> offscreen {@link javax.media.opengl.GLFBODrawable}s
+   * utilize {@link GLDrawable#swapBuffers() swap-buffers} to <i>downsample</i>
+   * the multisamples into the readable sampling sink.
+   * In this case, we require {@link GLDrawable#swapBuffers() swap-buffers} <b>before</b> reading pixels.
+   * </p>
+   * @return chosenCaps.isFBO() && chosenCaps.getSampleBuffers()
+   */
+  public static final boolean swapBuffersBeforeRead(final GLCapabilitiesImmutable chosenCaps) {
+      return chosenCaps.isFBO() && chosenCaps.getSampleBuffers();
+  }
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
index a921a28..223c23e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
@@ -324,9 +324,19 @@ public class GLPixelBuffer {
 
     /** The {@link GLPixelAttributes}. */
     public final GLPixelAttributes pixelAttributes;
-    /** Width in pixels. */
+    /**
+     * Width in pixels, representing {@link #buffer}'s {@link #byteSize}.
+     * <p>
+     * May not represent actual image width as user may re-use buffer for different dimensions, see {@link #requiresNewBuffer(GL, int, int, int)}.
+     * </p>
+     */
     public final int width;
-    /** Height in pixels. */
+    /**
+     * Height in pixels, representing {@link #buffer}'s {@link #byteSize}.
+     * <p>
+     * May not represent actual image height as user may re-use buffer for different dimensions, see {@link #requiresNewBuffer(GL, int, int, int)}.
+     * </p>
+     */
     public final int height;
     /** Depth in pixels. */
     public final int depth;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
index 1c6e974..b6cff85 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelStorageModes.java
@@ -40,8 +40,8 @@ import javax.media.opengl.GLException;
  * regardless of the GLProfile.
  */
 public class GLPixelStorageModes {
-    private int[] savedGL2GL3Modes = new int[8];
-    private int[] savedAlignment = new int[2];
+    private final int[] savedGL2GL3Modes = new int[8];
+    private final int[] savedAlignment = new int[2];
     private boolean saved = false;
 
     /** Create instance w/o {@link #save(GL)} */
@@ -127,31 +127,35 @@ public class GLPixelStorageModes {
             return;
         }
 
-        if(gl.isGL2GL3()) {
-            if(gl.isGL2()) {
+        if( gl.isGL2ES3() ) {
+            if( gl.isGL2() ) {
                 gl.getGL2().glPushClientAttrib(GL2.GL_CLIENT_PIXEL_STORE_BIT);
             } else {
                 gl.glGetIntegerv(GL2ES2.GL_PACK_ALIGNMENT,     savedAlignment,   0);
                 gl.glGetIntegerv(GL2ES2.GL_UNPACK_ALIGNMENT,   savedAlignment,   1);
-                gl.glGetIntegerv(GL2GL3.GL_PACK_ROW_LENGTH,    savedGL2GL3Modes, 0);
-                gl.glGetIntegerv(GL2GL3.GL_PACK_SKIP_ROWS,     savedGL2GL3Modes, 1);
-                gl.glGetIntegerv(GL2GL3.GL_PACK_SKIP_PIXELS,   savedGL2GL3Modes, 2);
-                gl.glGetIntegerv(GL2GL3.GL_PACK_SWAP_BYTES,    savedGL2GL3Modes, 3);
-                gl.glGetIntegerv(GL2GL3.GL_UNPACK_ROW_LENGTH,  savedGL2GL3Modes, 4);
-                gl.glGetIntegerv(GL2GL3.GL_UNPACK_SKIP_ROWS,   savedGL2GL3Modes, 5);
-                gl.glGetIntegerv(GL2GL3.GL_UNPACK_SKIP_PIXELS, savedGL2GL3Modes, 6);
-                gl.glGetIntegerv(GL2GL3.GL_UNPACK_SWAP_BYTES,  savedGL2GL3Modes, 7);
+                gl.glGetIntegerv(GL2ES3.GL_PACK_ROW_LENGTH,    savedGL2GL3Modes, 0);
+                gl.glGetIntegerv(GL2ES3.GL_PACK_SKIP_ROWS,     savedGL2GL3Modes, 1);
+                gl.glGetIntegerv(GL2ES3.GL_PACK_SKIP_PIXELS,   savedGL2GL3Modes, 2);
+                gl.glGetIntegerv(GL2ES2.GL_UNPACK_ROW_LENGTH,  savedGL2GL3Modes, 4);
+                gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_ROWS,   savedGL2GL3Modes, 5);
+                gl.glGetIntegerv(GL2ES2.GL_UNPACK_SKIP_PIXELS, savedGL2GL3Modes, 6);
+                if( gl.isGL2GL3() ) {
+                    gl.glGetIntegerv(GL2GL3.GL_PACK_SWAP_BYTES,    savedGL2GL3Modes, 3);
+                    gl.glGetIntegerv(GL2GL3.GL_UNPACK_SWAP_BYTES,  savedGL2GL3Modes, 7);
+                }
+            }
+            gl.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, 0);
+            gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_ROWS, 0);
+            gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_PIXELS, 0);
+            gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH, 0);
+            gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS, 0);
+            gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, 0);
+            if( gl.isGL2GL3() ) {
+                gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, 0);
+                gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, 0);
             }
-            gl.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, 0);
-            gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_ROWS, 0);
-            gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_PIXELS, 0);
-            gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES, 0);
-            gl.glPixelStorei(GL2GL3.GL_UNPACK_ROW_LENGTH, 0);
-            gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_ROWS, 0);
-            gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_PIXELS, 0);
-            gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES, 0);
         } else {
-            // embedded deals with pack/unpack alignment only
+            // ES1 or ES2 deals with pack/unpack alignment only
             gl.glGetIntegerv(GL2ES2.GL_PACK_ALIGNMENT,   savedAlignment, 0);
             gl.glGetIntegerv(GL2ES2.GL_UNPACK_ALIGNMENT, savedAlignment, 1);
         }
@@ -167,23 +171,25 @@ public class GLPixelStorageModes {
             throw new GLException("pixel storage modes not saved");
         }
 
-        if(gl.isGL2GL3()) {
-            if(gl.isGL2()) {
+        if( gl.isGL2ES3() ) {
+            if( gl.isGL2() ) {
                 gl.getGL2().glPopClientAttrib();
             } else {
                 gl.glPixelStorei(GL2ES2.GL_PACK_ALIGNMENT,     savedAlignment[0]);
                 gl.glPixelStorei(GL2ES2.GL_UNPACK_ALIGNMENT,   savedAlignment[1]);
-                gl.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH,    savedGL2GL3Modes[0]);
-                gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_ROWS,     savedGL2GL3Modes[1]);
-                gl.glPixelStorei(GL2GL3.GL_PACK_SKIP_PIXELS,   savedGL2GL3Modes[2]);
-                gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES,    savedGL2GL3Modes[3]);
-                gl.glPixelStorei(GL2GL3.GL_UNPACK_ROW_LENGTH,  savedGL2GL3Modes[4]);
-                gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_ROWS,   savedGL2GL3Modes[5]);
-                gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_PIXELS, savedGL2GL3Modes[6]);
-                gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES,  savedGL2GL3Modes[7]);
+                gl.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH,    savedGL2GL3Modes[0]);
+                gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_ROWS,     savedGL2GL3Modes[1]);
+                gl.glPixelStorei(GL2ES3.GL_PACK_SKIP_PIXELS,   savedGL2GL3Modes[2]);
+                gl.glPixelStorei(GL2ES2.GL_UNPACK_ROW_LENGTH,  savedGL2GL3Modes[4]);
+                gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_ROWS,   savedGL2GL3Modes[5]);
+                gl.glPixelStorei(GL2ES2.GL_UNPACK_SKIP_PIXELS, savedGL2GL3Modes[6]);
+                if( gl.isGL2GL3() ) {
+                    gl.glPixelStorei(GL2GL3.GL_PACK_SWAP_BYTES,    savedGL2GL3Modes[3]);
+                    gl.glPixelStorei(GL2GL3.GL_UNPACK_SWAP_BYTES,  savedGL2GL3Modes[7]);
+                }
             }
         } else {
-            // embedded deals with pack/unpack alignment only
+            // ES1 or ES2 deals with pack/unpack alignment only
             gl.glPixelStorei(GL2ES2.GL_PACK_ALIGNMENT,   savedAlignment[0]);
             gl.glPixelStorei(GL2ES2.GL_UNPACK_ALIGNMENT, savedAlignment[1]);
         }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index b942c9a..25a012b 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -32,6 +32,7 @@ import java.io.File;
 import java.io.IOException;
 
 import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES3;
 import javax.media.opengl.GL2GL3;
 import javax.media.opengl.GLAutoDrawable;
 import javax.media.opengl.GLDrawable;
@@ -151,17 +152,6 @@ public class GLReadBufferUtil {
      * @see #GLReadBufferUtil(boolean, boolean)
      */
     public boolean readPixels(GL gl, int inX, int inY, int inWidth, int inHeight, 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 width, height;
         if( 0 >= inWidth || drawable.getWidth() < inWidth ) {
@@ -174,6 +164,23 @@ public class GLReadBufferUtil {
         } else {
             height= inHeight;
         }
+        return readPixelsImpl(drawable, gl, inX, inY, width, height, mustFlipVertically);
+    }
+
+    protected boolean readPixelsImpl(final GLDrawable drawable, final GL gl,
+                                     final int inX, final int inY, final int width, final int height,
+                                     final 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 boolean flipVertically;
         if( drawable.isGLOriented() ) {
@@ -215,8 +222,10 @@ public class GLReadBufferUtil {
         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);
+            if(gl.isGL2ES3()) {
+                final GL2ES3 gl2es3 = gl.getGL2ES3();
+                gl2es3.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, width);
+                gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
             }
             readPixelBuffer.clear();
             try {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
index 1bbc12f..fd8f541 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
@@ -32,6 +32,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
 
 import javax.media.nativewindow.util.Dimension;
 import javax.media.nativewindow.util.DimensionImmutable;
@@ -248,19 +249,29 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
         }
         return dOff;
     }
-    private int setPixelRGBA8(final ImageLine line, final int lineOff, final ByteBuffer d, final int dOff, final int bytesPerPixel, final boolean hasAlpha) {
+    private int setPixelRGBA8(final ImageLine line, final int lineOff, final ByteBuffer src, final int srcOff, final int bytesPerPixel, final boolean hasAlpha) {
         final int b = hasAlpha ? 4-1 : 3-1;
-        if( d.limit() <= dOff + b ) {
-            throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+dOff+".."+(dOff+b)+"]: "+d);
+        if( src.limit() <= srcOff + b ) {
+            throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+srcOff+".."+(srcOff+b)+"]: "+src);
         }
-        final int p = PixelFormatUtil.convertToInt32(hasAlpha ? PixelFormat.RGBA8888 : PixelFormat.RGB888, pixelformat, d, dOff);
+        final int p = PixelFormatUtil.convertToInt32(hasAlpha ? PixelFormat.RGBA8888 : PixelFormat.RGB888, pixelformat, src, srcOff);
+        line.scanline[lineOff    ] = 0xff &   p;              // R
+        line.scanline[lineOff + 1] = 0xff & ( p >>> 8 );      // G
+        line.scanline[lineOff + 2] = 0xff & ( p >>> 16 );     // B
+        if(hasAlpha) {
+            line.scanline[lineOff + 3] = 0xff & ( p >>> 24 ); // A
+        }
+        return srcOff + pixelformat.bytesPerPixel();
+    }
+
+    private static void setPixelRGBA8(final PixelFormat pixelformat, final ImageLine line, final int lineOff, final int srcPix, final int bytesPerPixel, final boolean hasAlpha) {
+        final int p = PixelFormatUtil.convertToInt32(hasAlpha ? PixelFormat.RGBA8888 : PixelFormat.RGB888, pixelformat, srcPix);
         line.scanline[lineOff    ] = 0xff &   p;              // R
         line.scanline[lineOff + 1] = 0xff & ( p >>> 8 );      // G
         line.scanline[lineOff + 2] = 0xff & ( p >>> 16 );     // B
         if(hasAlpha) {
             line.scanline[lineOff + 3] = 0xff & ( p >>> 24 ); // A
         }
-        return dOff + pixelformat.bytesPerPixel();
     }
 
     /**
@@ -304,9 +315,8 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
             final PngWriter png = new PngWriter(outstream, imi);
             // add some optional metadata (chunks)
             png.getMetadata().setDpi(dpi[0], dpi[1]);
-            png.getMetadata().setTimeNow(0); // 0 seconds fron now = now
+            png.getMetadata().setTimeNow(0); // 0 seconds from now = now
             png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGPixelRect");
-            // png.getMetadata().setText("my key", "my text");
             final boolean hasAlpha = 4 == bytesPerPixel;
 
             final ImageLine l1 = new ImageLine(imi);
@@ -332,4 +342,60 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
             }
         }
     }
+
+    public static void write(final PixelFormat pixelformat, final DimensionImmutable size,
+                             int strideInPixels, final boolean isGLOriented, final IntBuffer pixels,
+                             final double dpiX, final double dpiY,
+                             final OutputStream outstream, final boolean closeOutstream) throws IOException {
+        final int width = size.getWidth();
+        final int height = size.getHeight();
+        final int bytesPerPixel = pixelformat.bytesPerPixel();
+        final ImageInfo imi = new ImageInfo(width, height, 8 /* bitdepth */,
+                                            (4 == bytesPerPixel) ? true : false /* alpha */,
+                                            (1 == bytesPerPixel) ? true : false /* grayscale */,
+                                            false /* indexed */);
+        if( 0 != strideInPixels ) {
+            if( strideInPixels < size.getWidth()) {
+                throw new IllegalArgumentException("Invalid stride "+bytesPerPixel+", must be greater than width "+size.getWidth());
+            }
+        } else {
+            strideInPixels = size.getWidth();
+        }
+        final int reqPixels = strideInPixels * size.getHeight();
+        if( pixels.limit() < reqPixels ) {
+            throw new IndexOutOfBoundsException("Dest buffer has insufficient pixels left, needs "+reqPixels+": "+pixels);
+        }
+
+        // open image for writing to a output stream
+        try {
+            final PngWriter png = new PngWriter(outstream, imi);
+            // add some optional metadata (chunks)
+            png.getMetadata().setDpi(dpiX, dpiY);
+            png.getMetadata().setTimeNow(0); // 0 seconds from now = now
+            png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGPixelRect");
+            final boolean hasAlpha = 4 == bytesPerPixel;
+
+            final ImageLine l1 = new ImageLine(imi);
+            for (int row = 0; row < height; row++) {
+                int dataOff = isGLOriented ? ( height - 1 - row ) * strideInPixels : row * strideInPixels;
+                int lineOff = 0;
+                if(1 == bytesPerPixel) {
+                    for (int j = width - 1; j >= 0; j--) {
+                        l1.scanline[lineOff++] = pixels.get(dataOff++); // // Luminance, 1 bytesPerPixel
+                    }
+                } else {
+                    for (int j = width - 1; j >= 0; j--) {
+                        setPixelRGBA8(pixelformat, l1, lineOff, pixels.get(dataOff++), bytesPerPixel, hasAlpha);
+                        lineOff += bytesPerPixel;
+                    }
+                }
+                png.writeRow(l1, row);
+            }
+            png.end();
+        } finally {
+            if( closeOutstream ) {
+                IOUtil.close(outstream, false);
+            }
+        }
+    }
 }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
index 22f5c01..dabde83 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
@@ -412,22 +412,11 @@ public abstract class TileRendererBase {
      * requires a <i>pre-{@link GLDrawable#swapBuffers() swap-buffers}</i>
      * before accessing the results, i.e. before {@link #endTile(GL)}.
      * <p>
-     * Usually one uses the {@link GL#getDefaultReadBuffer() default-read-buffer}, i.e.
-     * {@link GL#GL_FRONT} for single-buffer and {@link GL#GL_BACK} for double-buffer {@link GLDrawable}s
-     * and {@link GL#GL_COLOR_ATTACHMENT0} for offscreen framebuffer objects.<br>
-     * Here {@link GLDrawable#swapBuffers() swap-buffers} shall happen <b>after</b> calling {@link #endTile(GL)}, the default.
+     * See {@link GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable)}.
      * </p>
-     * <p>
-     * However, <i>multisampling</i> offscreen {@link GLFBODrawable}s
-     * utilize {@link GLDrawable#swapBuffers() swap-buffers} to <i>downsample</i>
-     * the multisamples into the readable sampling sink.
-     * In this case, we require a {@link GLDrawable#swapBuffers() swap-buffers} <b>before</b> calling {@link #endTile(GL)}.
-     * </p>
-     * @param chosenCaps the chosen {@link GLCapabilitiesImmutable}
-     * @return chosenCaps.isFBO() && chosenCaps.getSampleBuffers()
      */
     public final boolean reqPreSwapBuffers(GLCapabilitiesImmutable chosenCaps) {
-        return chosenCaps.isFBO() && chosenCaps.getSampleBuffers();
+        return GLDrawableUtil.swapBuffersBeforeRead(chosenCaps);
     }
 
     /**
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
index 9957f20..5a455c8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
@@ -30,6 +30,7 @@ package com.jogamp.opengl.util.av;
 import java.net.URI;
 
 import javax.media.opengl.GL;
+import javax.media.opengl.GLEventListener;
 import javax.media.opengl.GLException;
 
 import jogamp.opengl.Debug;
@@ -255,7 +256,12 @@ public interface GLMediaPlayer extends TextureSequence {
     /**
      * {@inheritDoc}
      * <p>
-     * See {@link TexSeqEventListener} for semantics and usage.
+     * As the contract of {@link TexSeqEventListener} requests,
+     * implementations of {@link GLMediaEventListener} shall also:
+     * <ul>
+     *   <li>off-load complex or {@link GLMediaPlayer} commands on another thread, or</li>
+     *   <li>simply changing a volatile state of their {@link GLEventListener} implementation.</li>
+     * </ul>
      * </p>
      */
     public interface GLMediaEventListener extends TexSeqEventListener<GLMediaPlayer> {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
index f5d31a1..9490e04 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
@@ -30,6 +30,7 @@ package com.jogamp.opengl.util.awt;
 import java.awt.image.BufferedImage;
 
 import javax.media.opengl.GL;
+import javax.media.opengl.GLDrawable;
 import javax.media.opengl.GLProfile;
 
 import com.jogamp.opengl.util.GLReadBufferUtil;
@@ -51,12 +52,53 @@ public class AWTGLReadBufferUtil extends GLReadBufferUtil {
 
     public AWTGLPixelBuffer getAWTGLPixelBuffer() { return (AWTGLPixelBuffer)this.getPixelBuffer(); }
 
+    /**
+     * Read the drawable's pixels to TextureData and Texture, if requested at construction,
+     * and returns an aligned {@link BufferedImage}.
+     *
+     * @param gl the current GL context object. It's read drawable is being used as the pixel source.
+     * @param awtOrientation flips the data vertically if <code>true</code>.
+     *                       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 #AWTGLReadBufferUtil(GLProfile, boolean)
+     */
     public BufferedImage readPixelsToBufferedImage(GL gl, boolean awtOrientation) {
         return readPixelsToBufferedImage(gl, 0, 0, 0, 0, awtOrientation);
     }
+
+    /**
+     * Read the drawable's pixels to TextureData and Texture, if requested at construction,
+     * and returns an aligned {@link BufferedImage}.
+     *
+     * @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 inWidth optional readPixel width value, used if [1 .. drawable.width], otherwise using drawable.width
+     * @param inHeight optional readPixel height, used if [1 .. drawable.height], otherwise using drawable.height
+     * @param awtOrientation flips the data vertically if <code>true</code>.
+     *                       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 #AWTGLReadBufferUtil(GLProfile, boolean)
+     */
     public BufferedImage readPixelsToBufferedImage(GL gl, int inX, int inY, int inWidth, int inHeight, boolean awtOrientation) {
-        if( readPixels(gl, inX, inY, inWidth, inHeight, awtOrientation) ) {
-            final BufferedImage image = getAWTGLPixelBuffer().image;
+        final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+        final int width, height;
+        if( 0 >= inWidth || drawable.getWidth() < inWidth ) {
+            width = drawable.getWidth();
+        } else {
+            width = inWidth;
+        }
+        if( 0 >= inHeight || drawable.getHeight() < inHeight ) {
+            height = drawable.getHeight();
+        } else {
+            height= inHeight;
+        }
+        if( readPixelsImpl(drawable, gl, inX, inY, width, height, awtOrientation) ) {
+            final BufferedImage image = getAWTGLPixelBuffer().getAlignedImage(width, height);
             if( getTextureData().getMustFlipVertically()  ) {
                 ImageUtil.flipImageVertically(image);
             }
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 0cde24d..0f64fd0 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
@@ -50,11 +50,13 @@ import java.io.OutputStream;
 import java.net.URL;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
 import java.util.ArrayList;
 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.PixelFormat;
 import javax.media.opengl.GL;
 import javax.media.opengl.GL2;
@@ -1400,18 +1402,34 @@ public class TextureIO {
                 final PixelFormat pixFmt = pixelAttribs.getPixelFormat();
                 if ( ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel) &&
                      ( pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) {
-                    ByteBuffer buf = (ByteBuffer) data.getBuffer();
-                    if (null == buf) {
-                        buf = (ByteBuffer) data.getMipmapData()[0];
+                    Buffer buf0 = data.getBuffer();
+                    if (null == buf0) {
+                        buf0 = data.getMipmapData()[0];
+                    }
+                    if( null == buf0 ) {
+                        throw new IOException("Pixel storage buffer is null");
+                    }
+                    final DimensionImmutable size = new Dimension(data.getWidth(), data.getHeight());
+                    if( buf0 instanceof ByteBuffer ) {
+                        final ByteBuffer buf = (ByteBuffer) buf0;
+                        buf.rewind();
+                        final PNGPixelRect image = new PNGPixelRect(pixFmt, size,
+                                                                    0 /* stride */, !data.getMustFlipVertically() /* isGLOriented */, buf /* pixels */,
+                                                                    -1f, -1f);
+                        final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */));
+                        image.write(outs, true /* close */);
+                        return true;
+                    } else if( buf0 instanceof IntBuffer ) {
+                        final IntBuffer buf = (IntBuffer) buf0;
+                        buf.rewind();
+                        final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */));
+                        PNGPixelRect.write(pixFmt, size,
+                                           0 /* stride */, !data.getMustFlipVertically() /* isGLOriented */, buf /* pixels */,
+                                           -1f, -1f, outs, true /* closeOutstream */);
+                        return true;
+                    } else {
+                        throw new IOException("PNG writer doesn't support pixel storage buffer of type "+buf0.getClass().getName());
                     }
-                    buf.rewind();
-
-                    final PNGPixelRect image = new PNGPixelRect(pixFmt, new Dimension(data.getWidth(), data.getHeight()),
-                                                                0 /* stride */, true /* isGLOriented */, buf /* pixels */,
-                                                                -1f, -1f);
-                    final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */));
-                    image.write(outs, true /* close */);
-                    return true;
                 }
                 throw new IOException("PNG writer doesn't support this pixel format 0x"+Integer.toHexString(pixelFormat)+
                                       " / type 0x"+Integer.toHexString(pixelFormat)+" (only GL_RGB/A, GL_BGR/A + bytes)");
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
index 6c2949c..ab9d1f8 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java
@@ -31,6 +31,7 @@ import javax.media.opengl.GL;
 import javax.media.opengl.GLAutoDrawable;
 import javax.media.opengl.GLRunnable;
 import javax.media.opengl.GLEventListener;
+
 import com.jogamp.opengl.util.TimeFrameI;
 
 /**
@@ -133,17 +134,16 @@ public interface TextureSequence {
     /**
      * Event listener to notify users of updates regarding the {@link TextureSequence}.
      * <p>
-     * The implementation sending the events, and hence calling down to all listeners,
-     * does not necessarily make the user's OpenGL context current.
+     * Implementations sending events down to all listeners,
+     * while not necessarily making the user's OpenGL context current.
      * </p>
      * <p>
-     * Further more, the call may happen off-thread, possibly holding another, possibly shared, OpenGL context current.
-     * </p>
+     * Events may be sent from a 3rd-party thread, possibly holding another, maybe shared, OpenGL context current.<br/>
      * Hence a user shall not issue <i>any</i> OpenGL, time consuming
-     * or {@link TextureSequence} lifecycle operations directly.<br>
+     * or {@link TextureSequence} operations directly.<br>
      * Instead, the user shall:
      * <ul>
-     *   <li>issue commands off-thread via spawning off another thread, or</li>
+     *   <li>off-load complex or {@link TextureSequence} commands on another thread, or</li>
      *   <li>injecting {@link GLRunnable} objects via {@link GLAutoDrawable#invoke(boolean, GLRunnable)}, or</li>
      *   <li>simply changing a volatile state of their {@link GLEventListener} implementation.</li>
      * </ul>
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index 2d6aed1..3f0c779 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -627,14 +627,24 @@ public interface GLBase {
     * 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.
+    * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} 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>
+    * <p>
+    * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+    * and {@link GL#GL_BACK} is the default.
+    * </p>
+    * <p>
+    * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i
+    * </p>
+    * <p>
+    * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead}
+    * for read-pixels and swap-buffers implications.
+    * </p>
     */
    public int getDefaultReadBuffer();
-
 }
 
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 9245d10..9a43117 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -1277,12 +1277,23 @@ public abstract class GLContext {
    * 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.
+   * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} 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>
+   * <p>
+   * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+   * and {@link GL#GL_BACK} is the default.
+   * </p>
+   * <p>
+   * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i
+   * </p>
+   * <p>
+   * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead}
+   * for read-pixels and swap-buffers implications.
+   * </p>
    */
   public abstract int getDefaultReadBuffer();
 
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index a43ddee..80f4695 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -39,7 +39,6 @@ package javax.media.opengl;
 
 import jogamp.nativewindow.NWJNILibLoader;
 import jogamp.opengl.Debug;
-import jogamp.opengl.GLContextImpl;
 import jogamp.opengl.GLDrawableFactoryImpl;
 import jogamp.opengl.DesktopGLDynamicLookupHelper;
 
@@ -51,6 +50,7 @@ import com.jogamp.common.util.VersionUtil;
 import com.jogamp.common.util.cache.TempJarCache;
 import com.jogamp.common.util.locks.LockFactory;
 import com.jogamp.common.util.locks.RecursiveThreadGroupLock;
+import com.jogamp.gluegen.runtime.FunctionAddressResolver;
 import com.jogamp.nativewindow.NativeWindowVersion;
 import com.jogamp.opengl.JoglVersion;
 
@@ -58,6 +58,7 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.opengl.fixedfunc.GLPointerFunc;
 
+import java.lang.reflect.Constructor;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.HashMap;
@@ -110,7 +111,7 @@ public class GLProfile {
         final boolean justInitialized;
         initLock.lock();
         try {
-            if(!initialized) { // volatile: ok
+            if(!initialized) {
                 initialized = true;
                 justInitialized = true;
                 if(DEBUG) {
@@ -118,6 +119,10 @@ public class GLProfile {
                     Thread.dumpStack();
                 }
 
+                if(ReflectionUtil.DEBUG_STATS_FORNAME) {
+                    ReflectionUtil.resetForNameCount();
+                }
+
                 // run the whole static initialization privileged to speed up,
                 // since this skips checking further access
                 AccessController.doPrivileged(new PrivilegedAction<Object>() {
@@ -125,24 +130,6 @@ public class GLProfile {
                     public Object run() {
                         Platform.initSingleton();
 
-                        // Performance hack to trigger classloading of the GL classes impl, which makes up to 12%, 800ms down to 700ms
-                        new Thread(new Runnable() {
-                          @Override
-                          public void run() {
-                              final ClassLoader cl = GLProfile.class.getClassLoader();
-                              try {
-                                  ReflectionUtil.createInstance(getGLImplBaseClassName(GL4bc)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
-                              } catch (Throwable t) {}
-                              try {
-                                  ReflectionUtil.createInstance(getGLImplBaseClassName(GLES3)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
-                              } catch (Throwable t) {}
-                              try {
-                                  ReflectionUtil.createInstance(getGLImplBaseClassName(GLES1)+"Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { null, null }, cl);
-                              } catch (Throwable t) {}
-                          }
-                        }, "GLProfile-GL_Bootstrapping").start();
-
-
                         if(TempJarCache.isInitialized()) {
                            final ClassLoader cl = GLProfile.class.getClassLoader();
                            final String newtFactoryClassName = "com.jogamp.newt.NewtFactory";
@@ -156,6 +143,11 @@ public class GLProfile {
                         return null;
                     }
                 });
+                if( ReflectionUtil.DEBUG_STATS_FORNAME ) {
+                    if( justInitialized ) {
+                        System.err.println(ReflectionUtil.getForNameStats(null).toString());
+                    }
+                }
             } else {
                 justInitialized = false;
             }
@@ -191,7 +183,7 @@ public class GLProfile {
     public static void shutdown() {
         initLock.lock();
         try {
-            if(initialized) { // volatile: ok
+            if(initialized) {
                 initialized = false;
                 if(DEBUG) {
                     System.err.println("GLProfile.shutdown() - thread "+Thread.currentThread().getName());
@@ -1045,7 +1037,6 @@ public class GLProfile {
     public final String getGLImplBaseClassName() {
         return getGLImplBaseClassName(getImplName());
     }
-
     private static final String getGLImplBaseClassName(String profileImpl) {
         if( GLES2 == profileImpl || GLES3 == profileImpl ) {
             return "jogamp.opengl.es3.GLES3";
@@ -1062,6 +1053,25 @@ public class GLProfile {
         }
     }
 
+    public final Constructor<?> getGLCtor(boolean glObject) {
+        return getGLCtor(getImplName(), glObject);
+    }
+    private static final Constructor<?> getGLCtor(String profileImpl, boolean glObject) {
+        if( GLES2 == profileImpl || GLES3 == profileImpl ) {
+            return glObject ? ctorGLES3Impl : ctorGLES3ProcAddr;
+        } else if( GLES1 == profileImpl ) {
+            return glObject ? ctorGLES1Impl : ctorGLES1ProcAddr;
+        } else if ( GL4bc == profileImpl ||
+                    GL4   == profileImpl ||
+                    GL3bc == profileImpl ||
+                    GL3   == profileImpl ||
+                    GL2   == profileImpl ) {
+            return glObject ? ctorGL234Impl : ctorGL234ProcAddr;
+        } else {
+            throw new GLException("unsupported profile \"" + profileImpl + "\"");
+        }
+    }
+
     /**
      * @param o GLProfile object to compare with
      * @return true if given Object is a GLProfile and
@@ -1530,13 +1540,87 @@ public class GLProfile {
     private static /*final*/ boolean hasEGLFactory;
     private static /*final*/ boolean hasGLES3Impl;
     private static /*final*/ boolean hasGLES1Impl;
+    private static /*final*/ Constructor<?> ctorGL234Impl;
+    private static /*final*/ Constructor<?> ctorGLES3Impl;
+    private static /*final*/ Constructor<?> ctorGLES1Impl;
+    private static /*final*/ Constructor<?> ctorGL234ProcAddr;
+    private static /*final*/ Constructor<?> ctorGLES3ProcAddr;
+    private static /*final*/ Constructor<?> ctorGLES1ProcAddr;
 
     private static /*final*/ GLDrawableFactoryImpl eglFactory = null;
     private static /*final*/ GLDrawableFactoryImpl desktopFactory = null;
     private static /*final*/ AbstractGraphicsDevice defaultDevice = null;
 
-    private static volatile boolean initialized = false;
-    private static RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock();
+    private static boolean initialized = false;
+    private static final RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock();
+
+    private static final Class<?>[] ctorGLArgs = new Class<?>[] { GLProfile.class, jogamp.opengl.GLContextImpl.class };
+    private static final Class<?>[] ctorProcArgs = new Class<?>[] { FunctionAddressResolver.class };
+    private static final String GL4bcImplClassName = "jogamp.opengl.gl4.GL4bcImpl";
+    private static final String GL4bcProcClassName = "jogamp.opengl.gl4.GL4bcProcAddressTable";
+    private static final String GLES1ImplClassName = "jogamp.opengl.es1.GLES1Impl";
+    private static final String GLES1ProcClassName = "jogamp.opengl.es1.GLES1ProcAddressTable";
+    private static final String GLES3ImplClassName = "jogamp.opengl.es3.GLES3Impl";
+    private static final String GLES3ProcClassName = "jogamp.opengl.es3.GLES3ProcAddressTable";
+
+    private static final Constructor<?> getCtor(final String clazzName, final boolean glObject, final ClassLoader cl) {
+        try {
+            return ReflectionUtil.getConstructor(clazzName, glObject ? ctorGLArgs : ctorProcArgs, cl);
+        } catch (Throwable t) {
+            if( DEBUG ) {
+                System.err.println("Catched: "+t.getMessage());
+                t.printStackTrace();
+            }
+            return null;
+        }
+    }
+
+    private static final void initGLCtorImpl() {
+        final ClassLoader classloader = GLProfile.class.getClassLoader();
+
+        // depends on hasDesktopGLFactory
+        {
+            final Constructor<?> ctorGL = getCtor(GL4bcImplClassName, true, classloader);
+            final Constructor<?> ctorProc = null != ctorGL ?  getCtor(GL4bcProcClassName, false, classloader) : null;
+            if( null != ctorProc ) {
+                hasGL234Impl   = true;
+                ctorGL234Impl = ctorGL;
+                ctorGL234ProcAddr = ctorProc;
+            } else {
+                hasGL234Impl   = false;
+                ctorGL234Impl = null;
+                ctorGL234ProcAddr = null;
+            }
+        }
+
+        // depends on hasEGLFactory
+        {
+            final Constructor<?> ctorGL = getCtor(GLES1ImplClassName, true, classloader);
+            final Constructor<?> ctorProc = null != ctorGL ?  getCtor(GLES1ProcClassName, false, classloader) : null;
+            if( null != ctorProc ) {
+                hasGLES1Impl   = true;
+                ctorGLES1Impl = ctorGL;
+                ctorGLES1ProcAddr = ctorProc;
+            } else {
+                hasGLES1Impl   = false;
+                ctorGLES1Impl = null;
+                ctorGLES1ProcAddr = null;
+            }
+        }
+        {
+            final Constructor<?> ctorGL = getCtor(GLES3ImplClassName, true, classloader);
+            final Constructor<?> ctorProc = null != ctorGL ?  getCtor(GLES3ProcClassName, false, classloader) : null;
+            if( null != ctorProc ) {
+                hasGLES3Impl   = true;
+                ctorGLES3Impl = ctorGL;
+                ctorGLES3ProcAddr = ctorProc;
+            } else {
+                hasGLES3Impl   = false;
+                ctorGLES3Impl = null;
+                ctorGLES3ProcAddr = null;
+            }
+        }
+    }
 
     /**
      * Tries the profiles implementation and native libraries.
@@ -1551,17 +1635,12 @@ public class GLProfile {
             System.err.println(JoglVersion.getInstance());
         }
 
-        ClassLoader classloader = GLProfile.class.getClassLoader();
+        final ClassLoader classloader = GLProfile.class.getClassLoader();
 
         isAWTAvailable = NativeWindowFactory.isAWTAvailable() &&
                          ReflectionUtil.isClassAvailable("javax.media.opengl.awt.GLCanvas", classloader) ; // JOGL
 
-        // depends on hasDesktopGLFactory
-        hasGL234Impl   = ReflectionUtil.isClassAvailable("jogamp.opengl.gl4.GL4bcImpl", classloader);
-
-        // depends on hasEGLFactory
-        hasGLES1Impl   = ReflectionUtil.isClassAvailable("jogamp.opengl.es1.GLES1Impl", classloader);
-        hasGLES3Impl   = ReflectionUtil.isClassAvailable("jogamp.opengl.es3.GLES3Impl", classloader);
+        initGLCtorImpl();
 
         //
         // Iteration of desktop GL availability detection
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index abf670c..0958908 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -818,9 +818,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
               printActive = false;
               return; // not yet available ..
           }
-          if( !isShowing ) {
+          if( !isVisible() ) {
               if(DEBUG) {
-                  System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, drawable valid, canvas not showing");
+                  System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, canvas not visible");
               }
               printActive = false;
               return; // not yet available ..
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 522585f..fbd923a 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -60,6 +60,7 @@ import java.util.List;
 
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.SurfaceUpdatedListener;
 import javax.media.nativewindow.WindowClosingProtocol;
 import javax.media.opengl.GL;
 import javax.media.opengl.GL2;
@@ -222,7 +223,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
       return singleAWTGLPixelBufferProvider;
   }
 
-  private final GLDrawableHelper helper = new GLDrawableHelper();
+  private final GLDrawableHelper helper;
+  private boolean autoSwapBufferMode;
+
   private volatile boolean isInitialized;
 
   //
@@ -352,9 +355,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     this.glProfile = offscreenCaps.getGLProfile();
     this.factory = GLDrawableFactoryImpl.getFactoryImpl(glProfile);
     this.chooser = chooser;
+
+    helper = new GLDrawableHelper();
     if( null != shareWith ) {
         helper.setSharedContext(null, shareWith);
     }
+    autoSwapBufferMode = helper.getAutoSwapBufferMode();
+
     this.setFocusable(true); // allow keyboard input!
     this.addHierarchyListener(hierarchyListener);
     this.isShowing = isShowing();
@@ -430,7 +437,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
 
   @Override
   public void display() {
-    if( isShowing ) {
+    if( isShowing || ( printActive && isVisible() ) ) {
         if (EventQueue.isDispatchThread()) {
           // Want display() to be synchronous, so call paintImmediately()
           paintImmediately(0, 0, getWidth(), getHeight());
@@ -620,9 +627,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
               printActive = false;
               return; // not yet available ..
           }
-          if( !isShowing ) {
+          if( !isVisible() ) {
               if(DEBUG) {
-                  System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, drawable valid, panel not showing");
+                  System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, panel not visible");
               }
               printActive = false;
               return; // not yet available ..
@@ -940,35 +947,31 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   }
 
   @Override
-  public void setAutoSwapBufferMode(boolean onOrOff) {
-    // In the current implementation this is a no-op. Both the pbuffer
-    // and pixmap based rendering paths use a single-buffered surface
-    // so swapping the buffers doesn't do anything. We also don't
-    // currently have the provision to skip copying the data to the
-    // Swing portion of the GLJPanel in any of the rendering paths.
+  public void setAutoSwapBufferMode(boolean enable) {
+    this.autoSwapBufferMode = enable;
+    boolean backendHandlesSwapBuffer = false;
+    if( isInitialized ) {
+        final Backend b = backend;
+        if ( null != b ) {
+            backendHandlesSwapBuffer= b.handlesSwapBuffer();
+        }
+    }
+    if( !backendHandlesSwapBuffer ) {
+        helper.setAutoSwapBufferMode(enable);
+    }
   }
 
   @Override
   public boolean getAutoSwapBufferMode() {
-    // In the current implementation this is a no-op. Both the pbuffer
-    // and pixmap based rendering paths use a single-buffered surface
-    // so swapping the buffers doesn't do anything. We also don't
-    // currently have the provision to skip copying the data to the
-    // Swing portion of the GLJPanel in any of the rendering paths.
-    return true;
+    return autoSwapBufferMode;
   }
 
   @Override
   public void swapBuffers() {
-    // In the current implementation this is a no-op. Both the pbuffer
-    // and pixmap based rendering paths use a single-buffered surface
-    // so swapping the buffers doesn't do anything. We also don't
-    // currently have the provision to skip copying the data to the
-    // Swing portion of the GLJPanel in any of the rendering paths.
-    if( printActive && isInitialized) {
+    if( isInitialized ) {
         final Backend b = backend;
         if ( null != b ) {
-            b.getDrawable().swapBuffers();
+            b.swapBuffers();
         }
     }
   }
@@ -1366,6 +1369,19 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     public boolean preGL(Graphics g);
 
     /**
+     * Return true if backend handles 'swap buffer' itself
+     * and hence the helper's setAutoSwapBuffer(enable) shall not be called.
+     * In this case {@link GLJPanel#autoSwapBufferMode} is being used
+     * in the backend to determine whether to swap buffers or not.
+     */
+    public boolean handlesSwapBuffer();
+
+    /**
+     * Shall invoke underlying drawable's swapBuffer.
+     */
+    public void swapBuffers();
+
+    /**
      * Called after the OpenGL work is done in init() and display().
      * The isDisplay argument indicates whether this was called on
      * behalf of a call to display() rather than init().
@@ -1400,6 +1416,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
 
     private volatile GLContextImpl offscreenContext; // volatile: avoid locking for read-only access
     private boolean flipVertical;
+    private int frameCount = 0;
 
     // For saving/restoring of OpenGL state during ReadPixels
     private final GLPixelStorageModes psm =  new GLPixelStorageModes();
@@ -1423,7 +1440,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     @Override
     public final void initialize() {
       if(DEBUG) {
-          System.err.println(getThreadName()+": OffscreenBackend: initialize()");
+          System.err.println(getThreadName()+": OffscreenBackend: initialize() - frameCount "+frameCount);
       }
       try {
           final GLContext[] shareWith = { null };
@@ -1436,10 +1453,20 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
                                                     chooser,
                                                     panelWidth, panelHeight);
           offscreenDrawable.setRealized(true);
+          if( DEBUG ) {
+              offscreenDrawable.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() {
+                  @Override
+                  public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+                      System.err.println(getThreadName()+": OffscreenBackend.swapBuffers - frameCount "+frameCount);
+                  } } );
+          }
+
           offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith[0]);
           offscreenContext.setContextCreationFlags(additionalCtxCreationFlags);
           if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
               isInitialized = true;
+              helper.setAutoSwapBufferMode(false); // we handle swap-buffers, see handlesSwapBuffer()
+
               final GL gl = offscreenContext.getGL();
               flipVertical = !GLJPanel.this.skipGLOrientationVerticalFlip && offscreenDrawable.isGLOriented();
               final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities();
@@ -1453,8 +1480,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
                           ", isGL2ES2 " + gl.isGL2ES2()+"]");
               }
               if( useGLSLFlip ) {
-                  final boolean _autoSwapBufferMode = helper.getAutoSwapBufferMode();
-                  helper.setAutoSwapBufferMode(false);
                   final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable;
                   fboDrawable.setTextureUnit( GLJPanel.this.requestedTextureUnit );
                   try {
@@ -1475,7 +1500,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
                         fboFlipped.destroy(gl);
                         fboFlipped = null;
                       }
-                      helper.setAutoSwapBufferMode(_autoSwapBufferMode);
                   }
               } else {
                   fboFlipped = null;
@@ -1502,7 +1526,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     @Override
     public final void destroy() {
       if(DEBUG) {
-          System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable));
+          System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable)+" - frameCount "+frameCount);
       }
       if ( null != offscreenContext && offscreenContext.isCreated() ) {
         if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
@@ -1563,8 +1587,29 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     }
 
     @Override
+    public final boolean handlesSwapBuffer() {
+        return true;
+    }
+
+    @Override
+    public final void swapBuffers() {
+        final GLDrawable d = offscreenDrawable;
+        if( null != d ) {
+            d.swapBuffers();
+        }
+    }
+
+    @Override
     public final void postGL(Graphics g, boolean isDisplay) {
       if (isDisplay) {
+        if(DEBUG) {
+            System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: - frameCount "+frameCount);
+        }
+        if( autoSwapBufferMode ) {
+            // Since we only use a single-buffer non-MSAA or double-buffered MSAA offscreenDrawable,
+            // we can always swap!
+            offscreenDrawable.swapBuffers();
+        }
         final GL gl = offscreenContext.getGL();
 
         final int componentCount;
@@ -1643,6 +1688,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
         }
 
         // Must now copy pixels from offscreen context into surface
+        if(DEBUG) {
+            System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.readPixels: - frameCount "+frameCount);
+        }
 
         // Save current modes
         psm.setAlignment(gl, alignment, alignment);
@@ -1652,8 +1700,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
             gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
         }
 
-        offscreenDrawable.swapBuffers();
-
         if(null != glslTextureRaster) { // implies flippedVertical
             final boolean viewportChange;
             final int[] usrViewport = new int[] { 0, 0, 0, 0 };
@@ -1731,9 +1777,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
       helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
 
       if ( null != alignedImage ) {
+        if( DEBUG ) {
+            System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.doPaintComponent.drawImage: - frameCount "+frameCount);
+        }
         // Draw resulting image in one shot
         g.drawImage(alignedImage, 0, 0, alignedImage.getWidth(), alignedImage.getHeight(), null); // Null ImageObserver since image data is ready.
       }
+      frameCount++;
     }
 
     @Override
@@ -1924,13 +1974,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
 
     @Override
     public final GLCapabilitiesImmutable getChosenGLCapabilities() {
-      // FIXME: should do better than this; is it possible to using only platform-independent code?
+      // FIXME: should do better than this; is it possible to query J2D Caps ?
       return new GLCapabilities(null);
     }
 
     @Override
     public final GLProfile getGLProfile() {
-      // FIXME: should do better than this; is it possible to using only platform-independent code?
+      // FIXME: should do better than this; is it possible to query J2D's Profile ?
       return GLProfile.getDefault(GLProfile.getDefaultDevice());
     }
 
@@ -2078,6 +2128,19 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     }
 
     @Override
+    public final boolean handlesSwapBuffer() {
+        return false;
+    }
+
+    @Override
+    public final void swapBuffers() {
+        final GLDrawable d = joglDrawable;
+        if( null != d ) {
+            d.swapBuffers();
+        }
+    }
+
+    @Override
     public final void postGL(Graphics g, boolean isDisplay) {
       // Cause OpenGL pipeline to flush its results because
       // otherwise it's possible we will buffer up multiple frames'
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java b/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java
index fe2dd73..68f926b 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/RenderStateImpl.java
@@ -61,10 +61,6 @@ public class RenderStateImpl extends RenderState {
 //        st.ownUniform(gcu_Strength);
     }
 
-    public RenderStateImpl(ShaderState st, Vertex.Factory<? extends Vertex> pointFactory) {
-        this(st, pointFactory, new PMVMatrix());
-    }
-
     @Override
     public final GLUniformData getWeight() { return gcu_Weight; }
     @Override
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java
index 472bfbd..2351826 100644
--- a/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java
@@ -298,7 +298,7 @@ public class GLBufferObjectTracker {
     public synchronized final GLBufferStorage mapBuffer(final GLBufferStateTracker bufferStateTracker,
                                                         final GL caller, final int target, final long offset, final long length, final int access,
                                                         final MapBufferRangeDispatch dispatch, final long glProcAddress) throws GLException {
-        return this.mapBufferImpl(bufferStateTracker, caller, target, true /* useRange */, length, access, access, dispatch, glProcAddress);
+        return this.mapBufferImpl(bufferStateTracker, caller, target, true /* useRange */, offset, length, access, dispatch, glProcAddress);
     }
     /**
      * Must be called when mapping GL buffer objects via {@link GL2#mapNamedBuffer(int, int)}.
@@ -319,7 +319,7 @@ public class GLBufferObjectTracker {
      */
     public synchronized final GLBufferStorage mapBuffer(final int bufferName, final long offset, final long length, final int access, final MapBufferRangeDispatch dispatch,
                                                         final long glProcAddress) throws GLException {
-        return this.mapBufferImpl(0 /* target */, bufferName, true /* isNamedBuffer */, false /* useRange */, 0 /* offset */, 0 /* length */, access, dispatch, glProcAddress);
+        return this.mapBufferImpl(0 /* target */, bufferName, true /* isNamedBuffer */, true /* useRange */, offset, length, access, dispatch, glProcAddress);
     }
     /**
      * @throws GLException if buffer is not bound to target
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 431bba6..9ccd785 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -54,7 +54,6 @@ 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;
 import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
@@ -1127,17 +1126,17 @@ public abstract class GLContextImpl extends GLContext {
   // Helpers for various context implementations
   //
 
-  private Object createInstance(GLProfile glp, String suffix, Class<?>[] cstrArgTypes, Object[] cstrArgs) {
-    return ReflectionUtil.createInstance(glp.getGLImplBaseClassName()+suffix, cstrArgTypes, cstrArgs, getClass().getClassLoader());
+  private Object createInstance(GLProfile glp, boolean glObject, Object[] cstrArgs) {
+      return ReflectionUtil.createInstance(glp.getGLCtor(glObject), cstrArgs);
   }
 
   private boolean verifyInstance(GLProfile glp, String suffix, Object instance) {
-    return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix);
+      return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix);
   }
 
   /** Create the GL for this context. */
   protected GL createGL(GLProfile glp) {
-    final GL gl = (GL) createInstance(glp, "Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { glp, this } );
+    final GL gl = (GL) createInstance(glp, true, new Object[] { glp, this } );
 
     /* FIXME: refactor dependence on Java 2D / JOGL bridge
     if (tracker != null) {
@@ -1585,8 +1584,7 @@ public abstract class GLContextImpl extends GLContext {
             System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+") -> "+toHexString(table.hashCode()));
         }
     } else {
-        glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), "ProcAddressTable",
-                                                               new Class[] { FunctionAddressResolver.class } ,
+        glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), false,
                                                                new Object[] { new GLProcAddressResolver() } );
         resetProcAddressTable(getGLProcAddressTable());
         synchronized(mappedContextTypeObjectLock) {
@@ -2233,7 +2231,7 @@ public abstract class GLContextImpl extends GLContext {
   @Override
   public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); }
   @Override
-  public final int getDefaultReadBuffer() { return drawable.getDefaultReadBuffer(gl); }
+  public final int getDefaultReadBuffer() { return drawable.getDefaultReadBuffer(gl, drawableRead != drawable); }
 
   //---------------------------------------------------------------------------
   // GL_ARB_debug_output, GL_AMD_debug_output helpers
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index 94d39a4..d112745 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -260,8 +260,8 @@ public abstract class GLDrawableImpl implements GLDrawable {
   /** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */
   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()) {
+  protected int getDefaultReadBuffer(GL gl, boolean hasDedicatedDrawableRead) {
+      if( gl.isGLES() || hasDedicatedDrawableRead || 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;
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index 0e9d142..6f5fa3e 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -325,7 +325,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 ; }
+    protected final int getDefaultReadBuffer(GL gl, boolean hasDedicatedDrawableRead) {
+        return initialized ? fbos[fboIFront].getDefaultReadBuffer() : GL.GL_COLOR_ATTACHMENT0 ;
+    }
 
     @Override
     protected final void setRealizedImpl() {
diff --git a/src/jogl/classes/jogamp/opengl/GLStateTracker.java b/src/jogl/classes/jogamp/opengl/GLStateTracker.java
index 307fd0a..0e45174 100644
--- a/src/jogl/classes/jogamp/opengl/GLStateTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLStateTracker.java
@@ -177,20 +177,20 @@ public class GLStateTracker {
     pixelStateMap.put(GL.GL_PACK_ALIGNMENT,          4);
     pixelStateMap.put(GL2GL3.GL_PACK_SWAP_BYTES,     GL.GL_FALSE);
     pixelStateMap.put(GL2GL3.GL_PACK_LSB_FIRST,      GL.GL_FALSE);
-    pixelStateMap.put(GL2GL3.GL_PACK_ROW_LENGTH,     0);
-    pixelStateMap.put(GL2GL3.GL_PACK_SKIP_ROWS,      0);
-    pixelStateMap.put(GL2GL3.GL_PACK_SKIP_PIXELS,    0);
+    pixelStateMap.put(GL2ES3.GL_PACK_ROW_LENGTH,     0);
+    pixelStateMap.put(GL2ES3.GL_PACK_SKIP_ROWS,      0);
+    pixelStateMap.put(GL2ES3.GL_PACK_SKIP_PIXELS,    0);
     pixelStateMap.put(GL2GL3.GL_PACK_IMAGE_HEIGHT,   0);
     pixelStateMap.put(GL2GL3.GL_PACK_SKIP_IMAGES,    0);
 
     pixelStateMap.put(GL.GL_UNPACK_ALIGNMENT,        4);
     pixelStateMap.put(GL2GL3.GL_UNPACK_SWAP_BYTES,   GL.GL_FALSE);
     pixelStateMap.put(GL2GL3.GL_UNPACK_LSB_FIRST,    GL.GL_FALSE);
-    pixelStateMap.put(GL2GL3.GL_UNPACK_ROW_LENGTH,   0);
-    pixelStateMap.put(GL2GL3.GL_UNPACK_SKIP_ROWS,    0);
-    pixelStateMap.put(GL2GL3.GL_UNPACK_SKIP_PIXELS,  0);
-    pixelStateMap.put(GL2GL3.GL_UNPACK_IMAGE_HEIGHT, 0);
-    pixelStateMap.put(GL2GL3.GL_UNPACK_SKIP_IMAGES,  0);
+    pixelStateMap.put(GL2ES2.GL_UNPACK_ROW_LENGTH,   0);
+    pixelStateMap.put(GL2ES2.GL_UNPACK_SKIP_ROWS,    0);
+    pixelStateMap.put(GL2ES2.GL_UNPACK_SKIP_PIXELS,  0);
+    pixelStateMap.put(GL2ES3.GL_UNPACK_IMAGE_HEIGHT, 0);
+    pixelStateMap.put(GL2ES3.GL_UNPACK_SKIP_IMAGES,  0);
   }
 }
 
diff --git a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java
index 8b12f8a..eeaaa58 100644
--- a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java
+++ b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java
@@ -31,6 +31,8 @@ package jogamp.opengl.openal.av;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 
+import jogamp.opengl.Debug;
+
 import com.jogamp.common.util.LFRingbuffer;
 import com.jogamp.common.util.Ringbuffer;
 import com.jogamp.common.util.locks.LockFactory;
@@ -50,6 +52,8 @@ import com.jogamp.opengl.util.av.AudioSink;
 public class ALAudioSink implements AudioSink {
 
     private static final String AL_SOFT_buffer_samples = "AL_SOFT_buffer_samples";
+    private static final String ALC_EXT_thread_local_context = "ALC_EXT_thread_local_context";
+    private static final boolean DEBUG_TRACE;
     private static final ALC alc;
     private static final AL al;
     private static final ALExt alExt;
@@ -58,6 +62,7 @@ public class ALAudioSink implements AudioSink {
     private String deviceSpecifier;
     private ALCdevice device;
     private boolean hasSOFTBufferSamples;
+    private boolean hasALC_thread_local_context;
     private AudioFormat preferredAudioFormat;
     private ALCcontext context;
     private final RecursiveLock lock = LockFactory.createRecursiveLock();
@@ -106,6 +111,9 @@ public class ALAudioSink implements AudioSink {
     private volatile boolean playRequested = false;
 
     static {
+        Debug.initSingleton();
+        DEBUG_TRACE = Debug.isPropertyDefined("jogl.debug.AudioSink.trace", true);
+
         ALC _alc = null;
         AL _al = null;
         ALExt _alExt = null;
@@ -132,67 +140,71 @@ public class ALAudioSink implements AudioSink {
         if( !staticAvailable ) {
             return;
         }
+        synchronized(ALAudioSink.class) {
+            try {
+                // Get handle to default device.
+                device = alc.alcOpenDevice(null);
+                if (device == null) {
+                    throw new RuntimeException(getThreadName()+": ALAudioSink: Error opening default OpenAL device");
+                }
 
-        try {
-            // Get handle to default device.
-            device = alc.alcOpenDevice(null);
-            if (device == null) {
-                throw new RuntimeException("ALAudioSink: Error opening default OpenAL device");
-            }
+                // Get the device specifier.
+                deviceSpecifier = alc.alcGetString(device, ALC.ALC_DEVICE_SPECIFIER);
+                if (deviceSpecifier == null) {
+                    throw new RuntimeException(getThreadName()+": ALAudioSink: Error getting specifier for default OpenAL device");
+                }
 
-            // Get the device specifier.
-            deviceSpecifier = alc.alcGetString(device, ALC.ALC_DEVICE_SPECIFIER);
-            if (deviceSpecifier == null) {
-                throw new RuntimeException("ALAudioSink: Error getting specifier for default OpenAL device");
-            }
+                // Create audio context.
+                context = alc.alcCreateContext(device, null);
+                if (context == null) {
+                    throw new RuntimeException(getThreadName()+": ALAudioSink: Error creating OpenAL context for "+deviceSpecifier);
+                }
 
-            // Create audio context.
-            context = alc.alcCreateContext(device, null);
-            if (context == null) {
-                throw new RuntimeException("ALAudioSink: Error creating OpenAL context for "+deviceSpecifier);
-            }
+                lockContext();
+                try {
+                    // Check for an error.
+                    if ( alc.alcGetError(device) != ALC.ALC_NO_ERROR ) {
+                        throw new RuntimeException(getThreadName()+": ALAudioSink: Error making OpenAL context current");
+                    }
 
-            lockContext();
-            try {
-                // Check for an error.
-                if ( alc.alcGetError(device) != ALC.ALC_NO_ERROR ) {
-                    throw new RuntimeException("ALAudioSink: Error making OpenAL context current");
-                }
+                    hasSOFTBufferSamples = al.alIsExtensionPresent(AL_SOFT_buffer_samples);
+                    hasALC_thread_local_context = alc.alcIsExtensionPresent(null, ALC_EXT_thread_local_context) ||
+                                                  alc.alcIsExtensionPresent(device, ALC_EXT_thread_local_context) ;
+                    preferredAudioFormat = queryPreferredAudioFormat();
+                    if( DEBUG ) {
+                        System.out.println("ALAudioSink: OpenAL Extensions:"+al.alGetString(AL.AL_EXTENSIONS));
+                        System.out.println("ALAudioSink: Null device OpenAL Extensions:"+alc.alcGetString(null, ALC.ALC_EXTENSIONS));
+                        System.out.println("ALAudioSink: Device "+deviceSpecifier+" OpenAL Extensions:"+alc.alcGetString(device, ALC.ALC_EXTENSIONS));
+                        System.out.println("ALAudioSink: hasSOFTBufferSamples "+hasSOFTBufferSamples);
+                        System.out.println("ALAudioSink: hasALC_thread_local_context "+hasALC_thread_local_context);
+                        System.out.println("ALAudioSink: preferredAudioFormat "+preferredAudioFormat);
+                    }
 
-                hasSOFTBufferSamples = al.alIsExtensionPresent(AL_SOFT_buffer_samples);
-                preferredAudioFormat = queryPreferredAudioFormat();
-                if( DEBUG ) {
-                    System.out.println("ALAudioSink: OpenAL Extensions:"+al.alGetString(AL.AL_EXTENSIONS));
-                    System.out.println("ALAudioSink: Null device OpenAL Extensions:"+alc.alcGetString(null, ALC.ALC_EXTENSIONS));
-                    System.out.println("ALAudioSink: Device "+deviceSpecifier+" OpenAL Extensions:"+alc.alcGetString(device, ALC.ALC_EXTENSIONS));
-                    System.out.println("ALAudioSink: hasSOFTBufferSamples "+hasSOFTBufferSamples);
-                    System.out.println("ALAudioSink: preferredAudioFormat "+preferredAudioFormat);
-                }
+                    // Create source
+                    {
+                        alSource = new int[1];
+                        al.alGenSources(1, alSource, 0);
+                        final int err = al.alGetError();
+                        if( AL.AL_NO_ERROR != err ) {
+                            alSource = null;
+                            throw new RuntimeException(getThreadName()+": ALAudioSink: Error generating Source: 0x"+Integer.toHexString(err));
+                        }
+                    }
 
-                // Create source
-                {
-                    alSource = new int[1];
-                    al.alGenSources(1, alSource, 0);
-                    final int err = al.alGetError();
-                    if( err != AL.AL_NO_ERROR ) {
-                        alSource = null;
-                        throw new RuntimeException("ALAudioSink: Error generating Source: 0x"+Integer.toHexString(err));
+                    if( DEBUG ) {
+                        System.err.println("ALAudioSink: Using device: " + deviceSpecifier);
                     }
+                    initialized = true;
+                } finally {
+                    unlockContext();
                 }
-
+                return;
+            } catch ( Exception e ) {
                 if( DEBUG ) {
-                    System.err.println("ALAudioSink: Using device: " + deviceSpecifier);
+                    System.err.println(e.getMessage());
                 }
-                initialized = true;
-            } finally {
-                unlockContext();
-            }
-            return;
-        } catch ( Exception e ) {
-            if( DEBUG ) {
-                System.err.println(e.getMessage());
+                destroy();
             }
-            destroy();
         }
     }
 
@@ -208,10 +220,33 @@ public class ALAudioSink implements AudioSink {
 
     private final void lockContext() {
         lock.lock();
-        alc.alcMakeContextCurrent(context);
+        if( hasALC_thread_local_context ) {
+            alExt.alcSetThreadContext(context);
+        } else {
+            alc.alcMakeContextCurrent(context);
+        }
+        final int alcErr = alc.alcGetError(null);
+        if( ALC.ALC_NO_ERROR != alcErr ) {
+            final String err = getThreadName()+": ALCError "+toHexString(alcErr)+" while makeCurrent. "+this;
+            System.err.println(err);
+            Thread.dumpStack();
+            lock.unlock();
+            throw new RuntimeException(err);
+        }
+        final int alErr = al.alGetError();
+        if( ALC.ALC_NO_ERROR != alErr ) {
+            if( DEBUG ) {
+                System.err.println(getThreadName()+": Prev - ALError "+toHexString(alErr)+" @ makeCurrent. "+this);
+                Thread.dumpStack();
+            }
+        }
     }
     private final void unlockContext() {
-        alc.alcMakeContextCurrent(null);
+        if( hasALC_thread_local_context ) {
+            alExt.alcSetThreadContext(null);
+        } else {
+            alc.alcMakeContextCurrent(null);
+        }
         lock.unlock();
     }
     private final void destroyContext() {
@@ -251,6 +286,14 @@ public class ALAudioSink implements AudioSink {
                "queue[g "+frameGrowAmount+", l "+frameLimit+"]";
     }
 
+    private final String shortString() {
+        final int alSrcName = null != alSource ? alSource[0] : 0;
+        final int ctxHash = context != null ? context.hashCode() : 0;
+        return "[ctx "+toHexString(ctxHash)+", playReq "+playRequested+", alSrc "+alSrcName+
+               ", queued["+alFramesPlaying.size()+", " + alBufferBytesQueued+" bytes], "+
+               "queue[g "+frameGrowAmount+", l "+frameLimit+"]";
+    }
+
     public final String getPerfString() {
         final int alBuffersLen = null != alBufferNames ? alBufferNames.length : 0;
         return "Play [buffer "+alFramesPlaying.size()+"/"+alBuffersLen+", apts "+getPTS()+", "+getQueuedTime() + " ms, " + alBufferBytesQueued+" bytes]";
@@ -325,9 +368,9 @@ public class ALAudioSink implements AudioSink {
                 alBufferNames = new int[initialFrameCount];
                 al.alGenBuffers(initialFrameCount, alBufferNames, 0);
                 final int err = al.alGetError();
-                if( err != AL.AL_NO_ERROR ) {
+                if( AL.AL_NO_ERROR != err ) {
                     alBufferNames = null;
-                    throw new RuntimeException("ALAudioSink: Error generating Buffers: 0x"+Integer.toHexString(err));
+                    throw new RuntimeException(getThreadName()+": ALAudioSink: Error generating Buffers: 0x"+Integer.toHexString(err));
                 }
                 final ALAudioFrame[] alFrames = new ALAudioFrame[initialFrameCount];
                 for(int i=0; i<initialFrameCount; i++) {
@@ -340,6 +383,10 @@ public class ALAudioSink implements AudioSink {
                         queueGrowAmount > 0 ? queueGrowAmount : AudioSink.DefaultQueueGrowAmount, useFrameDuration);
                 this.frameLimit = requestedFormat.getFrameCount(
                         queueLimit > 0 ? queueLimit : AudioSink.DefaultQueueLimitWithVideo, useFrameDuration);
+                if( DEBUG_TRACE ) {
+                    alFramesAvail.dump(System.err, "Avail-init");
+                    alFramesPlaying.dump(System.err, "Playi-init");
+                }
             }
         } finally {
             unlockContext();
@@ -375,7 +422,7 @@ public class ALAudioSink implements AudioSink {
         final int[] newALBufferNames = new int[frameGrowAmount];
         al.alGenBuffers(frameGrowAmount, newALBufferNames, 0);
         final int err = al.alGetError();
-        if( err != AL.AL_NO_ERROR ) {
+        if( AL.AL_NO_ERROR != err ) {
             if( DEBUG ) {
                 System.err.println(getThreadName()+": ALAudioSink.growBuffers: Error generating "+frameGrowAmount+" new Buffers: 0x"+Integer.toHexString(err));
             }
@@ -397,6 +444,10 @@ public class ALAudioSink implements AudioSink {
         if( DEBUG ) {
             System.err.println(getThreadName()+": ALAudioSink: Buffer grown "+frameGrowAmount+": Avail "+alFramesAvail+", playing "+alFramesPlaying);
         }
+        if( DEBUG_TRACE ) {
+            alFramesAvail.dump(System.err, "Avail-grow");
+            alFramesPlaying.dump(System.err, "Playi-grow");
+        }
         return true;
     }
 
@@ -433,7 +484,7 @@ public class ALAudioSink implements AudioSink {
             lockContext();
         }
         try {
-            stopImpl();
+            stopImpl(true);
             if( null != alSource ) {
                 try {
                     al.alDeleteSources(1, alSource, 0);
@@ -469,7 +520,7 @@ public class ALAudioSink implements AudioSink {
         return initialized;
     }
 
-    private final int dequeueBuffer(boolean wait) {
+    private final int dequeueBuffer(final boolean wait, final boolean ignoreBufferInconsistency) {
         int alErr = AL.AL_NO_ERROR;
         final int releaseBufferCount;
         if( alBufferBytesQueued > 0 ) {
@@ -480,7 +531,7 @@ public class ALAudioSink implements AudioSink {
                 al.alGetSourcei(alSource[0], AL.AL_BUFFERS_PROCESSED, val, 0);
                 alErr = al.alGetError();
                 if( AL.AL_NO_ERROR != alErr ) {
-                    throw new RuntimeException("ALError "+toHexString(alErr)+" while quering processed buffers at source. "+this);
+                    throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while quering processed buffers at source. "+this);
                 }
                 if( wait && val[0] < releaseBufferLimes ) {
                     i++;
@@ -488,7 +539,7 @@ public class ALAudioSink implements AudioSink {
                     final int avgBufferDura = chosenFormat.getBytesDuration( alBufferBytesQueued / alFramesPlaying.size() );
                     final int sleep = Math.max(2, Math.min(100, releaseBufferLimes * avgBufferDura));
                     if( DEBUG ) {
-                        System.err.println(getThreadName()+": ALAudioSink: Dequeue.wait["+i+"]: avgBufferDura "+avgBufferDura+", releaseBufferLimes "+releaseBufferLimes+", sleep "+sleep+" ms, playImpl "+(AL.AL_PLAYING == getSourceState())+", processed "+val[0]+", "+this);
+                        System.err.println(getThreadName()+": ALAudioSink: Dequeue.wait["+i+"]: avgBufferDura "+avgBufferDura+", releaseBufferLimes "+releaseBufferLimes+", sleep "+sleep+" ms, playImpl "+(AL.AL_PLAYING == getSourceState(false))+", processed "+val[0]+", "+this);
                     }
                     unlockContext();
                     try {
@@ -505,31 +556,51 @@ public class ALAudioSink implements AudioSink {
         }
 
         if( releaseBufferCount > 0 ) {
-            int[] buffers=new int[releaseBufferCount];
+            final int[] buffers = new int[releaseBufferCount];
             al.alSourceUnqueueBuffers(alSource[0], releaseBufferCount, buffers, 0);
             alErr = al.alGetError();
             if( AL.AL_NO_ERROR != alErr ) {
-                throw new RuntimeException("ALError "+toHexString(alErr)+" while dequeueing "+releaseBufferCount+" buffers. "+this);
+                throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while dequeueing "+releaseBufferCount+" buffers. "+this);
             }
             for ( int i=0; i<releaseBufferCount; i++ ) {
                 final ALAudioFrame releasedBuffer = alFramesPlaying.get();
                 if( null == releasedBuffer ) {
-                    throw new InternalError("Internal Error: "+this);
-                }
-                if( releasedBuffer.alBuffer != buffers[i] ) {
-                    alFramesAvail.dump(System.err, "Avail-deq02-post");
-                    alFramesPlaying.dump(System.err, "Playi-deq02-post");
-                    throw new InternalError("Buffer name mismatch: dequeued: "+buffers[i]+", released "+releasedBuffer+", "+this);
+                    if( !ignoreBufferInconsistency ) {
+                        throw new InternalError("Internal Error: "+this);
+                    }
+                } else {
+                    if(DEBUG_TRACE) {
+                        System.err.println("<  [al "+buffers[i]+", q "+releasedBuffer.alBuffer+"] <- "+shortString()+" @ "+getThreadName());
+                    }
+                    if( releasedBuffer.alBuffer != buffers[i] ) {
+                        if( !ignoreBufferInconsistency ) {
+                            alFramesAvail.dump(System.err, "Avail-deq02-post");
+                            alFramesPlaying.dump(System.err, "Playi-deq02-post");
+                            throw new InternalError("Buffer name mismatch: dequeued: "+buffers[i]+", released "+releasedBuffer+", "+this);
+                        }
+                    }
                 }
                 alBufferBytesQueued -= releasedBuffer.getByteSize();
                 if( !alFramesAvail.put(releasedBuffer) ) {
                     throw new InternalError("Internal Error: "+this);
                 }
+                if(DEBUG_TRACE) {
+                    System.err.println("<< [al "+buffers[i]+", q "+releasedBuffer.alBuffer+"] <- "+shortString()+" @ "+getThreadName());
+                }
             }
         }
         return releaseBufferCount;
     }
     private final void dequeueForceAll() {
+        if(DEBUG_TRACE) {
+            System.err.println("<   _FLUSH_  <- "+shortString()+" @ "+getThreadName());
+        }
+        final int[] val=new int[1];
+        al.alSourcei(alSource[0], AL.AL_BUFFER, 0); // explicit force zero buffer!
+        if(DEBUG_TRACE) {
+            al.alGetSourcei(alSource[0], AL.AL_BUFFERS_PROCESSED, val, 0);
+        }
+        final int alErr = al.alGetError();
         while ( !alFramesPlaying.isEmpty() ) {
             final ALAudioFrame releasedBuffer = alFramesPlaying.get();
             if( null == releasedBuffer ) {
@@ -540,13 +611,15 @@ public class ALAudioSink implements AudioSink {
                 throw new InternalError("Internal Error: "+this);
             }
         }
-        if( 0 != alBufferBytesQueued ) {
-            throw new InternalError("Internal Error: "+this);
+        alBufferBytesQueued = 0;
+        if(DEBUG_TRACE) {
+            System.err.println("<<  _FLUSH_  [al "+val[0]+", err "+toHexString(alErr)+"] <- "+shortString()+" @ "+getThreadName());
+            Thread.dumpStack();
         }
     }
 
     private final int dequeueBuffer(boolean wait, int inPTS, int inDuration) {
-        final int dequeuedBufferCount = dequeueBuffer( wait );
+        final int dequeuedBufferCount = dequeueBuffer( wait, false /* ignoreBufferInconsistency */ );
         final ALAudioFrame currentBuffer = alFramesPlaying.peek();
         if( null != currentBuffer ) {
             playingPTS = currentBuffer.getPTS();
@@ -572,18 +645,12 @@ public class ALAudioSink implements AudioSink {
             return null;
         }
         final ALAudioFrame alFrame;
-        int alErr = AL.AL_NO_ERROR;
 
         // OpenAL consumes buffers in the background
         // we first need to initialize the OpenAL buffers then
         // start continuous playback.
         lockContext();
         try {
-            alErr = al.alGetError();
-            if(al.alGetError() != AL.AL_NO_ERROR) {
-                throw new RuntimeException("ALError "+toHexString(alErr)+" while makeCurrent. "+this);
-            }
-
             final int duration = chosenFormat.getBytesDuration(byteCount);
             final boolean dequeueDone;
             if( alFramesAvail.isEmpty() ) {
@@ -612,6 +679,7 @@ public class ALAudioSink implements AudioSink {
             if( !alFramesPlaying.put( alFrame ) ) {
                 throw new InternalError("Internal Error: "+this);
             }
+            final int[] alBufferNames = new int[] { alFrame.alBuffer };
             if( hasSOFTBufferSamples ) {
                 final int samplesPerChannel = chosenFormat.getBytesSampleCount(byteCount) / chosenFormat.channelCount;
                 // final int samplesPerChannel = ALHelpers.bytesToSampleCount(byteCount, alChannelLayout, alSampleType);
@@ -621,15 +689,22 @@ public class ALAudioSink implements AudioSink {
                 al.alBufferData(alFrame.alBuffer, alFormat, bytes, byteCount, chosenFormat.sampleRate);
             }
 
-            final int[] alBufferNames = new int[] { alFrame.alBuffer };
+            if(DEBUG_TRACE) {
+                System.err.println(">  "+alFrame.alBuffer+" -> "+shortString()+" @ "+getThreadName());
+            }
+
             al.alSourceQueueBuffers(alSource[0], 1, alBufferNames, 0);
-            alErr = al.alGetError();
-            if(al.alGetError() != AL.AL_NO_ERROR) {
-                throw new RuntimeException("ALError "+toHexString(alErr)+" while queueing buffer "+toHexString(alBufferNames[0])+". "+this);
+            final int alErr = al.alGetError();
+            if( AL.AL_NO_ERROR != alErr ) {
+                throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while queueing buffer "+toHexString(alBufferNames[0])+". "+this);
             }
             alBufferBytesQueued += byteCount;
             enqueuedFrameCount++;
 
+            if(DEBUG_TRACE) {
+                System.err.println(">> "+alFrame.alBuffer+" -> "+shortString()+" @ "+getThreadName());
+            }
+
             playImpl(); // continue playing, fixes issue where we ran out of enqueued data!
         } finally {
             unlockContext();
@@ -655,17 +730,24 @@ public class ALAudioSink implements AudioSink {
     }
     private final boolean isPlayingImpl0() {
         if( playRequested ) {
-            return AL.AL_PLAYING == getSourceState();
+            return AL.AL_PLAYING == getSourceState(false);
         } else {
             return false;
         }
     }
-    private final int getSourceState() {
+    private final int getSourceState(boolean ignoreError) {
         final int[] val = new int[1];
         al.alGetSourcei(alSource[0], AL.AL_SOURCE_STATE, val, 0);
         final int alErr = al.alGetError();
-        if(al.alGetError() != AL.AL_NO_ERROR) {
-            throw new RuntimeException("ALError "+toHexString(alErr)+" while querying SOURCE_STATE. "+this);
+        if( AL.AL_NO_ERROR != alErr ) {
+            final String msg = getThreadName()+": ALError "+toHexString(alErr)+" while querying SOURCE_STATE. "+this;
+            if( ignoreError ) {
+                if( DEBUG ) {
+                    System.err.println(msg);
+                }
+            } else {
+                throw new RuntimeException(msg);
+            }
         }
         return val[0];
     }
@@ -680,18 +762,18 @@ public class ALAudioSink implements AudioSink {
         try {
             playImpl();
             if( DEBUG ) {
-                System.err.println(getThreadName()+": ALAudioSink: PLAY playImpl "+(AL.AL_PLAYING == getSourceState())+", "+this);
+                System.err.println(getThreadName()+": ALAudioSink: PLAY playImpl "+(AL.AL_PLAYING == getSourceState(false))+", "+this);
             }
         } finally {
             unlockContext();
         }
     }
     private final void playImpl() {
-        if( playRequested && AL.AL_PLAYING != getSourceState() ) {
+        if( playRequested && AL.AL_PLAYING != getSourceState(false) ) {
             al.alSourcePlay(alSource[0]);
             final int alErr = al.alGetError();
-            if(al.alGetError() != AL.AL_NO_ERROR) {
-                throw new RuntimeException("ALError "+toHexString(alErr)+" while start playing. "+this);
+            if( AL.AL_NO_ERROR != alErr ) {
+                throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while start playing. "+this);
             }
         }
     }
@@ -706,7 +788,7 @@ public class ALAudioSink implements AudioSink {
             try {
                 pauseImpl();
                 if( DEBUG ) {
-                    System.err.println(getThreadName()+": ALAudioSink: PAUSE playImpl "+(AL.AL_PLAYING == getSourceState())+", "+this);
+                    System.err.println(getThreadName()+": ALAudioSink: PAUSE playImpl "+(AL.AL_PLAYING == getSourceState(false))+", "+this);
                 }
             } finally {
                 unlockContext();
@@ -718,18 +800,25 @@ public class ALAudioSink implements AudioSink {
             playRequested = false;
             al.alSourcePause(alSource[0]);
             final int alErr = al.alGetError();
-            if(al.alGetError() != AL.AL_NO_ERROR) {
-                throw new RuntimeException("ALError "+toHexString(alErr)+" while pausing. "+this);
+            if( AL.AL_NO_ERROR != alErr ) {
+                throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while pausing. "+this);
             }
         }
     }
-    private final void stopImpl() {
-        if( AL.AL_STOPPED != getSourceState() ) {
+    private final void stopImpl(boolean ignoreError) {
+        if( AL.AL_STOPPED != getSourceState(ignoreError) ) {
             playRequested = false;
             al.alSourceStop(alSource[0]);
             final int alErr = al.alGetError();
-            if(al.alGetError() != AL.AL_NO_ERROR) {
-                throw new RuntimeException("ALError "+toHexString(alErr)+" while pausing. "+this);
+            if( AL.AL_NO_ERROR != alErr ) {
+                final String msg = "ALError "+toHexString(alErr)+" while stopping. "+this;
+                if( ignoreError ) {
+                    if( DEBUG ) {
+                        System.err.println(getThreadName()+": "+msg);
+                    }
+                } else {
+                    throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while stopping. "+this);
+                }
             }
         }
     }
@@ -794,15 +883,14 @@ public class ALAudioSink implements AudioSink {
         lockContext();
         try {
             // pauseImpl();
-            stopImpl();
-            al.alSourcei(alSource[0], AL.AL_BUFFER, 0); // explicit force zero buffer!
-            dequeueBuffer( false /* wait */ );
+            stopImpl(false);
+            // Redundant: dequeueBuffer( false /* wait */, true /* ignoreBufferInconsistency */);
             dequeueForceAll();
             if( alBufferNames.length != alFramesAvail.size() || alFramesPlaying.size() != 0 ) {
                 throw new InternalError("XXX: "+this);
             }
             if( DEBUG ) {
-                System.err.println(getThreadName()+": ALAudioSink: FLUSH playImpl "+(AL.AL_PLAYING == getSourceState())+", "+this);
+                System.err.println(getThreadName()+": ALAudioSink: FLUSH playImpl "+(AL.AL_PLAYING == getSourceState(false))+", "+this);
             }
         } finally {
             unlockContext();
diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
index 7cea51d..6a0e006 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
@@ -1127,7 +1127,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
                     if( isBlocked && isActive ) {
                         this.interrupt();
                     }
-                    while( isActive ) {
+                    while( isActive && isRunning ) {
                         try {
                             this.wait(); // wait until paused
                         } catch (InterruptedException e) {
@@ -1141,7 +1141,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
             if( isRunning && !isActive ) {
                 shallPause = false;
                 if( Thread.currentThread() != this ) {
-                    while( !isActive ) {
+                    while( !isActive && !shallPause && isRunning ) {
                         this.notifyAll();  // wake-up pause-block
                         try {
                             this.wait(); // wait until resumed
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
index bc0865a..b4b887b 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
@@ -29,17 +29,22 @@ package jogamp.opengl.util.av.impl;
 
 import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
 
-interface FFMPEGNatives {
+/* pp */ abstract class FFMPEGNatives {
 
-    boolean initSymbols0(long[] symbols, int count);
-    int getAvUtilMajorVersionCC0();
-    int getAvFormatMajorVersionCC0();
-    int getAvCodecMajorVersionCC0();
-    int getAvResampleMajorVersionCC0();
-    int getSwResampleMajorVersionCC0();
+    private static final Object mutex_avcodec_openclose_jni = new Object();
 
-    long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
-    void destroyInstance0(long moviePtr);
+    final boolean initSymbols0(long[] symbols, int count) {
+        return initSymbols0(mutex_avcodec_openclose_jni, symbols, count);
+    }
+    abstract boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
+    abstract int getAvUtilMajorVersionCC0();
+    abstract int getAvFormatMajorVersionCC0();
+    abstract int getAvCodecMajorVersionCC0();
+    abstract int getAvResampleMajorVersionCC0();
+    abstract int getSwResampleMajorVersionCC0();
+
+    abstract long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+    abstract void destroyInstance0(long moviePtr);
 
     /**
      * Issues {@link #updateAttributes(int, int, int, int, int, int, int, float, int, int, String, String)}
@@ -56,24 +61,24 @@ interface FFMPEGNatives {
      * @param aPrefSampleRate
      * @param aPrefChannelCount
      */
-    void setStream0(long moviePtr, String url, boolean isCameraInput,
-                    int vid, String sizes, int vWidth, int vHeight,
-                    int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+    abstract void setStream0(long moviePtr, String url, boolean isCameraInput,
+                             int vid, String sizes, int vWidth, int vHeight,
+                             int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
 
-    void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+    abstract void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
 
-    int getVideoPTS0(long moviePtr);
+    abstract int getVideoPTS0(long moviePtr);
 
-    int getAudioPTS0(long moviePtr);
+    abstract int getAudioPTS0(long moviePtr);
 
     /**
      * @return resulting current video PTS, or {@link TextureFrame#INVALID_PTS}
      */
-    int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+    abstract int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
 
-    int play0(long moviePtr);
-    int pause0(long moviePtr);
-    int seek0(long moviePtr, int position);
+    abstract int play0(long moviePtr);
+    abstract int pause0(long moviePtr);
+    abstract int seek0(long moviePtr, int position);
 
     /** FFMPEG/libAV Audio Sample Format */
     public static enum SampleFormat {
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
index 4b013c1..6bab23f 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
@@ -27,52 +27,52 @@
  */
 package jogamp.opengl.util.av.impl;
 
-class FFMPEGv08Natives implements FFMPEGNatives {
+class FFMPEGv08Natives extends FFMPEGNatives {
     @Override
-    public native boolean initSymbols0(long[] symbols, int count);
+    native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
 
     @Override
-    public native int getAvUtilMajorVersionCC0();
+    native int getAvUtilMajorVersionCC0();
 
     @Override
-    public native int getAvFormatMajorVersionCC0();
+    native int getAvFormatMajorVersionCC0();
 
     @Override
-    public native int getAvCodecMajorVersionCC0();
+    native int getAvCodecMajorVersionCC0();
 
     @Override
-    public native int getAvResampleMajorVersionCC0();
+    native int getAvResampleMajorVersionCC0();
 
     @Override
-    public native int getSwResampleMajorVersionCC0();
+    native int getSwResampleMajorVersionCC0();
 
     @Override
-    public native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+    native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
 
     @Override
-    public native void destroyInstance0(long moviePtr);
+    native void destroyInstance0(long moviePtr);
 
     @Override
-    public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+    native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
 
     @Override
-    public native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+    native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
 
     @Override
-    public native int getVideoPTS0(long moviePtr);
+    native int getVideoPTS0(long moviePtr);
 
     @Override
-    public native int getAudioPTS0(long moviePtr);
+    native int getAudioPTS0(long moviePtr);
 
     @Override
-    public native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+    native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
 
     @Override
-    public native int play0(long moviePtr);
+    native int play0(long moviePtr);
 
     @Override
-    public native int pause0(long moviePtr);
+    native int pause0(long moviePtr);
 
     @Override
-    public native int seek0(long moviePtr, int position);
+    native int seek0(long moviePtr, int position);
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
index d697632..a48b5f2 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
@@ -27,52 +27,52 @@
  */
 package jogamp.opengl.util.av.impl;
 
-class FFMPEGv09Natives implements FFMPEGNatives {
+class FFMPEGv09Natives extends FFMPEGNatives {
     @Override
-    public native boolean initSymbols0(long[] symbols, int count);
+    native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
 
     @Override
-    public native int getAvUtilMajorVersionCC0();
+    native int getAvUtilMajorVersionCC0();
 
     @Override
-    public native int getAvFormatMajorVersionCC0();
+    native int getAvFormatMajorVersionCC0();
 
     @Override
-    public native int getAvCodecMajorVersionCC0();
+    native int getAvCodecMajorVersionCC0();
 
     @Override
-    public native int getAvResampleMajorVersionCC0();
+    native int getAvResampleMajorVersionCC0();
 
     @Override
-    public native int getSwResampleMajorVersionCC0();
+    native int getSwResampleMajorVersionCC0();
 
     @Override
-    public native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+    native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
 
     @Override
-    public native void destroyInstance0(long moviePtr);
+    native void destroyInstance0(long moviePtr);
 
     @Override
-    public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+    native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
 
     @Override
-    public native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+    native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
 
     @Override
-    public native int getVideoPTS0(long moviePtr);
+    native int getVideoPTS0(long moviePtr);
 
     @Override
-    public native int getAudioPTS0(long moviePtr);
+    native int getAudioPTS0(long moviePtr);
 
     @Override
-    public native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+    native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
 
     @Override
-    public native int play0(long moviePtr);
+    native int play0(long moviePtr);
 
     @Override
-    public native int pause0(long moviePtr);
+    native int pause0(long moviePtr);
 
     @Override
-    public native int seek0(long moviePtr, int position);
+    native int seek0(long moviePtr, int position);
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java
index 0b5f70d..f35fb29 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java
@@ -27,52 +27,52 @@
  */
 package jogamp.opengl.util.av.impl;
 
-class FFMPEGv10Natives implements FFMPEGNatives {
+class FFMPEGv10Natives extends FFMPEGNatives {
     @Override
-    public native boolean initSymbols0(long[] symbols, int count);
+    native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count);
 
     @Override
-    public native int getAvUtilMajorVersionCC0();
+    native int getAvUtilMajorVersionCC0();
 
     @Override
-    public native int getAvFormatMajorVersionCC0();
+    native int getAvFormatMajorVersionCC0();
 
     @Override
-    public native int getAvCodecMajorVersionCC0();
+    native int getAvCodecMajorVersionCC0();
 
     @Override
-    public native int getAvResampleMajorVersionCC0();
+    native int getAvResampleMajorVersionCC0();
 
     @Override
-    public native int getSwResampleMajorVersionCC0();
+    native int getSwResampleMajorVersionCC0();
 
     @Override
-    public native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+    native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
 
     @Override
-    public native void destroyInstance0(long moviePtr);
+    native void destroyInstance0(long moviePtr);
 
     @Override
-    public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+    native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
 
     @Override
-    public native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+    native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
 
     @Override
-    public native int getVideoPTS0(long moviePtr);
+    native int getVideoPTS0(long moviePtr);
 
     @Override
-    public native int getAudioPTS0(long moviePtr);
+    native int getAudioPTS0(long moviePtr);
 
     @Override
-    public native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+    native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
 
     @Override
-    public native int play0(long moviePtr);
+    native int play0(long moviePtr);
 
     @Override
-    public native int pause0(long moviePtr);
+    native int pause0(long moviePtr);
 
     @Override
-    public native int seek0(long moviePtr, int position);
+    native int seek0(long moviePtr, int position);
 }
diff --git a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
index d5b01ef..45087ea 100644
--- a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
+++ b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
@@ -56,7 +56,6 @@
 
 package jogamp.opengl.util.jpeg;
 
-import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -65,6 +64,7 @@ import java.util.Arrays;
 import jogamp.opengl.Debug;
 
 import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.Bitstream;
 import com.jogamp.common.util.VersionNumber;
 import com.jogamp.opengl.util.texture.TextureData;
 import com.jogamp.opengl.util.texture.TextureData.ColorSpace;
@@ -446,9 +446,7 @@ public class JPEGDecoder {
         return "JPEG[size "+width+"x"+height+", compOut "+compOuts+", "+jfifS+", "+exifS+", "+adobeS+"]";
     }
 
-    private BufferedInputStream istream;
-    private int _ipos = 0;
-    private int _iposSave = 0;
+    private final Bitstream<InputStream> bstream = new Bitstream<InputStream>(new Bitstream.ByteInputStream(null), false /* outputMode */);
 
     private int width = 0;
     private int height = 0;
@@ -463,66 +461,36 @@ public class JPEGDecoder {
     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);
+    private final void setStream(InputStream is) {
+        try {
+            bstream.setStream(is, false /* outputMode */);
+        } catch (Exception e) {
+            throw new RuntimeException(e); // should not happen, no flush()
         }
-        _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 readUInt8() throws IOException {
+        return bstream.readUInt8(true /* msbFirst */);
     }
 
-    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 readUInt16() throws IOException {
+        return bstream.readUInt16(true /* msbFirst */, true /* bigEndian */);
     }
 
     private final int readNumber() throws IOException {
-        final int len=readUint16();
+        final int len=readUInt16();
         if(len!=4){
             throw new CodecException("ERROR: Define number format error [Len!=4, but "+len+"]");
         }
-        return readUint16();
+        return readUInt16();
     }
 
     private final byte[] readDataBlock() throws IOException {
         int count=0, i=0;
-        final int len=readUint16();   count+=2;
+        final int len=readUInt16();   count+=2;
         byte[] data = new byte[len-2];
         while(count<len){
-            data[i++] = (byte)readUint8(); count++;
+            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;
@@ -531,14 +499,14 @@ public class JPEGDecoder {
         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.print(toHexString(0x000000FF & data[offset+i])+", ");
             }
             System.err.println("");
         }
     }
 
     public synchronized void clear(InputStream inputStream) {
-        resetInput(inputStream);
+        setStream(inputStream);
         width = 0;
         height = 0;
         jfif = null;
@@ -556,12 +524,12 @@ public class JPEGDecoder {
 
         Frame frame = null;
         int resetInterval = 0;
-        int fileMarker = readUint16();
+        int fileMarker = readUInt16();
         if ( fileMarker != M_SOI ) {
             throw new CodecException("SOI not found, but has marker "+toHexString(fileMarker));
         }
 
-        fileMarker = readUint16();
+        fileMarker = readUInt16();
         while (fileMarker != M_EOI) {
             if(DEBUG) { System.err.println("JPG.parse got marker "+toHexString(fileMarker)); }
             switch(fileMarker) {
@@ -599,21 +567,21 @@ public class JPEGDecoder {
 
             case M_QTT: {
                 int count = 0;
-                final int quantizationTablesLength = readUint16(); count+=2;
+                final int quantizationTablesLength = readUInt16(); count+=2;
                 while( count < quantizationTablesLength ) {
-                    final int quantizationTableSpec = readUint8(); count++;
+                    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++;
+                            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;
+                            tableData[z] = readUInt16(); count+=2;
                         }
                     } else {
                         throw new CodecException("DQT: invalid table precision "+precisionID+", quantizationTableSpec "+quantizationTableSpec+", idx "+tableIdx);
@@ -636,24 +604,24 @@ public class JPEGDecoder {
                     throw new CodecException("only single frame JPEGs supported");
                 }
                 int count = 0;
-                final int sofLen = readUint16(); count+=2; // header length;
+                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++;
+                    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 componentId = readUInt8(); count++;
+                    final int temp = readUInt8(); count++;
                     final int h = temp >> 4;
                     final int v = temp & 0x0F;
-                    final int qttIdx = readUint8(); count++;
+                    final int qttIdx = readUInt8(); count++;
                     final ComponentIn compIn = new ComponentIn(h, v, qttIdx);
                     frame.putOrdered(componentId, compIn);
                 }
@@ -669,18 +637,18 @@ public class JPEGDecoder {
 
             case M_DHT: {
                 int count = 0;
-                final int huffmanLength = readUint16(); count+=2;
+                final int huffmanLength = readUInt16(); count+=2;
                 int i=count, codeLengthTotal = 0;
                 while( i < huffmanLength ) {
-                    final int huffmanTableSpec = readUint8(); count++;
+                    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++;
+                        codeLengthSum += (codeLengths[j] = readUInt8()); count++;
                     }
                     final byte[] huffmanValues = new byte[codeLengthSum];
                     for (int j = 0; j < codeLengthSum; j++) {
-                        huffmanValues[j] = (byte)readUint8(); count++;
+                        huffmanValues[j] = (byte)readUInt8(); count++;
                     }
                     codeLengthTotal += codeLengthSum;
                     i += 17 + codeLengthSum;
@@ -703,21 +671,21 @@ public class JPEGDecoder {
 
             case M_SOS: {
                 int count = 0;
-                final int sosLen = readUint16(); count+=2;
-                final int selectorsCount = readUint8(); count++;
+                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 int compID = readUInt8(); count++;
                     final ComponentIn component = frame.getCompByID(compID);
-                    final int tableSpec = readUint8(); count++;
+                    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++;
+                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]");
                 }
@@ -736,10 +704,10 @@ public class JPEGDecoder {
                     offset -= 3;
                     break;
                 } */
-                throw new CodecException("unknown JPEG marker " + toHexString(fileMarker));
+                throw new CodecException("unknown JPEG marker " + toHexString(fileMarker) + ", " + bstream);
             }
             if( 0 == fileMarker ) {
-                fileMarker = readUint16();
+                fileMarker = readUInt16();
             }
         }
         if(DEBUG) { System.err.println("JPG.parse.2: End of parsing input "+this); }
@@ -775,13 +743,13 @@ public class JPEGDecoder {
             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);
+        int mcusPerLine = (int) Math.ceil(frame.samplesPerLine / 8f / maxH);
+        int mcusPerColumn = (int) Math.ceil(frame.scanLines / 8f / 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 blocksPerLine = (int) Math.ceil(Math.ceil(frame.samplesPerLine / 8f) * component.h / maxH);
+            final int blocksPerColumn = (int) Math.ceil(Math.ceil(frame.scanLines  / 8f) * component.v / maxV);
             final int blocksPerLineForMcu = mcusPerLine * component.h;
             final int blocksPerColumnForMcu = mcusPerColumn * component.v;
             component.allocateBlocks(blocksPerColumn, blocksPerColumnForMcu, blocksPerLine, blocksPerLineForMcu);
@@ -1066,7 +1034,6 @@ public class JPEGDecoder {
         private int mcusPerLine;
         private boolean progressive;
         // private int maxH, maxV;
-        private int bitsData, bitsCount;
         private int spectralStart, spectralEnd;
         private int successive;
         private int eobrun;
@@ -1081,8 +1048,7 @@ public class JPEGDecoder {
             this.progressive = frame.progressive;
             // this.maxH = frame.maxH;
             // this.maxV = frame.maxV;
-            this.bitsData = 0;
-            this.bitsCount = 0;
+            bstream.skip( bstream.getBitCount() ); // align to next byte
             this.spectralStart = spectralStart;
             this.spectralEnd = spectralEnd;
             this.successive = successive;
@@ -1149,16 +1115,16 @@ public class JPEGDecoder {
                     return markerException.getMarker();
                 } catch (CodecException codecException) {
                     if(DEBUG) { System.err.println("JPEG.decodeScan: Codec exception: "+codecException.getMessage()); codecException.printStackTrace(); }
-                    bitsCount = 0;
+                    bstream.skip( bstream.getBitCount() ); // align to next byte
                     return M_EOI; // force end !
                 }
 
                 // find marker
-                bitsCount = 0;
-                markStream(2);
-                marker = readUint16();
+                bstream.skip( bstream.getBitCount() ); // align to next byte
+                bstream.mark(2);
+                marker = readUInt16();
                 if( marker < 0xFF00 ) {
-                    rewindStream();
+                    bstream.reset();
                     throw new CodecException("marker not found @ mcu "+mcu+"/"+mcuExpected+", u16: "+toHexString(marker));
                 }
                 final boolean isRSTx = 0xFFD0 <= marker && marker <= 0xFFD7; // !RSTx
@@ -1172,28 +1138,25 @@ public class JPEGDecoder {
             return marker;
         }
 
-        private int readBit() throws MarkerException, IOException {
-            if (bitsCount > 0) {
-                bitsCount--;
-                return (bitsData >> bitsCount) & 1;
-            }
-            bitsData = readUint8();
-            if( -1 == bitsData ) {
-                return -1;
+        private final int readBit() throws MarkerException, IOException {
+            final int bit = bstream.readBit(true /* msbFirst */);
+            if( Bitstream.EOS == bit || 7 != bstream.getBitCount() ) {
+                return bit;
             }
-            if (bitsData == 0xFF) { // marker prefix
-                final int nextByte = readUint8(); // marker signature
+            // new byte read, i.e. bitCount == 7
+            final int bitsData = bstream.getBitBuffer(); // peek for marker
+            if ( 0xFF == bitsData ) { // marker prefix
+                final int nextByte = bstream.getStream().read(); // snoop marker signature, will be dropped!
                 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);
+                    throw new MarkerException(marker, "Marker at readBit pos " + bstream);
                 }
                 // unstuff 0
             }
-            bitsCount = 7;
-            return bitsData >>> 7;
+            return bit;
         }
 
         private int decodeHuffman(BinObj tree) throws IOException {
@@ -1205,7 +1168,7 @@ public class JPEGDecoder {
                     return 0x000000FF & node.getValue();
                 }
             }
-            throw new CodecException("EOF reached at "+_ipos);
+            throw new CodecException("EOF reached at "+bstream);
         }
         private int receive(int length) throws IOException {
             int n = 0;
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
index ee3e1a3..c0a3b46 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
@@ -254,7 +254,13 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
     int val = 0;
 
     final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
-    int fbtype = glXGetFBConfig(device.getHandle(), fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp);
+    if( !glXGetFBConfig(device.getHandle(), fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp) ) {
+        if(DEBUG) {
+            System.err.println("X11GLXGraphicsConfiguration.FBCfgDrawableTypeBits: FBConfig invalid: fbcfg: "+toHexString(fbcfg));
+        }
+        return 0;
+    }
+    final int fbtype = tmp.get(0);
 
     if ( 0 != ( fbtype & GLX.GLX_WINDOW_BIT ) ) {
         val |= GLGraphicsConfigurationUtil.WINDOW_BIT |
@@ -314,8 +320,19 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
     final long display = device.getHandle();
     final int allDrawableTypeBits = FBCfgDrawableTypeBits(device, fbcfg);
     int drawableTypeBits = winattrmask & allDrawableTypeBits;
-
+    if( 0 == allDrawableTypeBits || 0 == drawableTypeBits ) {
+      if(DEBUG) {
+          System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: zero drawablebits: allDrawableTypeBits: "+toHexString(allDrawableTypeBits)+", drawableTypeBits "+toHexString(drawableTypeBits));
+      }
+      return null;
+    }
     final int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg);
+    if( VisualIDHolder.VID_UNDEFINED == fbcfgid ) {
+      if(DEBUG) {
+          System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: FBConfig invalid (0): fbcfg: "+toHexString(fbcfg));
+      }
+      return null;
+    }
     final XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg);
     if(null == visualInfo) {
         if(DEBUG) {
@@ -415,20 +432,26 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
     }
   }
 
-  static int glXGetFBConfig(long display, long cfg, int attrib, IntBuffer tmp) {
+  static boolean glXGetFBConfig(long display, long cfg, int attrib, IntBuffer tmp) {
     if (display == 0) {
       throw new GLException("No display connection");
     }
-    int res = GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp);
-    if (res != 0) {
-      throw new GLException("glXGetFBConfig("+toHexString(attrib)+") failed: error code " + glXGetFBConfigErrorCode(res));
+    final boolean res = GLX.GLX_BAD_ATTRIBUTE != GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp);
+    if( !res ) {
+        if(DEBUG) {
+            System.err.println("X11GLXGraphicsConfiguration.glXGetFBConfig: FBConfig invalid: fbcfg: "+toHexString(cfg));
+        }
     }
-    return tmp.get(tmp.position());
+    return res;
   }
 
   static int glXFBConfig2FBConfigID(long display, long cfg) {
       final IntBuffer tmpID = Buffers.newDirectIntBuffer(1);
-      return glXGetFBConfig(display, cfg, GLX.GLX_FBCONFIG_ID, tmpID);
+      if( glXGetFBConfig(display, cfg, GLX.GLX_FBCONFIG_ID, tmpID) ) {
+          return tmpID.get(0);
+      } else {
+          return VisualIDHolder.VID_UNDEFINED; // error
+      }
   }
 
   static long glXFBConfigID2FBConfig(long display, int screen, int id) {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
index 1f92960..75771f8 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
@@ -258,13 +258,19 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
         final long fbcfg = X11GLXGraphicsConfiguration.glXFBConfigID2FBConfig(display, screen, fbID);
         if( 0 == fbcfg || !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfg ) ) {
             if(DEBUG) {
-                System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed - GLX FBConfig invalid: ("+x11Screen+","+toHexString(fbID)+"): fbcfg: "+toHexString(fbcfg));
+                System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed.0 - GLX FBConfig invalid: ("+x11Screen+","+toHexString(fbID)+"): fbcfg: "+toHexString(fbcfg));
             }
             return null;
         }
         final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
 
         final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glp, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, factory.isGLXMultisampleAvailable(x11Device));
+        if(null==caps) {
+            if(DEBUG) {
+                System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed.1 - GLX FBConfig invalid: ("+x11Screen+","+toHexString(fbID)+"): fbcfg: "+toHexString(fbcfg));
+            }
+            return null;
+        }
         return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser());
     }
 
diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c
index e86b2a5..a7e9f48 100644
--- a/src/jogl/native/libav/ffmpeg_impl_template.c
+++ b/src/jogl/native/libav/ffmpeg_impl_template.c
@@ -200,11 +200,36 @@ static SWR_FREE sp_swr_free;
 static SWR_CONVERT sp_swr_convert;
 // count: 65
 
+// We use JNI Monitor Locking, since this removes the need 
+// to statically link-in pthreads on window ..
+// #define USE_PTHREAD_LOCKING 1
+//
+#define USE_JNI_LOCKING 1
+
+#if defined (USE_PTHREAD_LOCKING)
+    #include <pthread.h>
+    #warning USE LOCKING PTHREAD
+    static pthread_mutex_t mutex_avcodec_openclose;
+    #define MY_MUTEX_LOCK(e,s) pthread_mutex_lock(&(s))
+    #define MY_MUTEX_UNLOCK(e,s) pthread_mutex_unlock(&(s))
+#elif defined (USE_JNI_LOCKING)
+    static jobject mutex_avcodec_openclose;
+    #define MY_MUTEX_LOCK(e,s) (*e)->MonitorEnter(e, s)
+    #define MY_MUTEX_UNLOCK(e,s) (*e)->MonitorExit(e, s)
+#else
+    #warning USE LOCKING NONE
+    #define MY_MUTEX_LOCK(e,s)
+    #define MY_MUTEX_UNLOCK(e,s)
+#endif
+
 #define SYMBOL_COUNT 65
 
 JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0)
-  (JNIEnv *env, jobject instance, jobject jSymbols, jint count)
+  (JNIEnv *env, jobject instance, jobject jmutex_avcodec_openclose, jobject jSymbols, jint count)
 {
+    #ifdef USE_PTHREAD_LOCKING
+        pthread_mutexattr_t renderLockAttr;
+    #endif
     int64_t* symbols; // jlong -> int64_t -> intptr_t -> FUNC_PTR
     int i;
 
@@ -315,6 +340,23 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0)
         }
     #endif
 
+    #if defined (USE_PTHREAD_LOCKING)
+        pthread_mutexattr_init(&renderLockAttr);
+        pthread_mutexattr_settype(&renderLockAttr, PTHREAD_MUTEX_RECURSIVE);
+        pthread_mutex_init(&mutex_avcodec_openclose, &renderLockAttr); // recursive
+    #elif defined (USE_JNI_LOCKING)
+        mutex_avcodec_openclose = (*env)->NewGlobalRef(env, jmutex_avcodec_openclose);
+    #endif
+
+    /** At static destroy: Never
+    #if defined (USE_PTHREAD_LOCKING)
+        pthread_mutex_unlock(&mutex_avcodec_openclose);
+        pthread_mutex_destroy(&mutex_avcodec_openclose);
+    #elif defined (USE_JNI_LOCKING)
+        (*env)->DeleteGlobalRef(env, mutex_avcodec_openclose);
+    #endif
+    */
+
     return JNI_TRUE;
 }
 
@@ -361,19 +403,23 @@ static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
             pAV->aResampleBuffer = NULL;
         }
 
-        // Close the V codec
-        if(NULL != pAV->pVCodecCtx) {
-            sp_avcodec_close(pAV->pVCodecCtx);
-            pAV->pVCodecCtx = NULL;
-        }
-        pAV->pVCodec=NULL;
+        MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+        {
+            // Close the V codec
+            if(NULL != pAV->pVCodecCtx) {
+                sp_avcodec_close(pAV->pVCodecCtx);
+                pAV->pVCodecCtx = NULL;
+            }
+            pAV->pVCodec=NULL;
 
-        // Close the A codec
-        if(NULL != pAV->pACodecCtx) {
-            sp_avcodec_close(pAV->pACodecCtx);
-            pAV->pACodecCtx = NULL;
+            // Close the A codec
+            if(NULL != pAV->pACodecCtx) {
+                sp_avcodec_close(pAV->pACodecCtx);
+                pAV->pACodecCtx = NULL;
+            }
+            pAV->pACodec=NULL;
         }
-        pAV->pACodec=NULL;
+        MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
 
         // Close the frames
         if(NULL != pAV->pVFrame) {
@@ -421,6 +467,7 @@ static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
             (*env)->DeleteGlobalRef(env, pAV->ffmpegMediaPlayer);
             pAV->ffmpegMediaPlayer = NULL;
         }
+
         free(pAV);
     }
 }
@@ -709,22 +756,29 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
             sp_av_dict_set(&inOpts, "framerate", buffer, 0);
         }
     }
-    res = sp_avformat_open_input(&pAV->pFormatCtx, filename, inFmt, NULL != inOpts ? &inOpts : NULL);
-    if( NULL != inOpts ) {
-        sp_av_dict_free(&inOpts);
-    }
-    if(res != 0) {
-        JoglCommon_throwNewRuntimeException(env, "Couldn't open URI: %s [%dx%d @ %d hz], err %d", filename, vWidth, vHeight, vRate, res);
-        (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
-        return;
-    }
 
-    // Retrieve detailed stream information
-    if(sp_avformat_find_stream_info(pAV->pFormatCtx, NULL)<0) {
-        (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
-        JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information");
-        return;
+    MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+    {
+        res = sp_avformat_open_input(&pAV->pFormatCtx, filename, inFmt, NULL != inOpts ? &inOpts : NULL);
+        if( NULL != inOpts ) {
+            sp_av_dict_free(&inOpts);
+        }
+        if(res != 0) {
+            MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
+            JoglCommon_throwNewRuntimeException(env, "Couldn't open URI: %s [%dx%d @ %d hz], err %d", filename, vWidth, vHeight, vRate, res);
+            (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
+            return;
+        }
+
+        // Retrieve detailed stream information
+        if(sp_avformat_find_stream_info(pAV->pFormatCtx, NULL)<0) {
+            MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
+            (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
+            JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information");
+            return;
+        }
     }
+    MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
 
     if(pAV->verbose) {
         // Dump information about file onto standard error
@@ -732,7 +786,6 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
     }
     (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
 
-
     // FIXME: Libav Binary compatibility! JAU01
     if (pAV->pFormatCtx->duration != AV_NOPTS_VALUE) {
         pAV->duration = pAV->pFormatCtx->duration / AV_TIME_BASE_MSEC;
@@ -824,10 +877,14 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
         }
 
         // Open codec
-        #if LIBAVCODEC_VERSION_MAJOR >= 55
-            pAV->pACodecCtx->refcounted_frames = pAV->useRefCountedFrames;
-        #endif
-        res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL);
+        MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+        {
+            #if LIBAVCODEC_VERSION_MAJOR >= 55
+                pAV->pACodecCtx->refcounted_frames = pAV->useRefCountedFrames;
+            #endif
+            res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL);
+        }
+        MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
         if(res<0) {
             JoglCommon_throwNewRuntimeException(env, "Couldn't open audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec);
             return;
@@ -982,10 +1039,14 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
         }
 
         // Open codec
-        #if LIBAVCODEC_VERSION_MAJOR >= 55
-            pAV->pVCodecCtx->refcounted_frames = pAV->useRefCountedFrames;
-        #endif
-        res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL);
+        MY_MUTEX_LOCK(env, mutex_avcodec_openclose);
+        {
+            #if LIBAVCODEC_VERSION_MAJOR >= 55
+                pAV->pVCodecCtx->refcounted_frames = pAV->useRefCountedFrames;
+            #endif
+            res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL);
+        }
+        MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose);
         if(res<0) {
             JoglCommon_throwNewRuntimeException(env, "Couldn't open video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec);
             return;
diff --git a/src/jogl/native/libav/ffmpeg_tool.h b/src/jogl/native/libav/ffmpeg_tool.h
index 97e60af..136be2e 100644
--- a/src/jogl/native/libav/ffmpeg_tool.h
+++ b/src/jogl/native/libav/ffmpeg_tool.h
@@ -130,7 +130,6 @@ typedef struct {
     int64_t dtsLast;  // DTS of the last frame
 } PTSStats;
 
-
 typedef struct {
     jobject          ffmpegMediaPlayer;
     int32_t          verbose;
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index a57dafc..bb7b447 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -432,36 +432,15 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
   public final boolean hideCursor() {
       AWTEDTExecutor.singleton.invoke(false, new Runnable() {
           public void run() {
-              component.setCursor(AWTMisc.getNullCursor());
+              final Cursor cursor = AWTMisc.getNullCursor();
+              if( null != cursor ) {
+                  component.setCursor(cursor);
+              }
           } } );
       return true;
   }
 
   //
-  // SurfaceUpdateListener
-  //
-
-  @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);
-  }
-
-  //
   // NativeSurface
   //
 
@@ -572,6 +551,26 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
   }
 
   @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);
+  }
+
+  @Override
   public long getSurfaceHandle() {
     return drawable;
   }
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index 15a43cf..034bf24 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -43,7 +43,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import javax.media.nativewindow.util.Point;
 import javax.media.nativewindow.util.PointImmutable;
 
 import jogamp.nativewindow.Debug;
@@ -462,7 +461,7 @@ public abstract class NativeWindowFactory {
      * @see #getDefaultToolkitLock(java.lang.String)
      */
     public static ToolkitLock getDefaultToolkitLock() {
-        return getDefaultToolkitLock(getNativeWindowType(false));
+        return getDefaultToolkitLock(nativeWindowingTypePure);
     }
 
     /**
@@ -655,8 +654,16 @@ public abstract class NativeWindowFactory {
             return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
         } else if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
             return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+        /**
+         * FIXME: Needs service provider interface (SPI) for TK dependent implementation
+        } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+        } else if( NativeWindowFactory.TYPE_ANDROID== nwt ) {
+        } else if( NativeWindowFactory.TYPE_EGL == nwt ) {
+        } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+        } else if( NativeWindowFactory.TYPE_AWT == nwt ) {
+        */
         }
-        throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
+        throw new UnsupportedOperationException("n/a for windowing system: "+nwt);
     }
 
     /**
@@ -687,8 +694,16 @@ public abstract class NativeWindowFactory {
             return GDIUtil.GetRelativeLocation(nw.getWindowHandle(), 0, 0, 0);
         } else if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
             return OSXUtil.GetLocationOnScreen(nw.getWindowHandle(), null == nw.getParent(), 0, 0);
+        /**
+         * FIXME: Needs service provider interface (SPI) for TK dependent implementation
+        } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+        } else if( NativeWindowFactory.TYPE_ANDROID== nwt ) {
+        } else if( NativeWindowFactory.TYPE_EGL == nwt ) {
+        } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+        } else if( NativeWindowFactory.TYPE_AWT == nwt ) {
+            */
         }
-        throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
+        throw new UnsupportedOperationException("n/a for windowing system: "+nwt);
     }
 
 
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
index 361d034..87a9ca4 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
@@ -208,7 +208,6 @@ public class PixelFormatUtil {
         return convertToInt32(dest_fmt, r, g, b, a);
     }
 
-    /**
     public static int convertToInt32(PixelFormat dest_fmt, PixelFormat src_fmt, final int src_pixel) {
         final byte r, g, b, a;
         switch(src_fmt) {
@@ -258,7 +257,7 @@ public class PixelFormatUtil {
                 throw new InternalError("Unhandled format "+src_fmt);
         }
         return convertToInt32(dest_fmt, r, g, b, a);
-    } */
+    }
 
     public static PixelRectangle convert32(final PixelRectangle src,
                                            final PixelFormat destFmt, int ddestStride, final boolean isGLOriented,
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
index 1e83232..0b03395 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
@@ -36,22 +36,23 @@ import javax.media.nativewindow.SurfaceUpdatedListener;
 public class SurfaceUpdatedHelper implements SurfaceUpdatedListener {
     private final Object surfaceUpdatedListenersLock = new Object();
     private final ArrayList<SurfaceUpdatedListener> surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>();
+    private volatile boolean isEmpty = true;
 
     //
     // Management Utils
     //
-    public int size() { return surfaceUpdatedListeners.size(); }
-    public SurfaceUpdatedListener get(int i) { return surfaceUpdatedListeners.get(i); }
+    public final int size() { return surfaceUpdatedListeners.size(); }
+    public final SurfaceUpdatedListener get(int i) { return surfaceUpdatedListeners.get(i); }
 
     //
     // Implementation of NativeSurface SurfaceUpdatedListener methods
     //
 
-    public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+    public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
         addSurfaceUpdatedListener(-1, l);
     }
 
-    public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l)
+    public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l)
         throws IndexOutOfBoundsException
     {
         if(l == null) {
@@ -62,23 +63,29 @@ public class SurfaceUpdatedHelper implements SurfaceUpdatedListener {
                 index = surfaceUpdatedListeners.size();
             }
             surfaceUpdatedListeners.add(index, l);
+            isEmpty = false;
         }
     }
 
-    public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+    public final boolean removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
         if (l == null) {
-            return;
+            return false;
         }
         synchronized(surfaceUpdatedListenersLock) {
-            surfaceUpdatedListeners.remove(l);
+            final boolean res = surfaceUpdatedListeners.remove(l);
+            isEmpty = 0 == surfaceUpdatedListeners.size();
+            return res;
         }
     }
 
     @Override
-    public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+    public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+        if( isEmpty ) {
+            return;
+        }
         synchronized(surfaceUpdatedListenersLock) {
           for(int i = 0; i < surfaceUpdatedListeners.size(); i++ ) {
-            SurfaceUpdatedListener l = surfaceUpdatedListeners.get(i);
+            final SurfaceUpdatedListener l = surfaceUpdatedListeners.get(i);
             l.surfaceUpdated(updater, ns, when);
           }
         }
diff --git a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
index 069cffe..7389360 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
@@ -50,6 +50,8 @@ import javax.media.nativewindow.util.PixelFormat;
 import javax.media.nativewindow.util.PixelFormatUtil;
 import javax.swing.MenuSelectionManager;
 
+import jogamp.nativewindow.jawt.JAWTUtil;
+
 public class AWTMisc {
 
     public static JFrame getJFrame(Component c) {
@@ -174,9 +176,20 @@ public class AWTMisc {
     static final HashMap<Integer, Cursor> cursorMap = new HashMap<Integer, Cursor>();
     static final Cursor nulCursor;
     static {
-        final Toolkit toolkit = Toolkit.getDefaultToolkit();
-        final BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
-        nulCursor = toolkit.createCustomCursor(img, new Point(0,0), "nullCursor");
+        Cursor _nulCursor = null;
+        if( !JAWTUtil.isHeadlessMode() ) {
+            try {
+                final Toolkit toolkit = Toolkit.getDefaultToolkit();
+                final BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
+                _nulCursor = toolkit.createCustomCursor(img, new Point(0,0), "nullCursor");
+            } catch (Exception he) {
+                if( JAWTUtil.DEBUG ) {
+                    System.err.println("Catched exception: "+he.getMessage());
+                    he.printStackTrace();
+                }
+            }
+        }
+        nulCursor = _nulCursor;
     }
 
     public static synchronized Cursor getNullCursor() { return nulCursor; }
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
index 5a1d915..d4edf2b 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
@@ -296,60 +296,71 @@ public class JAWTUtil {
         System.err.println("JAWTUtil initialization (JAWT/JNI/...");
         // Thread.dumpStack();
     }
-    JAWTJNILibLoader.initSingleton();
-    if(!JAWTJNILibLoader.loadNativeWindow("awt")) {
-        throw new NativeWindowException("NativeWindow AWT native library load error.");
-    }
 
     headlessMode = GraphicsEnvironment.isHeadless();
-    boolean ok = false;
-    Class<?> jC = null;
-    Method m = null;
-    if (!headlessMode) {
+
+    if( headlessMode ) {
+        // Headless case
+        jawtLockObject = null;
+        isQueueFlusherThread = null;
+        j2dExist = false;
+        sunToolkitAWTLockMethod = null;
+        sunToolkitAWTUnlockMethod = null;
+        hasSunToolkitAWTLock = false;
+        // hasSunToolkitAWTLock = false;
+    } else {
+        // Non-headless case
+        JAWTJNILibLoader.initSingleton(); // load libjawt.so
+        if(!JAWTJNILibLoader.loadNativeWindow("awt")) { // load libnativewindow_awt.so
+            throw new NativeWindowException("NativeWindow AWT native library load error.");
+        }
         jawtLockObject = getJAWT(false); // don't care for offscreen layer here
+
+        boolean j2dExistTmp = false;
+        Class<?> java2DClass = null;
+        Method isQueueFlusherThreadTmp = null;
         try {
-            jC = Class.forName("jogamp.opengl.awt.Java2D");
-            m = jC.getMethod("isQueueFlusherThread", (Class[])null);
-            ok = true;
+            java2DClass = Class.forName("jogamp.opengl.awt.Java2D");
+            isQueueFlusherThreadTmp = java2DClass.getMethod("isQueueFlusherThread", (Class[])null);
+            j2dExistTmp = true;
         } catch (Exception e) {
         }
-    } else {
-        jawtLockObject = null; // headless !
-    }
-    isQueueFlusherThread = m;
-    j2dExist = ok;
+        isQueueFlusherThread = isQueueFlusherThreadTmp;
+        j2dExist = j2dExistTmp;
 
-    PrivilegedDataBlob1 pdb1 = (PrivilegedDataBlob1) AccessController.doPrivileged(new PrivilegedAction<Object>() {
-        @Override
-        public Object run() {
-            PrivilegedDataBlob1 d = new PrivilegedDataBlob1();
+        PrivilegedDataBlob1 pdb1 = (PrivilegedDataBlob1) AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            @Override
+            public Object run() {
+                PrivilegedDataBlob1 d = new PrivilegedDataBlob1();
+                try {
+                    final Class<?> sunToolkitClass = Class.forName("sun.awt.SunToolkit");
+                    d.sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[]{});
+                    d.sunToolkitAWTLockMethod.setAccessible(true);
+                    d.sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[]{});
+                    d.sunToolkitAWTUnlockMethod.setAccessible(true);
+                    d.ok=true;
+                } catch (Exception e) {
+                    // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
+                }
+                return d;
+            }
+        });
+        sunToolkitAWTLockMethod = pdb1.sunToolkitAWTLockMethod;
+        sunToolkitAWTUnlockMethod = pdb1.sunToolkitAWTUnlockMethod;
+
+        boolean _hasSunToolkitAWTLock = false;
+        if ( pdb1.ok ) {
             try {
-                final Class<?> sunToolkitClass = Class.forName("sun.awt.SunToolkit");
-                d.sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[]{});
-                d.sunToolkitAWTLockMethod.setAccessible(true);
-                d.sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[]{});
-                d.sunToolkitAWTUnlockMethod.setAccessible(true);
-                d.ok=true;
+                sunToolkitAWTLockMethod.invoke(null, (Object[])null);
+                sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
+                _hasSunToolkitAWTLock = true;
             } catch (Exception e) {
-                // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
             }
-            return d;
-        }
-    });
-    sunToolkitAWTLockMethod = pdb1.sunToolkitAWTLockMethod;
-    sunToolkitAWTUnlockMethod = pdb1.sunToolkitAWTUnlockMethod;
-
-    boolean _hasSunToolkitAWTLock = false;
-    if ( pdb1.ok ) {
-        try {
-            sunToolkitAWTLockMethod.invoke(null, (Object[])null);
-            sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
-            _hasSunToolkitAWTLock = true;
-        } catch (Exception e) {
         }
+        hasSunToolkitAWTLock = _hasSunToolkitAWTLock;
+        // hasSunToolkitAWTLock = false;
     }
-    hasSunToolkitAWTLock = _hasSunToolkitAWTLock;
-    // hasSunToolkitAWTLock = false;
+
     jawtLock = LockFactory.createRecursiveLock();
 
     jawtToolkitLock = new ToolkitLock() {
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index 1ed6284..f0cc689 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -621,9 +621,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
                     printActive = false;
                     return; // not yet available ..
                 }
-                if( !isShowing() ) {
+                if( !isVisible() ) {
                     if(DEBUG) {
-                        System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable valid, canvas not showing");
+                        System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, canvas not visible");
                     }
                     printActive = false;
                     return; // not yet available ..
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index ca8ab67..4b74092 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -683,21 +683,6 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     }
 
     @Override
-    public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
-        window.removeSurfaceUpdatedListener(l);
-    }
-
-    @Override
-    public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
-        window.addSurfaceUpdatedListener(l);
-    }
-
-    @Override
-    public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
-        window.addSurfaceUpdatedListener(index, l);
-    }
-
-    @Override
     public void sendWindowEvent(int eventType) {
         window.sendWindowEvent(eventType);
     }
@@ -851,6 +836,26 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     }
 
     @Override
+    public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+        window.removeSurfaceUpdatedListener(l);
+    }
+
+    @Override
+    public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+        window.addSurfaceUpdatedListener(l);
+    }
+
+    @Override
+    public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+        window.addSurfaceUpdatedListener(index, l);
+    }
+
+    @Override
+    public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+        window.surfaceUpdated(updater, ns, when);
+    }
+
+    @Override
     public final long getWindowHandle() {
         return window.getWindowHandle();
 
@@ -877,11 +882,6 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
         return window.getScreenIndex();
     }
 
-    @Override
-    public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
-        window.surfaceUpdated(updater, ns, when);
-    }
-
     /**
      * A most simple JOGL AWT test entry
      */
diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
index 43e56c8..6f4be75 100644
--- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
+++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
@@ -146,9 +146,6 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
                                 newtChild.setSize(clientArea.width, clientArea.height);
                                 postSetSize = false;
                             }
-                            if( SWTAccessor.isOSX ) {
-                                newtChild.setPosition(parent.getLocation().x,parent.getLocation().y);
-                            }
                             newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
                         }
                     }
@@ -166,7 +163,18 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
         addListener (SWT.Paint, listener);
         addListener (SWT.Dispose, listener);
     }
-
+    @Override
+    public void setBounds(int x, int y, int w, int h) {
+    	// propagate the setBounds method coming from parent elements to this element
+    	// and force newtChild to update its position in OSX
+    	super.setBounds(x,y,w,h);
+    	if(SWTAccessor.isOSX) {
+    	    newtChild.setPosition(x, y);
+    		clientArea.width = w;
+    		clientArea.height = h;
+    		updateSizeCheck();
+    	}
+    }
     /** assumes nativeWindow == null ! */
     protected final boolean validateNative() {
         updateSizeCheck();
@@ -199,6 +207,10 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
 
             nativeWindow = new SWTNativeWindow(config, nativeWindowHandle);
             reparentWindow( true );
+        	if(SWTAccessor.isOSX) {
+        	    // initial positioning for OSX, called when the window is created
+        	    newtChild.setPosition(getLocation().x, getLocation().y);
+        	}
         }
 
         return null != nativeWindow;
@@ -256,8 +268,9 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
         super.dispose();
     }
 
-    private Rectangle getSWTCanvasPosition() {
-        return super.getBounds();
+    private Point getParentLocationOnScreen() {
+    	org.eclipse.swt.graphics.Point parentLoc = getParent().toDisplay(0,0);
+        return new Point(parentLoc.x,parentLoc.y);
     }
     /** @return this SWT Canvas NativeWindow representation, may be null in case it has not been realized. */
     public NativeWindow getNativeWindow() { return nativeWindow; }
@@ -506,10 +519,9 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
         public Point getLocationOnScreen(Point point) {
             final Point los; // client window location on screen
             if( SWTAccessor.isOSX ) {
-                los = OSXUtil.GetLocationOnScreen(nativeWindowHandle, false, 0, 0);
-                // top-level position -> client window position: OSX needs to add SWT parent position incl. insets
-                final Rectangle swtCanvasPosition = getSWTCanvasPosition();
-                los.translate(swtCanvasPosition.x + insets.getLeftWidth(), swtCanvasPosition.y + insets.getTopHeight());
+            	// let getLOS provide the point where the child window may be placed
+            	// from, as taken from SWT Control.toDisplay();
+            	los = getParentLocationOnScreen();
             } else if (SWTAccessor.isX11) {
                 final AbstractGraphicsScreen s = config.getScreen();
                 los = X11Lib.GetRelativeLocation(s.getDevice().getHandle(), s.getIndex(), nativeWindowHandle, 0 /*root win*/, 0, 0);
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index b485a47..952e611 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -76,8 +76,7 @@ public abstract class DisplayImpl extends Display {
         });
 
         final ClassLoader cl = DisplayImpl.class.getClassLoader();
-        pngUtilAvail = ReflectionUtil.isClassAvailable("jogamp.opengl.util.pngj.PngReader", cl) &&
-                       ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.PNGPixelRect", cl);
+        pngUtilAvail = ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.PNGPixelRect", cl);
     }
 
     public static final boolean isPNGUtilAvailable() { return pngUtilAvail; }
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 1e2291c..9593d4f 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -811,6 +811,26 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
 
     @Override
+    public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+        surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
+    }
+
+    @Override
+    public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+        surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
+    }
+
+    @Override
+    public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+        surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+    }
+
+    @Override
+    public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+        surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
+    }
+
+    @Override
     public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
         return config.getNativeGraphicsConfiguration();
     }
@@ -2087,7 +2107,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 if(DEBUG_IMPLEMENTATION) {
                     System.err.println("Window setPosition: "+getX()+"/"+getY()+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle));
                 }
-                if ( !isFullscreen() && ( getX() != x || getY() != y ) ) {
+                // Let the window be positioned if !fullscreen and position changed or being a child window.
+                if ( !isFullscreen() && ( getX() != x || getY() != y || null != getParent()) ) {
                     if(isNativeValid()) {
                         // this.x/this.y will be set by sizeChanged, triggered by windowing event system
                         reconfigureWindowImpl(x, y, getWidth(), getHeight(), getReconfigureFlags(0, isVisible()));
@@ -2507,29 +2528,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
 
     //
-    // SurfaceUpdatedListener Support
-    //
-    @Override
-    public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
-        surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
-    }
-
-    @Override
-    public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
-        surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
-    }
-
-    @Override
-    public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
-        surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
-    }
-
-    @Override
-    public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
-        surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
-    }
-
-    //
     // MouseListener/Event Support
     //
 
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index 130b2e3..25ea47c 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -1133,13 +1133,18 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0
   (JNIEnv *env, jobject unused, jlong window)
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-    NSWindow* win = (NSWindow*) ((intptr_t) window);
+    NSWindow* mWin = (NSWindow*) ((intptr_t) window);
+    NSWindow* pWin = [mWin parentWindow];
 
-    DBG_PRINT( "orderFront0 - window: %p (START)\n", win);
+    DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
 
-    [win orderFrontRegardless];
+    if( NULL == pWin ) {
+        [mWin orderFrontRegardless];
+    } else {
+        [mWin orderWindow: NSWindowAbove relativeTo: [pWin windowNumber]];
+    }
 
-    DBG_PRINT( "orderFront0 - window: %p (END)\n", win);
+    DBG_PRINT( "orderFront0 - window: (parent %p) %p (END)\n", pWin, mWin);
 
     [pool release];
 }
@@ -1155,14 +1160,13 @@ 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 visible %d) %p visible %d (START)\n", pWin, pWinVisible, mWin, [mWin isVisible]);
+    DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
 
-    if( NULL == pWin || !pWinVisible ) {
+    if( NULL == pWin ) {
         [mWin orderOut: mWin];
     } else {
-        [mWin orderBack: mWin];
+        [mWin orderWindow: NSWindowOut relativeTo: [pWin windowNumber]];
     }
 
     DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin);
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
index ec8fa10..1de0951 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
@@ -3,14 +3,14 @@
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
- * 
+ *
  *    1. Redistributions of source code must retain the above copyright notice, this list of
  *       conditions and the following disclaimer.
- * 
+ *
  *    2. Redistributions in binary form must reproduce the above copyright notice, this list
  *       of conditions and the following disclaimer in the documentation and/or other materials
  *       provided with the distribution.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
+ *
  * The views and conclusions contained in the software and documentation are those of the
  * authors and should not be interpreted as representing official policies, either expressed
  * or implied, of JogAmp Community.
@@ -57,7 +57,7 @@ import android.util.Log;
 
 public class MovieCubeActivity0 extends NewtBaseActivity {
    static String TAG = "MovieCubeActivity0";
-   
+
    MouseAdapter showKeyboardMouseListener = new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent e) {
@@ -66,18 +66,18 @@ public class MovieCubeActivity0 extends NewtBaseActivity {
            }
         }
    };
-   
+
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
-       
-       String[] streamLocs = new String[] {                    
+
+       String[] streamLocs = new String[] {
                System.getProperty("jnlp.media0_url2"),
                System.getProperty("jnlp.media0_url1"),
-               System.getProperty("jnlp.media0_url0") };       
+               System.getProperty("jnlp.media0_url0") };
        final URI streamLoc = getURI(streamLocs, 0, false);
        if(null == streamLoc) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); }
-       
+
        // also initializes JOGL
        final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2());
        capsMain.setBackgroundOpaque(false);
@@ -86,53 +86,56 @@ public class MovieCubeActivity0 extends NewtBaseActivity {
        final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null);
        final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0);
        scrn.addReference();
-              
+
        try {
            final Animator anim = new Animator();
-           
-           // Main           
+
+           // Main
            final GLWindow glWindowMain = GLWindow.create(scrn, capsMain);
            glWindowMain.setFullscreen(true);
            setContentView(getWindow(), glWindowMain);
            anim.add(glWindowMain);
            glWindowMain.setVisible(true);
            glWindowMain.addMouseListener(showKeyboardMouseListener);
-           
-           final MovieCube demoMain = new MovieCube(-2.3f, 0f, 0f);
+
+           final MovieCube demoMain = new MovieCube(MovieCube.zoom_def, 0f, 0f);
            final GLMediaPlayer mPlayer = demoMain.getGLMediaPlayer();
            mPlayer.addEventListener(new GLMediaEventListener() {
                 @Override
                 public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) {
                 }
-    
+
                 @Override
                 public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when) {
                     System.err.println("MovieCubeActivity0 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
                     System.err.println("MovieCubeActivity0 State: "+mp);
                     if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
                         glWindowMain.addGLEventListener(demoMain);
-                        anim.setUpdateFPSFrames(60, System.err);
+                        anim.setUpdateFPSFrames(60, null);
+                        anim.resetFPSCounter();
+                    }
+                    if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
                         anim.resetFPSCounter();
                     }
                     if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
                         final StreamException se = mPlayer.getStreamException();
                         if( null != se ) {
-                            se.printStackTrace();                        
+                            se.printStackTrace();
                         }
                         getActivity().finish();
                     }
-                }            
-            });        
+                }
+            });
            demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0);
        } catch (IOException e) {
            e.printStackTrace();
        }
-       
+
        scrn.removeReference();
 
        Log.d(TAG, "onCreate - X");
    }
-   
+
    static URI getURI(String path[], int off, boolean checkAvail) {
        URI uri = null;
        for(int i=off; null==uri && i<path.length; i++) {
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java
new file mode 100644
index 0000000..1282d5d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java
@@ -0,0 +1,195 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.graph;
+
+import java.io.IOException;
+
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.curve.opengl.TextRenderer;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+public abstract class TextRendererGLELBase implements GLEventListener {
+    protected final float[] textPosition = new float[] {0,0,0};
+    protected final int[] texSize = new int[] { 0 };
+    protected final float[] staticRGBAColor = new float[] { 1f, 1f, 1f, 1f };
+
+    protected final Font font;
+    protected final int usrRenderModes;
+
+    /**
+     * In exclusive mode, impl. uses a pixelScale of 1f and orthogonal PMV on window dimensions
+     * and renderString uses 'height' for '1'.
+     * <p>
+     * In non-exclusive mode, i.e. shared w/ custom PMV (within another 3d scene),
+     * it uses the custom pixelScale and renderString uses normalized 'height', i.e. '1'.
+     * </p>
+     */
+    protected boolean exclusivePMVMatrix = true;
+    protected PMVMatrix usrPMVMatrix = null;
+    protected RenderState rs = null;
+    protected TextRenderer renderer = null;
+
+    /** font size in pixels, default is 24 */
+    protected int fontSize = 24;
+    /** scale pixel, default is 1f */
+    protected float pixelScale = 1.0f;
+    protected int texSizeScale = 2;
+
+    boolean flipVerticalInGLOrientation = false;
+
+    public TextRendererGLELBase(final int renderModes) {
+        usrRenderModes = renderModes;
+        {
+            Font _font = null;
+            try {
+                _font = FontFactory.get(FontFactory.UBUNTU).getDefault();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            this.font = _font;
+        }
+    }
+
+    public void setFlipVerticalInGLOrientation(boolean v) { flipVerticalInGLOrientation=v; }
+    public final TextRenderer getRenderer() { return renderer; }
+
+    @Override
+    public void init(GLAutoDrawable drawable) {
+        if( null != font ) {
+            exclusivePMVMatrix = null == usrPMVMatrix;
+            this.rs = RenderState.createRenderState(new ShaderState(), SVertex.factory(), usrPMVMatrix);
+            this.renderer = TextRenderer.create(rs, usrRenderModes);
+            if( 0 == usrRenderModes ) {
+                texSizeScale = 0;
+            }
+            final GL2ES2 gl = drawable.getGL().getGL2ES2();
+            renderer.init(gl);
+            renderer.setAlpha(gl, staticRGBAColor[3]);
+            renderer.setColorStatic(gl, staticRGBAColor[0], staticRGBAColor[1], staticRGBAColor[2]);
+            final ShaderState st = rs.getShaderState();
+            st.useProgram(gl, false);
+        } else {
+            this.rs = null;
+            this.renderer = null;
+        }
+    }
+
+    @Override
+    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+        if( null != renderer ) {
+            final GL2ES2 gl = drawable.getGL().getGL2ES2();
+            final ShaderState st = rs.getShaderState();
+            st.useProgram(gl, true);
+            if( exclusivePMVMatrix ) {
+                // renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 1000.0f);
+                renderer.reshapeOrtho(gl, width, height, 0.1f, 1000.0f);
+                pixelScale = 1.0f;
+            } else {
+                renderer.reshapeNotify(gl, width, height);
+            }
+            st.useProgram(gl, false);
+            texSize[0] = width * texSizeScale;
+        }
+    }
+
+    @Override
+    public abstract void display(GLAutoDrawable drawable);
+
+    @Override
+    public void dispose(GLAutoDrawable drawable) {
+        if( null != renderer ) {
+            final GL2ES2 gl = drawable.getGL().getGL2ES2();
+            renderer.destroy(gl);
+        }
+    }
+
+    int lastRow = -1;
+
+    public void renderString(GLAutoDrawable drawable, String text, int column, float tx, float ty, float tz) {
+        final int row = lastRow + 1;
+        renderString(drawable, text, column, row, tx, ty, tz);
+        lastRow = row;
+    }
+
+    public void renderString(GLAutoDrawable drawable, String text, int column, int row, float tx, float ty, float tz) {
+        if( null != renderer ) {
+            final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+            float dx = tx;
+            float dy;
+
+            if( !exclusivePMVMatrix )  {
+                dy = 1f-ty;
+            } else {
+                final int height = drawable.getHeight();
+                dy = height-ty;
+            }
+
+            final AABBox textBox = font.getStringBounds(text, fontSize);
+            dx += pixelScale * font.getAdvanceWidth('X', fontSize) * column;
+            dy -= pixelScale * (int)textBox.getHeight() * ( row + 1 );
+
+            final ShaderState st = rs.getShaderState();
+            final PMVMatrix pmvMatrix = rs.pmvMatrix();
+            pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+            if( !exclusivePMVMatrix )  {
+                pmvMatrix.glPushMatrix();
+            } else {
+                pmvMatrix.glLoadIdentity();
+            }
+
+            st.useProgram(gl, true);
+            gl.glEnable(GL2ES2.GL_BLEND);
+            pmvMatrix.glTranslatef(dx, dy, tz);
+            if( flipVerticalInGLOrientation && drawable.isGLOriented() ) {
+                pmvMatrix.glScalef(pixelScale, -1f*pixelScale, 1f);
+            } else if( 1f != pixelScale ) {
+                pmvMatrix.glScalef(pixelScale, pixelScale, 1f);
+            }
+            renderer.updateMatrix(gl);
+            renderer.drawString3D(gl, font, text, textPosition, fontSize, texSize);
+            st.useProgram(gl, false);
+            gl.glDisable(GL2ES2.GL_BLEND);
+
+            if( !exclusivePMVMatrix )  {
+                pmvMatrix.glPopMatrix();
+            }
+            lastRow = -1;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
new file mode 100644
index 0000000..43f8b89
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
@@ -0,0 +1,117 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLProfile;
+
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.graph.curve.Region;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Multiple GLJPanels in a JFrame
+ */
+ at FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public abstract class GLReadBuffer00Base extends UITestCase {
+
+    public static class TextRendererGLEL extends TextRendererGLELBase {
+        public int frameNo = 0;
+        public int userCounter = 0;
+
+        public TextRendererGLEL() {
+            // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+            super(Region.VBAA_RENDERING_BIT);
+            texSizeScale = 2;
+
+            fontSize = 24;
+
+            staticRGBAColor[0] = 1.0f;
+            staticRGBAColor[1] = 1.0f;
+            staticRGBAColor[2] = 1.0f;
+            staticRGBAColor[3] = 0.99f;
+        }
+
+        @Override
+        public void display(GLAutoDrawable drawable) {
+            final String text = String.format("Frame %04d (%03d): %04dx%04d", frameNo, userCounter, drawable.getWidth(), drawable.getHeight());
+            System.err.println("TextRendererGLEL.display: "+text);
+            if( null != renderer ) {
+                renderString(drawable, text, 0 /* col */, 0 /* row */, 0, 0, -1);
+            } else {
+                System.err.println(text);
+            }
+            frameNo++;
+        }
+    }
+
+    @BeforeClass
+    public static void initClass() throws IOException {
+        GLProfile.initSingleton();
+    }
+
+    protected abstract void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip);
+
+    @Test
+    public void test00_MSAA0_DefFlip() throws InterruptedException, InvocationTargetException {
+        test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */);
+    }
+
+    @Test
+    public void test01_MSAA0_UsrFlip() throws InterruptedException, InvocationTargetException {
+        test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */);
+    }
+
+    @Test
+    public void test10_MSAA8_DefFlip() throws InterruptedException, InvocationTargetException {
+        final GLCapabilities caps = new GLCapabilities(null);
+        caps.setNumSamples(8);
+        caps.setSampleBuffers(true);
+        test(caps, false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */);
+    }
+
+    @Test
+    public void test11_MSAA8_UsrFlip() throws InterruptedException, InvocationTargetException {
+        final GLCapabilities caps = new GLCapabilities(null);
+        caps.setNumSamples(8);
+        caps.setSampleBuffers(true);
+        test(caps, false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */);
+    }
+
+    static long duration = 500; // ms
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLCanvasAWT.java
new file mode 100644
index 0000000..0f77aff
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLCanvasAWT.java
@@ -0,0 +1,252 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Multiple GLJPanels in a JFrame
+ */
+ at FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLReadBuffer01GLCanvasAWT extends GLReadBuffer00Base {
+
+    @BeforeClass
+    public static void initClass() {
+        GLProfile.initSingleton();
+    }
+
+    @Override
+    public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) {
+        if( skipGLOrientationVerticalFlip || useSwingDoubleBuffer ) {
+            return; // NOP
+        }
+        final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false);
+        final Frame frame = new Frame();
+        final Dimension d = new Dimension(320, 240);
+        final GLCanvas glad = createGLCanvas(caps, d);
+        final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+        final SnapshotGLELAWT snapshotGLEL = doSnapshot ? new SnapshotGLELAWT(textRendererGLEL, awtGLReadBufferUtil) : null;
+        try {
+            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+                public void run() {
+                    frame.setLocation(64, 64);
+                    frame.setLayout(new BorderLayout());
+                    // final JPanel panel = new JPanel();
+                    // panel.setLayout(new BorderLayout());
+                    // panel.setDoubleBuffered(useSwingDoubleBuffer);
+                    // frame.getContentPane().add(panel);
+
+                    final GearsES2 gears = new GearsES2(1);
+                    gears.setVerbose(false);
+                    glad.addGLEventListener(gears);
+                    glad.addGLEventListener(textRendererGLEL);
+                    if( doSnapshot ) {
+                        glad.addGLEventListener(snapshotGLEL);
+                    }
+                    // panel.add(glad);
+                    frame.add(glad, BorderLayout.CENTER);
+                    frame.pack();
+                    frame.setVisible(true);
+                } } );
+        } catch( Throwable throwable ) {
+            throwable.printStackTrace();
+            Assume.assumeNoException( throwable );
+        }
+        glad.display(); // trigger initialization to get chosen-caps!
+        final Dimension size0 = frame.getSize();
+        final Dimension size1 = new Dimension(size0.width+100, size0.height+100);
+        final Dimension size2 = new Dimension(size0.width-100, size0.height-100);
+        try {
+            for(int i=0; i<3; i++) {
+                final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1);
+                System.err.println(str);
+                if( keyFrame ) {
+                    waitForKey(str);
+                }
+                textRendererGLEL.userCounter = i + 1;
+                glad.display();
+            }
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        frame.setSize(size1);
+                        frame.validate();
+                    } } );
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        frame.setSize(size2);
+                        frame.validate();
+                    } } );
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        frame.setSize(size0);
+                        frame.validate();
+                    } } );
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+
+            if( doSnapshot ) {
+                glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+            }
+            final Animator anim = new Animator(glad);
+            anim.start();
+            try { Thread.sleep(2*duration); } catch (InterruptedException e) { }
+            anim.stop();
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        }
+        try {
+            SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        frame.dispose();
+                    } } );
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        }
+    }
+
+    private GLCanvas createGLCanvas(final GLCapabilitiesImmutable caps, final Dimension size) {
+        final GLCanvas canvas = new GLCanvas(caps);
+        canvas.setSize(size);
+        canvas.setPreferredSize(size);
+        canvas.setMinimumSize(size);
+        return canvas;
+    }
+
+    private class SnapshotGLELAWT implements GLEventListener {
+        final TextRendererGLEL textRendererGLEL;
+        final AWTGLReadBufferUtil glReadBufferUtil;
+        boolean defAutoSwapMode;
+        boolean swapBuffersBeforeRead;
+        int i;
+
+        SnapshotGLELAWT(final TextRendererGLEL textRendererGLEL, final AWTGLReadBufferUtil glReadBufferUtil) {
+            this.textRendererGLEL = textRendererGLEL;
+            this.glReadBufferUtil = glReadBufferUtil;
+            this.defAutoSwapMode = true;
+            this.swapBuffersBeforeRead = false;
+            i = 0;
+        }
+
+        @Override
+        public void init(GLAutoDrawable drawable) {
+            defAutoSwapMode = drawable.getAutoSwapBufferMode();
+            swapBuffersBeforeRead = GLDrawableUtil.swapBuffersBeforeRead(drawable.getChosenGLCapabilities());
+            drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead );
+        }
+        @Override
+        public void dispose(GLAutoDrawable drawable) {
+            drawable.setAutoSwapBufferMode( defAutoSwapMode );
+        }
+        @Override
+        public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+        @Override
+        public void display(GLAutoDrawable drawable) {
+            snapshot(i++, drawable.getGL(), TextureIO.PNG, null);
+        }
+        public void snapshot(int sn, GL gl, String fileSuffix, String destPath) {
+            final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+            final String postSNDetail = String.format("awt-usr%03d", textRendererGLEL.userCounter);
+            final String filenameAWT = getSnapshotFilename(sn, postSNDetail,
+                                                           drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+                                                           glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+            if( swapBuffersBeforeRead ) {
+                drawable.swapBuffers();
+                // Just to test whether we use the right buffer,
+                // i.e. back-buffer shall no more be required ..
+                gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+            } else {
+                gl.glFinish(); // just make sure rendering finished ..
+            }
+
+            final boolean awtOrientation = drawable.isGLOriented();
+            System.err.println(Thread.currentThread().getName()+": ** screenshot: awtOrient/v-flip "+awtOrientation+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameAWT);
+
+            final BufferedImage image = glReadBufferUtil.readPixelsToBufferedImage(gl, awtOrientation);
+            final File fout = new File(filenameAWT);
+            try {
+                ImageIO.write(image, "png", fout);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            /**
+            final String filenameJGL = getSnapshotFilename(sn, "jgl",
+                                                           drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+                                                           glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+            glReadBufferUtil.write(new File(filenameJGL));
+            */
+        }
+    };
+
+    static GLCapabilitiesImmutable caps = null;
+    static boolean doSnapshot = true;
+    static boolean keyFrame = false;
+
+    public static void main(String[] args) {
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-time")) {
+                i++;
+                duration = MiscUtils.atol(args[i], duration);
+            } else if(args[i].equals("-keyFrame")) {
+                keyFrame = true;
+            } else if(args[i].equals("-noSnapshot")) {
+                doSnapshot = false;
+            }
+        }
+        org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLCanvasAWT.class.getName());
+    }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java
new file mode 100644
index 0000000..e93356d
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java
@@ -0,0 +1,254 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Multiple GLJPanels in a JFrame
+ */
+ at FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00Base {
+
+    @BeforeClass
+    public static void initClass() {
+        GLProfile.initSingleton();
+    }
+
+    @Override
+    public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) {
+        final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false);
+        final JFrame frame = new JFrame();
+        final Dimension d = new Dimension(320, 240);
+        final GLJPanel glad = createGLJPanel(skipGLOrientationVerticalFlip, useSwingDoubleBuffer, caps, d);
+        final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+        final SnapshotGLELAWT snapshotGLEL = doSnapshot ? new SnapshotGLELAWT(textRendererGLEL, awtGLReadBufferUtil, skipGLOrientationVerticalFlip) : null;
+        try {
+            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+                public void run() {
+                    frame.setLocation(64, 64);
+                    final JPanel panel = new JPanel();
+                    panel.setLayout(new BorderLayout());
+                    panel.setDoubleBuffered(useSwingDoubleBuffer);
+                    frame.getContentPane().add(panel);
+
+                    final GearsES2 gears = new GearsES2(1);
+                    gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+                    gears.setVerbose(false);
+                    glad.addGLEventListener(gears);
+                    textRendererGLEL.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+                    glad.addGLEventListener(textRendererGLEL);
+                    if( doSnapshot ) {
+                        glad.addGLEventListener(snapshotGLEL);
+                    }
+                    panel.add(glad);
+                    frame.pack();
+                    frame.setVisible(true);
+                } } );
+        } catch( Throwable throwable ) {
+            throwable.printStackTrace();
+            Assume.assumeNoException( throwable );
+        }
+        glad.display(); // trigger initialization to get chosen-caps!
+        final Dimension size0 = frame.getSize();
+        final Dimension size1 = new Dimension(size0.width+100, size0.height+100);
+        final Dimension size2 = new Dimension(size0.width-100, size0.height-100);
+        try {
+            for(int i=0; i<3; i++) {
+                final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1);
+                System.err.println(str);
+                if( keyFrame ) {
+                    waitForKey(str);
+                }
+                textRendererGLEL.userCounter = i + 1;
+                glad.display();
+            }
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        frame.setSize(size1);
+                        frame.validate();
+                    } } );
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        frame.setSize(size2);
+                        frame.validate();
+                    } } );
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        frame.setSize(size0);
+                        frame.validate();
+                    } } );
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+
+            if( doSnapshot ) {
+                glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+            }
+            final Animator anim = new Animator(glad);
+            anim.start();
+            try { Thread.sleep(2*duration); } catch (InterruptedException e) { }
+            anim.stop();
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        }
+        try {
+            SwingUtilities.invokeAndWait(new Runnable() {
+                    public void run() {
+                        frame.dispose();
+                    } } );
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        }
+    }
+
+    private GLJPanel createGLJPanel(final boolean skipGLOrientationVerticalFlip, final boolean useSwingDoubleBuffer, final GLCapabilitiesImmutable caps, final Dimension size) {
+        final GLJPanel canvas = new GLJPanel(caps);
+        canvas.setSize(size);
+        canvas.setPreferredSize(size);
+        canvas.setMinimumSize(size);
+        canvas.setDoubleBuffered(useSwingDoubleBuffer);
+        canvas.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip);
+        return canvas;
+    }
+
+    private class SnapshotGLELAWT implements GLEventListener {
+        final TextRendererGLEL textRendererGLEL;
+        final AWTGLReadBufferUtil glReadBufferUtil;
+        final boolean skipGLOrientationVerticalFlip;
+        boolean defAutoSwapMode;
+        boolean swapBuffersBeforeRead;
+        int i;
+
+        SnapshotGLELAWT(final TextRendererGLEL textRendererGLEL, final AWTGLReadBufferUtil glReadBufferUtil, final boolean skipGLOrientationVerticalFlip) {
+            this.textRendererGLEL = textRendererGLEL;
+            this.glReadBufferUtil = glReadBufferUtil;
+            this.skipGLOrientationVerticalFlip = skipGLOrientationVerticalFlip;
+            this.defAutoSwapMode = true;
+            this.swapBuffersBeforeRead = false;
+            i = 0;
+        }
+
+        @Override
+        public void init(GLAutoDrawable drawable) {
+            defAutoSwapMode = drawable.getAutoSwapBufferMode();
+            swapBuffersBeforeRead = GLDrawableUtil.swapBuffersBeforeRead(drawable.getChosenGLCapabilities());
+            drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead );
+        }
+        @Override
+        public void dispose(GLAutoDrawable drawable) {
+            drawable.setAutoSwapBufferMode( defAutoSwapMode );
+        }
+        @Override
+        public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+        @Override
+        public void display(GLAutoDrawable drawable) {
+            snapshot(i++, drawable.getGL(), TextureIO.PNG, null);
+        }
+        public void snapshot(int sn, GL gl, String fileSuffix, String destPath) {
+            final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+            final String postSNDetail = String.format("awt-usr%03d", textRendererGLEL.userCounter);
+            final String filenameAWT = getSnapshotFilename(sn, postSNDetail,
+                                                           drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+                                                           glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+            if( swapBuffersBeforeRead ) {
+                drawable.swapBuffers();
+                // Just to test whether we use the right buffer,
+                // i.e. back-buffer shall no more be required ..
+                gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+            } else {
+                gl.glFinish(); // just make sure rendering finished ..
+            }
+
+            final boolean awtOrientation = !( drawable.isGLOriented() && skipGLOrientationVerticalFlip );
+            System.err.println(Thread.currentThread().getName()+": ** screenshot: awtOrient/v-flip "+awtOrientation+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameAWT);
+
+            final BufferedImage image = glReadBufferUtil.readPixelsToBufferedImage(gl, awtOrientation);
+            final File fout = new File(filenameAWT);
+            try {
+                ImageIO.write(image, "png", fout);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            /**
+            final String filenameJGL = getSnapshotFilename(sn, "jgl",
+                                                           drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+                                                           glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+            glReadBufferUtil.write(new File(filenameJGL));
+            */
+        }
+    };
+
+    static GLCapabilitiesImmutable caps = null;
+    static boolean doSnapshot = true;
+    static boolean keyFrame = false;
+
+    public static void main(String[] args) {
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-time")) {
+                i++;
+                duration = MiscUtils.atol(args[i], duration);
+            } else if(args[i].equals("-keyFrame")) {
+                keyFrame = true;
+            } else if(args[i].equals("-noSnapshot")) {
+                doSnapshot = false;
+            }
+        }
+        org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLJPanelAWT.class.getName());
+    }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java
new file mode 100644
index 0000000..a170d9b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java
@@ -0,0 +1,195 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.File;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+/**
+ * Multiple GLJPanels in a JFrame
+ */
+ at FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGLReadBuffer01GLWindowNEWT extends GLReadBuffer00Base {
+
+    @BeforeClass
+    public static void initClass() {
+        GLProfile.initSingleton();
+    }
+
+    @Override
+    public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) {
+        if( skipGLOrientationVerticalFlip || useSwingDoubleBuffer ) {
+            return; // NOP
+        }
+        final GLReadBufferUtil glReadBufferUtil = new GLReadBufferUtil(false, false);
+        final GLWindow glad= GLWindow.create(caps);
+        final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+        final SnapshotGLEL snapshotGLEL = doSnapshot ? new SnapshotGLEL(textRendererGLEL, glReadBufferUtil) : null;
+        try {
+            glad.setPosition(64, 64);
+            glad.setSize(320, 240);
+            final GearsES2 gears = new GearsES2(1);
+            gears.setVerbose(false);
+            glad.addGLEventListener(gears);
+            textRendererGLEL.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+            glad.addGLEventListener(textRendererGLEL);
+            if( doSnapshot ) {
+                glad.addGLEventListener(snapshotGLEL);
+            }
+            glad.setVisible(true);
+        } catch( Throwable throwable ) {
+            throwable.printStackTrace();
+            Assume.assumeNoException( throwable );
+        }
+        final DimensionImmutable size0 = new Dimension(glad.getWidth(), glad.getHeight());
+        final DimensionImmutable size1 = new Dimension(size0.getWidth()+100, size0.getHeight()+100);
+        final DimensionImmutable size2 = new Dimension(size0.getWidth()-100, size0.getHeight()-100);
+        try {
+            for(int i=0; i<3; i++) {
+                final String str = "Frame# "+textRendererGLEL.frameNo+", user #"+(i+1);
+                System.err.println(str);
+                if( keyFrame ) {
+                    waitForKey(str);
+                }
+                textRendererGLEL.userCounter = i + 1;
+                glad.display();
+            }
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+            glad.setSize(size1.getWidth(), size1.getHeight());
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+            glad.setSize(size2.getWidth(), size2.getHeight());
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+            glad.setSize(size0.getWidth(), size0.getHeight());
+            try { Thread.sleep(duration); } catch (InterruptedException e) { }
+
+            if( doSnapshot ) {
+                glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+            }
+            final Animator anim = new Animator(glad);
+            anim.start();
+            try { Thread.sleep(2*duration); } catch (InterruptedException e) { }
+            anim.stop();
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        }
+        glad.destroy();
+    }
+
+    private class SnapshotGLEL implements GLEventListener {
+        final TextRendererGLEL textRendererGLEL;
+        final GLReadBufferUtil glReadBufferUtil;
+        boolean defAutoSwapMode;
+        boolean swapBuffersBeforeRead;
+        int i;
+
+        SnapshotGLEL(final TextRendererGLEL textRendererGLEL, final GLReadBufferUtil glReadBufferUtil) {
+            this.textRendererGLEL = textRendererGLEL;
+            this.glReadBufferUtil = glReadBufferUtil;
+            this.defAutoSwapMode = true;
+            this.swapBuffersBeforeRead = false;
+            i = 0;
+        }
+
+        @Override
+        public void init(GLAutoDrawable drawable) {
+            defAutoSwapMode = drawable.getAutoSwapBufferMode();
+            swapBuffersBeforeRead = GLDrawableUtil.swapBuffersBeforeRead(drawable.getChosenGLCapabilities());
+            drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead );
+        }
+        @Override
+        public void dispose(GLAutoDrawable drawable) {
+            drawable.setAutoSwapBufferMode( defAutoSwapMode );
+        }
+        @Override
+        public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
+        @Override
+        public void display(GLAutoDrawable drawable) {
+            snapshot(i++, drawable, TextureIO.PNG, null);
+        }
+        public void snapshot(int sn, GLAutoDrawable drawable, String fileSuffix, String destPath) {
+            final GL gl = drawable.getGL();
+            final String postSNDetail = String.format("jgl-usr%03d", textRendererGLEL.userCounter);
+            final String filenameJGL = getSnapshotFilename(sn, postSNDetail,
+                                                           drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+                                                           glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
+            if( swapBuffersBeforeRead ) {
+                drawable.swapBuffers();
+                // Just to test whether we use the right buffer,
+                // i.e. back-buffer shall no more be required ..
+                gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+            } else {
+                gl.glFinish(); // just make sure rendering finished ..
+            }
+            final boolean mustFlipVertically = !drawable.isGLOriented();
+            System.err.println(Thread.currentThread().getName()+": ** screenshot: v-flip "+mustFlipVertically+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameJGL);
+
+            if(glReadBufferUtil.readPixels(gl, mustFlipVertically)) {
+                glReadBufferUtil.write(new File(filenameJGL));
+            }
+        }
+    };
+
+    static GLCapabilitiesImmutable caps = null;
+    static boolean doSnapshot = true;
+    static boolean keyFrame = false;
+
+    public static void main(String[] args) {
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-time")) {
+                i++;
+                duration = MiscUtils.atol(args[i], duration);
+            } else if(args[i].equals("-keyFrame")) {
+                keyFrame = true;
+            } else if(args[i].equals("-noSnapshot")) {
+                doSnapshot = false;
+            }
+        }
+        org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLWindowNEWT.class.getName());
+    }
+
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java
index ac82c74..23778ec 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java
@@ -36,6 +36,7 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
 import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES3;
 import javax.media.opengl.GL2GL3;
 import javax.media.opengl.GLBufferStorage;
 import javax.media.opengl.GLCapabilities;
@@ -57,44 +58,65 @@ public class TestMapBufferRead01NEWT extends UITestCase {
     static final boolean DEBUG = false;
 
     @Test
-    public void testWriteRead01a() throws InterruptedException {
+    public void testWriteRead01aMap() throws InterruptedException {
         if(!GLProfile.isAvailable(GLProfile.GL2GL3)) {
             System.err.println("Test requires GL2/GL3 profile.");
             return;
         }
         ByteBuffer verticiesBB = ByteBuffer.allocate(4*9);
         verticiesBB.order(ByteOrder.nativeOrder());
-        testWriteRead01(verticiesBB);
+        testWriteRead01(verticiesBB, false /* useRange */);
     }
     @Test
-    public void testWriteRead01b() throws InterruptedException {
+    public void testWriteRead01bMap() throws InterruptedException {
         if(!GLProfile.isAvailable(GLProfile.GL2GL3)) {
             System.err.println("Test requires GL2/GL3 profile.");
             return;
         }
         ByteBuffer verticiesBB = Buffers.newDirectByteBuffer(4*9);
-        testWriteRead01(verticiesBB);
+        testWriteRead01(verticiesBB, false /* useRange */);
     }
 
-    private void testWriteRead01(ByteBuffer verticiesBB) throws InterruptedException {
+    @Test
+    public void testWriteRead02aMapRange() throws InterruptedException {
+        if(!GLProfile.isAvailable(GLProfile.GL3) && !!GLProfile.isAvailable(GLProfile.GLES3)) {
+            System.err.println("Test requires GL3 or GLES3 profile.");
+            return;
+        }
+        ByteBuffer verticiesBB = ByteBuffer.allocate(4*9);
+        verticiesBB.order(ByteOrder.nativeOrder());
+        testWriteRead01(verticiesBB, true/* useRange */);
+    }
+    @Test
+    public void testWriteRead02bMapRange() throws InterruptedException {
+        if(!GLProfile.isAvailable(GLProfile.GL3) && !!GLProfile.isAvailable(GLProfile.GLES3)) {
+            System.err.println("Test requires GL3 or GLES3 profile.");
+            return;
+        }
+        ByteBuffer verticiesBB = Buffers.newDirectByteBuffer(4*9);
+        testWriteRead01(verticiesBB, true /* useRange */);
+    }
+
+    private void testWriteRead01(ByteBuffer verticiesBB, boolean useRange) throws InterruptedException {
+        final GLProfile glp = GLProfile.getMaxProgrammable(true);
         final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOffscreenWindow(
-                new GLCapabilities(GLProfile.getGL2GL3()), 800, 600, true);
+                new GLCapabilities(glp), 800, 600, true);
         try {
             final GL gl = winctx.context.getGL();
 
             int[] vertexBuffer = new int[1];
 
-            verticiesBB.putFloat(0);
-            verticiesBB.putFloat(0.5f);
-            verticiesBB.putFloat(0);
+            verticiesBB.putFloat(-0.3f);
+            verticiesBB.putFloat(-0.2f);
+            verticiesBB.putFloat(-0.1f);
 
-            verticiesBB.putFloat(0.5f);
-            verticiesBB.putFloat(-0.5f);
-            verticiesBB.putFloat(0);
+            verticiesBB.putFloat(0.1f);
+            verticiesBB.putFloat(0.2f);
+            verticiesBB.putFloat(0.3f);
 
-            verticiesBB.putFloat(-0.5f);
-            verticiesBB.putFloat(-0.5f);
-            verticiesBB.putFloat(0);
+            verticiesBB.putFloat(0.4f);
+            verticiesBB.putFloat(0.5f);
+            verticiesBB.putFloat(0.6f);
             verticiesBB.rewind();
             if(DEBUG) {
                 for(int i=0; i < verticiesBB.capacity(); i+=4) {
@@ -106,28 +128,42 @@ public class TestMapBufferRead01NEWT extends UITestCase {
 
             gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBuffer[0]);
 
-            // gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_READ);
-            gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_DRAW);
+            gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL2ES3.GL_STATIC_READ);
+            // gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_DRAW);
 
             final int bufferName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER);
             final GLBufferStorage bufferStorage = gl.getBufferStorage(bufferName);
             System.err.println("gpu-01 GL_ARRAY_BUFFER -> bufferName "+bufferName+" -> "+bufferStorage);
             Assert.assertEquals("Buffer storage's bytes-buffer not null before map", null, bufferStorage.getMappedBuffer());
 
-            final ByteBuffer bb = gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL2GL3.GL_READ_ONLY);
-            Assert.assertNotNull(bb);
-            System.err.println("gpu-02 mapped GL_ARRAY_BUFFER -> "+bb);
+            final int floatOffset, byteOffset, mapByteLength;
+            final ByteBuffer bb;
+            if( useRange ) {
+                floatOffset = 3;
+                byteOffset = Buffers.SIZEOF_FLOAT*floatOffset;
+                mapByteLength = verticiesBB.capacity()-byteOffset;
+                bb = gl.glMapBufferRange(GL.GL_ARRAY_BUFFER, byteOffset, mapByteLength, GL.GL_MAP_READ_BIT);
+            } else {
+                floatOffset = 0;
+                byteOffset = 0;
+                mapByteLength = verticiesBB.capacity();
+                bb = gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL2GL3.GL_READ_ONLY);
+            }
+            System.err.println("gpu-02 mapped GL_ARRAY_BUFFER, floatOffset "+floatOffset+", byteOffset "+byteOffset+", mapByteLength "+mapByteLength+" -> "+bb);
             System.err.println("gpu-03 GL_ARRAY_BUFFER -> bufferName "+bufferName+" -> "+bufferStorage);
-            Assert.assertEquals("Buffer storage size not equals buffer storage size", bufferStorage.getSize(), bb.capacity());
-            Assert.assertEquals("Buffer storage's bytes-buffer not equal with mapped bytes-buffer", bufferStorage.getMappedBuffer(), bb);
+            Assert.assertNotNull(bb);
+            Assert.assertEquals("BufferStorage size less byteOffset not equals buffer storage size", bufferStorage.getSize()-byteOffset, bb.capacity());
+            Assert.assertEquals("BufferStorage's bytes-buffer not equal with mapped bytes-buffer", bufferStorage.getMappedBuffer(), bb);
+            Assert.assertEquals("Buffer storage size not equals mapByteLength", mapByteLength, bb.capacity());
 
             if(DEBUG) {
+                System.err.println("floatOffset "+floatOffset+", byteOffset "+byteOffset);
                 for(int i=0; i < bb.capacity(); i+=4) {
                     System.err.println("gpu "+i+": "+bb.getFloat(i));
                 }
             }
             for(int i=0; i < bb.capacity(); i+=4) {
-                Assert.assertEquals(verticiesBB.getFloat(i), bb.getFloat(i), 0.0);
+                Assert.assertEquals(verticiesBB.getFloat(byteOffset+i), bb.getFloat(i), 0.0001f);
             }
             gl.glUnmapBuffer(GL.GL_ARRAY_BUFFER);
             Assert.assertEquals("Buffer storage's bytes-buffer not null after unmap", null, bufferStorage.getMappedBuffer());
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 616aa52..b02238c 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
@@ -66,14 +66,14 @@ public class TextureSequenceCubeES2 implements GLEventListener {
     }
 
     private TextureSequence texSeq;
-    private ShaderState st;
-    private PMVMatrix pmvMatrix;
+    public ShaderState st;
+    public PMVMatrix pmvMatrix;
     private GLUniformData pmvMatrixUniform;
     // private TextureCoords[] textureCoords = null;
     private float nearPlaneNormalized;
     // private float zoom0=-5.0f, zoom=zoom0;
     // private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f;
-    private float zoom=-2.3f;
+    public float zoom=-2.3f;
     private float view_rotx = 0.0f, view_roty = 0.0f;
     private final float view_rotz = 0.0f;
     int[] vboNames = new int[4];
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java
new file mode 100644
index 0000000..02f62c4
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/CrossFadePlayer.java
@@ -0,0 +1,211 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.demos.es2.av;
+
+import com.jogamp.opengl.util.av.AudioSink;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException;
+import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+import java.io.File;
+import java.net.URI;
+
+/**
+ * Parallel media player that demonstrate CrossFade of audio volume during playback.
+ * This also demonstrate audio only playback of the GLMediaPlayer.
+ */
+public class CrossFadePlayer
+{
+	static GLMediaPlayer[] player;
+	static volatile boolean stop = false;
+
+	public static void main(String[] args)
+	{
+
+        if(args.length==0) {
+            System.out.println("No files! \n" +
+                    "pass as many media files you want\n" +
+                    "to the CrossFadePlayer arguments \n" +
+                    "and i will try CrossFade-play them all in parallel!");
+        }
+
+		GLMediaEventListener mediaEventListener = new GLMediaEventListener()
+		{
+			@Override
+			public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { }
+
+			@Override
+			public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when)
+			{
+				System.out.println("\n***\nEvent mask changed: " + event_mask);
+				System.out.println("Timestamp: "+ when);
+				System.out.println("State of player: " + mp.getState().toString() +"\n");
+
+				if ((event_mask & GLMediaEventListener.EVENT_CHANGE_INIT) !=0) {
+					System.out.println("Duration: " + mp.getDuration() + "ms");
+					System.out.println("Volume: " + mp.getAudioVolume());
+					System.out.println("player.initGL()...");
+                    new Thread() {
+                        public void run() {
+                            try {
+                                mp.initGL(null);
+                                if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK
+                                    mp.play();
+                                }
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    }.start();
+				} else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PAUSE) !=0) {
+					System.out.println("player.paused()...");
+				} else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PLAY) !=0) {
+					System.out.println("playing...");
+					System.out.println(mp.toString());
+					System.out.println(mp.getAudioSink().toString());
+				} else if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+                    final StreamException se = mp.getStreamException();
+                    if( null != se ) {
+                        System.err.println("Player State: EOS + Exception");
+                        stop = true;
+                    } else {
+                        System.err.println("Player State: EOS");
+                        new Thread() {
+                            public void run() {
+                                System.out.println("mp.setPlaySpeed(1f) returned: " + mp.setPlaySpeed(1f));
+                                mp.seek(0);
+                                mp.play();
+                            }
+                        }.start();
+                    }
+                }
+				if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
+					final StreamException se = mp.getStreamException();
+					if( null != se ) {
+						se.printStackTrace();
+					}
+					new Thread() {
+						public void run() {
+							System.out.println("terminating...");
+							stop = true;
+						}
+					}.start();
+				}
+
+			}
+		};
+
+        // Initialize media players
+        player = new GLMediaPlayer[args.length];
+        int i=0;
+        for( String arg: args ) {
+            player[i] = GLMediaPlayerFactory.createDefault();
+            if(player[i]!=null){
+                System.out.println("Created CrossFade player: "+ i + " " + player[i].getClass().getName());
+                player[i].addEventListener(mediaEventListener);
+                try {
+                    final String filename = arg;
+                    if(filename.equals("")){
+                        System.out.println("No file selected: arg " + i +" = "+ filename);
+                        player[i]=null;
+                    } else {
+                        File file = new File(filename);
+                        if(!file.exists()){
+                            System.out.println("File do not exist");
+                        } else {
+                            URI uri = file.toURI();
+                            System.out.println("State of player "+ i +": " + player[i].getState().toString());
+                            System.out.println("...initializing stream "+ i +"...");
+                            player[i].initStream(uri, GLMediaPlayer.STREAM_ID_NONE, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT);
+
+                        }
+                    }
+                } catch (Exception e1) {
+                    e1.printStackTrace();
+                }
+            } else {
+                System.out.println("Failed to create player "+ i +"!");
+            }
+            i++;
+        }
+
+
+        // Main thread CrossFade until playback is done
+		long startTime = com.jogamp.common.os.Platform.currentTimeMillis();
+        double piPlayers = Math.PI*2.0f/args.length;
+		StreamException se = null;
+		while( null == se && stop == false ) {
+				try {
+					Thread.sleep(100);
+				} catch (InterruptedException e) { }
+
+                // Find out the longest duration...
+                float maxDuration = 1000.0f ;
+                for(GLMediaPlayer p: player) {
+                    if(p!=null){
+                        if( p.getDuration() > maxDuration) {
+                            maxDuration = p.getDuration();
+                        }
+                    }
+                }
+
+				// tune the volume on players to crossfade!
+				float progress = (com.jogamp.common.os.Platform.currentTimeMillis()-startTime)/maxDuration;
+
+                i = 0;
+                for(GLMediaPlayer p: player){
+                    if(p!=null){
+                        AudioSink sink = p.getAudioSink();
+				        if(sink != null){
+                            float volume = (float) (0.5f+(0.5f*(Math.cos(40.0f*progress+(piPlayers*i)))));
+                            float playbacktime = com.jogamp.common.os.Platform.currentTimeMillis()-startTime;
+                            // System.out.println("player: "+ i +" volume = " + volume +" progress = "+ progress +" time = "+ playbacktime + " / duration = " + maxDuration);
+                            sink.setVolume(volume);
+				        }
+
+                        se = p.getStreamException();
+                        if( null != se) {
+                            se.printStackTrace();
+                            throw new RuntimeException(se);
+                        }
+                    }
+
+                    i++;
+                }
+		}
+
+        for(GLMediaPlayer p: player) {
+            if(p!=null)
+                p.destroy(null);
+        }
+		System.out.println("...main exit...");
+	}
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
index c1ccf7c..b148eba 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java
@@ -34,6 +34,7 @@ import java.net.URI;
 import java.net.URISyntaxException;
 
 import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAnimatorControl;
 import javax.media.opengl.GLAutoDrawable;
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLEventListener;
@@ -41,6 +42,8 @@ import javax.media.opengl.GLException;
 import javax.media.opengl.GLProfile;
 
 import com.jogamp.common.util.IOUtil;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.font.Font;
 import com.jogamp.newt.Window;
 import com.jogamp.newt.event.KeyAdapter;
 import com.jogamp.newt.event.KeyEvent;
@@ -49,6 +52,7 @@ import com.jogamp.newt.event.WindowAdapter;
 import com.jogamp.newt.event.WindowEvent;
 import com.jogamp.newt.opengl.GLWindow;
 import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
 import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureSequenceCubeES2;
 import com.jogamp.opengl.test.junit.util.MiscUtils;
 import com.jogamp.opengl.test.junit.util.UITestCase;
@@ -63,11 +67,13 @@ import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
  * Simple cube movie player w/ aspect ration true projection on a cube.
  */
 public class MovieCube implements GLEventListener {
+    public static final float zoom_def = -2.77f;
     private static boolean waitForKey = false;
     private final float zoom0, rotx, roty;
     private TextureSequenceCubeES2 cube=null;
     private GLMediaPlayer mPlayer=null;
     private int swapInterval = 1;
+    private int swapIntervalSet = -1;
     private long lastPerfPos = 0;
     private volatile boolean resetGLState = false;
 
@@ -92,7 +98,7 @@ public class MovieCube implements GLEventListener {
      * </p>
      */
     public MovieCube() throws IOException, URISyntaxException {
-        this(-2.3f, 0f, 0f);
+        this(zoom_def, 0f, 0f);
 
         mPlayer.addEventListener(new GLMediaEventListener() {
             @Override
@@ -106,9 +112,12 @@ public class MovieCube implements GLEventListener {
                     resetGLState();
                 }
                 if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
-                    // loop for-ever ..
-                    mPlayer.seek(0);
-                    mPlayer.play();
+                    new Thread() {
+                        public void run() {
+                            // loop for-ever ..
+                            mPlayer.seek(0);
+                            mPlayer.play();
+                        } }.start();
                 }
             }
         });
@@ -147,6 +156,86 @@ public class MovieCube implements GLEventListener {
         resetGLState = true;
     }
 
+    private final class InfoTextRendererGLELBase extends TextRendererGLELBase {
+        static final float z_diff = 0.001f;
+        final float underlineSize;
+
+        InfoTextRendererGLELBase() {
+            // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+            super(Region.VBAA_RENDERING_BIT);
+            texSizeScale = 2;
+
+            fontSize = 1;
+            pixelScale = 1.0f / ( fontSize * 20f );
+
+            // underlineSize: 'underline' amount of pixel below 0/0 (Note: lineGap is negative)
+            final Font.Metrics metrics = font.getMetrics();
+            final float lineGap = metrics.getLineGap(fontSize);
+            final float descent = metrics.getDescent(fontSize);
+            underlineSize = descent - lineGap;
+            // System.err.println("XXX: fLG "+lineGap+", fDesc "+descent+", underlineSize "+underlineSize);
+
+            staticRGBAColor[0] = 0.0f;
+            staticRGBAColor[1] = 0.0f;
+            staticRGBAColor[2] = 0.0f;
+            staticRGBAColor[3] = 1.0f;
+        }
+
+        @Override
+        public void init(GLAutoDrawable drawable) {
+            // non-exclusive mode!
+            this.usrPMVMatrix = cube.pmvMatrix;
+            super.init(drawable);
+        }
+
+        @Override
+        public void display(GLAutoDrawable drawable) {
+            final GLAnimatorControl anim = drawable.getAnimator();
+            final float lfps = null != anim ? anim.getLastFPS() : 0f;
+            final float tfps = null != anim ? anim.getTotalFPS() : 0f;
+            final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+            final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f;
+
+            // Note: MODELVIEW is from [ -1 .. 1 ]
+
+            // dy: position right above video rectangle (bottom text line)
+            final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight();
+            final float aspect_h = 1f/aspect;
+            final float dy = 1f-aspect_h;
+
+            // yoff1: position right above video rectangle (bottom text line)
+            //        less than underlineSize, so 'underline' pixels are above video.
+            final float yoff1 = dy-(pixelScale*underlineSize);
+
+            // yoff2: position right below video rectangle (bottom text line)
+            final float yoff2 = 2f-dy;
+
+            /**
+            System.err.println("XXX: a "+aspect+", aspect_h "+aspect_h+", dy "+dy+
+                               "; underlineSize "+underlineSize+" "+(pixelScale*underlineSize)+
+                               "; yoff "+yoff1+", yoff2 "+yoff2); */
+
+            // FIXME: Graph TextRenderer does not scale well, i.e. text update per 1/10s cause too much recompute of regions!
+            // final String text1 = String.format("%03.1f/%03.1f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d",
+            final String text1 = String.format("%03.0f/%03.0f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d",
+                    pts, mPlayer.getDuration() / 1000f,
+                    mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(),
+                    aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet);
+            final String text2 = String.format("audio: id %d, kbps %d, codec %s",
+                    mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec());
+            final String text3 = String.format("video: id %d, kbps %d, codec %s",
+                    mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec());
+            final String text4 = mPlayer.getURI().getRawPath();
+            if( displayOSD && null != renderer ) {
+                renderString(drawable, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff);
+                renderString(drawable, text2, 1 /* col */,  0 /* row */, -1+z_diff, yoff2, 1f+z_diff);
+                renderString(drawable, text3, 1 /* col */,  1 /* row */, -1+z_diff, yoff2, 1f+z_diff);
+                renderString(drawable, text4, 1 /* col */,  2 /* row */, -1+z_diff, yoff2, 1f+z_diff);
+            }
+        } };
+    private final InfoTextRendererGLELBase textRendererGLEL = new InfoTextRendererGLELBase();
+    private boolean displayOSD = true;
+
     private final KeyListener keyAction = new KeyAdapter() {
         public void keyReleased(KeyEvent e)  {
             if( e.isAutoRepeat() ) {
@@ -155,7 +244,15 @@ public class MovieCube implements GLEventListener {
             System.err.println("MC "+e);
             final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
             int pts1 = 0;
-            switch(e.getKeyCode()) {
+            switch(e.getKeySymbol()) {
+                case KeyEvent.VK_V: {
+                    switch(swapIntervalSet) {
+                        case 0: swapInterval = 1; break;
+                        default: swapInterval = 0; break;
+                    }
+                    break;
+                }
+                case KeyEvent.VK_O:          displayOSD = !displayOSD; break;
                 case KeyEvent.VK_RIGHT:      pts1 = pts0 +  1000; break;
                 case KeyEvent.VK_UP:         pts1 = pts0 + 10000; break;
                 case KeyEvent.VK_PAGE_UP:    pts1 = pts0 + 30000; break;
@@ -260,14 +357,11 @@ public class MovieCube implements GLEventListener {
             added = true;
         } else { added = false; }
         System.err.println("MC.init: kl-added "+added+", "+drawable.getClass().getName());
+        drawable.addGLEventListener(textRendererGLEL);
     }
 
     @Override
     public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
-        final GL2ES2 gl = drawable.getGL().getGL2ES2();
-        if(-1 != swapInterval) {
-            gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
-        }
         if(null == mPlayer) { return; }
         cube.reshape(drawable, x, y, width, height);
     }
@@ -275,6 +369,7 @@ public class MovieCube implements GLEventListener {
     @Override
     public void dispose(GLAutoDrawable drawable) {
         System.err.println(Thread.currentThread()+" MovieCube.dispose ... ");
+        drawable.disposeGLEventListener(textRendererGLEL, true);
         disposeImpl(drawable, true);
     }
 
@@ -297,6 +392,13 @@ public class MovieCube implements GLEventListener {
 
     @Override
     public void display(GLAutoDrawable drawable) {
+        if(-1 != swapInterval) {
+            final GL2ES2 gl = drawable.getGL().getGL2ES2();
+            gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+            drawable.getAnimator().resetFPSCounter();
+            swapIntervalSet = swapInterval;
+            swapInterval = -1;
+        }
         if(null == mPlayer) { return; }
 
         if( resetGLState ) {
@@ -392,7 +494,7 @@ public class MovieCube implements GLEventListener {
         System.err.println("forceGLDef "+forceGLDef);
         System.err.println("swapInterval "+swapInterval);
 
-        final MovieCube mc = new MovieCube(-2.3f, 0f, 0f);
+        final MovieCube mc = new MovieCube(zoom_def, 0f, 0f);
         mc.setSwapInterval(swapInterval);
 
         final GLProfile glp;
@@ -437,7 +539,10 @@ public class MovieCube implements GLEventListener {
                 }
                 if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
                     window.addGLEventListener(mc);
-                    anim.setUpdateFPSFrames(60, System.err);
+                    anim.setUpdateFPSFrames(60, null);
+                    anim.resetFPSCounter();
+                }
+                if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
                     anim.resetFPSCounter();
                 }
                 if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
index fcf1cd2..787dbab 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
@@ -48,6 +48,7 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc;
 
 import com.jogamp.common.os.Platform;
 import com.jogamp.common.util.IOUtil;
+import com.jogamp.graph.curve.Region;
 import com.jogamp.newt.Window;
 import com.jogamp.newt.event.KeyAdapter;
 import com.jogamp.newt.event.KeyEvent;
@@ -60,6 +61,7 @@ import com.jogamp.newt.event.WindowEvent;
 import com.jogamp.newt.opengl.GLWindow;
 import com.jogamp.opengl.GLExtensions;
 import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
 import com.jogamp.opengl.test.junit.util.MiscUtils;
 import com.jogamp.opengl.test.junit.util.UITestCase;
 import com.jogamp.opengl.util.Animator;
@@ -101,6 +103,7 @@ public class MovieSimple implements GLEventListener {
     private int effects = EFFECT_NORMAL;
     private float alpha = 1.0f;
     private int swapInterval = 1;
+    private int swapIntervalSet = -1;
 
     private GLMediaPlayer mPlayer;
     private final boolean mPlayerShared;
@@ -127,6 +130,55 @@ public class MovieSimple implements GLEventListener {
         defURI = _defURI;
     }
 
+    private final class InfoTextRendererGLELBase extends TextRendererGLELBase {
+        InfoTextRendererGLELBase() {
+            // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+            super(Region.VBAA_RENDERING_BIT);
+            texSizeScale = 2;
+
+            fontSize = 18;
+
+            staticRGBAColor[0] = 1.0f;
+            staticRGBAColor[1] = 1.0f;
+            staticRGBAColor[2] = 1.0f;
+            staticRGBAColor[3] = 1.0f;
+        }
+
+        @Override
+        public void display(GLAutoDrawable drawable) {
+            final GLAnimatorControl anim = drawable.getAnimator();
+            final float lfps = null != anim ? anim.getLastFPS() : 0f;
+            final float tfps = null != anim ? anim.getTotalFPS() : 0f;
+            final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+            final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f;
+
+            // Note: MODELVIEW is from [ 0 .. height ]
+
+            final int height = drawable.getHeight();
+
+            final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight();
+
+            // FIXME: Graph TextRenderer does not scale well, i.e. text update per 1/10s cause too much recompute of regions!
+            // final String text1 = String.format("%03.1f/%03.1f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d",
+            final String text1 = String.format("%03.0f/%03.0f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d",
+                    pts, mPlayer.getDuration() / 1000f,
+                    mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(),
+                    aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet);
+            final String text2 = String.format("audio: id %d, kbps %d, codec %s",
+                    mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec());
+            final String text3 = String.format("video: id %d, kbps %d, codec %s",
+                    mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec());
+            final String text4 = mPlayer.getURI().getRawPath();
+            if( displayOSD && null != renderer ) {
+                renderString(drawable, text1, 1 /* col */,  1 /* row */, 0, 0,      -1);
+                renderString(drawable, text2, 1 /* col */, -4 /* row */, 0, height, -1);
+                renderString(drawable, text3, 1 /* col */, -3 /* row */, 0, height, -1);
+                renderString(drawable, text4, 1 /* col */, -2 /* row */, 0, height, -1);
+            }
+        } };
+    private final InfoTextRendererGLELBase textRendererGLEL = new InfoTextRendererGLELBase();
+    private boolean displayOSD = true;
+
     private final MouseListener mouseAction = new MouseAdapter() {
         public void mousePressed(MouseEvent e) {
             if(e.getY()<=winHeight/2 && null!=mPlayer && 1 == e.getClickCount()) {
@@ -170,8 +222,7 @@ public class MovieSimple implements GLEventListener {
                 zoom += e.getRotation()[1]/10f; // vertical: wheel
                 System.err.println("zoom: "+zoom);
             }
-        }
-    };
+        } };
 
     private final KeyListener keyAction = new KeyAdapter() {
         public void keyReleased(KeyEvent e)  {
@@ -181,7 +232,15 @@ public class MovieSimple implements GLEventListener {
             System.err.println("MC "+e);
             final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
             int pts1 = 0;
-            switch(e.getKeyCode()) {
+            switch(e.getKeySymbol()) {
+                case KeyEvent.VK_V: {
+                    switch(swapIntervalSet) {
+                        case 0: swapInterval = 1; break;
+                        default: swapInterval = 0; break;
+                    }
+                    break;
+                }
+                case KeyEvent.VK_O:          displayOSD = !displayOSD; break;
                 case KeyEvent.VK_RIGHT:      pts1 = pts0 +  1000; break;
                 case KeyEvent.VK_UP:         pts1 = pts0 + 10000; break;
                 case KeyEvent.VK_PAGE_UP:    pts1 = pts0 + 30000; break;
@@ -237,8 +296,7 @@ public class MovieSimple implements GLEventListener {
             if( 0 != pts1 ) {
                 mPlayer.seek(pts1);
             }
-        }
-    };
+        } };
 
     /**
      * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values
@@ -263,9 +321,12 @@ public class MovieSimple implements GLEventListener {
                     resetGLState();
                 }
                 if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
-                    // loop for-ever ..
-                    mPlayer.seek(0);
-                    mPlayer.play();
+                    new Thread() {
+                        public void run() {
+                            // loop for-ever ..
+                            mPlayer.seek(0);
+                            mPlayer.play();
+                        } }.start();
                 }
             }
         });
@@ -512,6 +573,7 @@ public class MovieSimple implements GLEventListener {
             winWidth = window.getWidth();
             winHeight = window.getHeight();
         }
+        drawable.addGLEventListener(textRendererGLEL);
     }
 
     protected void updateInterleavedVBO(GL gl, Texture tex) {
@@ -571,9 +633,6 @@ public class MovieSimple implements GLEventListener {
     @Override
     public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
         final GL2ES2 gl = drawable.getGL().getGL2ES2();
-        if(-1 != swapInterval) {
-            gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
-        }
         if(null == mPlayer) { return; }
         winWidth = width;
         winHeight = height;
@@ -609,6 +668,7 @@ public class MovieSimple implements GLEventListener {
 
     @Override
     public void dispose(GLAutoDrawable drawable) {
+        drawable.disposeGLEventListener(textRendererGLEL, true);
         disposeImpl(drawable, true);
     }
 
@@ -646,6 +706,13 @@ public class MovieSimple implements GLEventListener {
 
     @Override
     public void display(GLAutoDrawable drawable) {
+        final GL2ES2 gl = drawable.getGL().getGL2ES2();
+        if(-1 != swapInterval) {
+            gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+            drawable.getAnimator().resetFPSCounter();
+            swapIntervalSet = swapInterval;
+            swapInterval = -1;
+        }
         if(null == mPlayer) { return; }
 
         if( resetGLState ) {
@@ -662,8 +729,6 @@ public class MovieSimple implements GLEventListener {
             lastPerfPos = currentPos;
         }
 
-        GL2ES2 gl = drawable.getGL().getGL2ES2();
-
         gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
 
         if(null == st) {
@@ -737,23 +802,32 @@ public class MovieSimple implements GLEventListener {
                     // Use GLEventListener in all cases [A+V, V, A]
                     window.addGLEventListener(ms);
                     final GLAnimatorControl anim = window.getAnimator();
-                    anim.setUpdateFPSFrames(60, System.err);
+                    anim.setUpdateFPSFrames(60, null);
                     anim.resetFPSCounter();
-
                     /**
                      * Kick off player w/o GLEventListener, i.e. for audio only.
                      *
-                        try {
-                            ms.mPlayer.initGL(null);
-                        } catch (Exception e) {
-                            e.printStackTrace();
-                            destroyWindow();
-                            return;
-                        }
-                        ms.mPlayer.play();
-                        System.out.println("play.1 "+ms.mPlayer);
+                        new Thread() {
+                            public void run() {
+                                try {
+                                    mp.initGL(null);
+                                    if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK
+                                        mp.play();
+                                    }
+                                    System.out.println("play.1 "+mp);
+                                } catch (Exception e) {
+                                    e.printStackTrace();
+                                    destroyWindow();
+                                    return;
+                                }
+                            }
+                        }.start();
                     */
                 }
+                if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
+                    window.getAnimator().resetFPSCounter();
+                }
+
                 boolean destroy = false;
                 Throwable err = null;
 
@@ -765,8 +839,13 @@ public class MovieSimple implements GLEventListener {
                     } else {
                         System.err.println("MovieSimple State: EOS");
                         if( loopEOS ) {
-                            ms.mPlayer.seek(0);
-                            ms.mPlayer.play();
+                            new Thread() {
+                                public void run() {
+                                    mp.setPlaySpeed(1f);
+                                    mp.seek(0);
+                                    mp.play();
+                                }
+                            }.start();
                         } else {
                             destroy = true;
                         }
@@ -916,12 +995,11 @@ public class MovieSimple implements GLEventListener {
         System.err.println("GLProfile: "+glp);
         GLCapabilities caps = new GLCapabilities(glp);
 
-        final Animator anim = new Animator();
-        anim.start();
-
         final MovieSimple[] mss = new MovieSimple[windowCount];
         final GLWindow[] windows = new GLWindow[windowCount];
         for(int i=0; i<windowCount; i++) {
+            final Animator anim = new Animator();
+            anim.start();
             windows[i] = GLWindow.create(caps);
             windows[i].addWindowListener(new WindowAdapter() {
                 public void windowDestroyed(WindowEvent e) {
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 7beceb2..714c397 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
@@ -374,10 +374,28 @@ public class TestParenting01NEWT extends UITestCase {
 
         int state = 0;
         Window.ReparentOperation reparentAction;
-        while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) {
+        while(animator1.isAnimating() && animator1.getTotalFPSDuration()<7*durationPerTest) {
             Thread.sleep(durationPerTest);
             switch(state) {
                 case 0:
+                    // top-level glWindow2 hide
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    Assert.assertEquals(true, glWindow2.isVisible());
+                    glWindow2.setVisible(false);
+                    Assert.assertEquals(false, glWindow2.isVisible());
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    break;
+
+                case 1:
+                    // top-level glWindow2 show
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    Assert.assertEquals(false, glWindow2.isVisible());
+                    glWindow2.setVisible(true);
+                    Assert.assertEquals(true, glWindow2.isVisible());
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    break;
+
+                case 2:
                     // glWindow2 -- child --> glWindow1: compatible
                     Assert.assertEquals(true, glWindow2.isVisible());
                     System.err.println("Frames(1) "+glWindow2.getTotalFPSFrames());
@@ -403,7 +421,25 @@ public class TestParenting01NEWT extends UITestCase {
 
                     break;
 
-                case 1:
+                case 3:
+                    // child glWindow2 hide
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    Assert.assertEquals(true, glWindow2.isVisible());
+                    glWindow2.setVisible(false);
+                    Assert.assertEquals(false, glWindow2.isVisible());
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    break;
+
+                case 4:
+                    // child glWindow2 show
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    Assert.assertEquals(false, glWindow2.isVisible());
+                    glWindow2.setVisible(true);
+                    Assert.assertEquals(true, glWindow2.isVisible());
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    break;
+
+                case 5:
                     // glWindow2 --> top
                     Assert.assertEquals(true, glWindow2.isVisible());
 
@@ -566,10 +602,29 @@ public class TestParenting01NEWT extends UITestCase {
 
         int state = 0;
         Window.ReparentOperation reparentAction;
-        while(animator1.isAnimating() && animator1.getTotalFPSDuration()<3*durationPerTest) {
+        while(animator1.isAnimating() && animator1.getTotalFPSDuration()<7*durationPerTest) {
             Thread.sleep(durationPerTest);
             switch(state) {
                 case 0:
+                    // child glWindow2 hide
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    Assert.assertEquals(true, glWindow2.isVisible());
+                    glWindow2.setVisible(false);
+                    Assert.assertEquals(false, glWindow2.isVisible());
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    break;
+
+                case 1:
+                    // child glWindow2 show
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    Assert.assertEquals(false, glWindow2.isVisible());
+                    glWindow2.setVisible(true);
+                    Assert.assertEquals(true, glWindow2.isVisible());
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    break;
+
+                case 2:
+                    // glWindow2 --> top
                     Assert.assertEquals(true, glWindow2.isVisible());
                     reparentAction = glWindow2.reparentWindow(null, -1, -1, reparentHints);
                     Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction);
@@ -584,7 +639,27 @@ public class TestParenting01NEWT extends UITestCase {
                     Assert.assertSame(display1,glWindow2.getScreen().getDisplay());
                     Assert.assertEquals(1,Display.getActiveDisplayNumber());
                     break;
-                case 1:
+
+                case 3:
+                    // top-level glWindow2 hide
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    Assert.assertEquals(true, glWindow2.isVisible());
+                    glWindow2.setVisible(false);
+                    Assert.assertEquals(false, glWindow2.isVisible());
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    break;
+
+                case 4:
+                    // top-level glWindow2 show
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    Assert.assertEquals(false, glWindow2.isVisible());
+                    glWindow2.setVisible(true);
+                    Assert.assertEquals(true, glWindow2.isVisible());
+                    Assert.assertEquals(true, glWindow1.isVisible());
+                    break;
+
+                case 5:
+                    // glWindow2 -- child --> glWindow1: compatible
                     Assert.assertEquals(true, glWindow2.isVisible());
                     reparentAction = glWindow2.reparentWindow(glWindow1, -1, -1, reparentHints);
                     Assert.assertTrue(Window.ReparentOperation.ACTION_INVALID != reparentAction);
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 82247a5..a08e9f8 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
@@ -3,14 +3,14 @@
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
- * 
+ *
  *    1. Redistributions of source code must retain the above copyright notice, this list of
  *       conditions and the following disclaimer.
- * 
+ *
  *    2. Redistributions in binary form must reproduce the above copyright notice, this list
  *       of conditions and the following disclaimer in the documentation and/or other materials
  *       provided with the distribution.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
+ *
  * The views and conclusions contained in the software and documentation are those of the
  * authors and should not be interpreted as representing official policies, either expressed
  * or implied, of JogAmp Community.
  */
- 
+
 package com.jogamp.opengl.test.junit.util;
 
 import java.io.BufferedReader;
@@ -69,15 +69,15 @@ 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   = 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;
-    
+
     private static volatile boolean testSupported = true;
     private static volatile boolean resetXRandRIfX11AfterClass = false;
-    
+
     private static volatile int maxMethodNameLen = 0;
 
     private static final synchronized void initSingletonInstance() {
@@ -89,11 +89,11 @@ public abstract class UITestCase {
             }
         }
     }
-    
+
     public static boolean isTestSupported() {
         return testSupported;
     }
-    
+
     public static void setTestSupported(boolean v) {
         System.err.println("setTestSupported: "+v);
         testSupported = v;
@@ -102,13 +102,13 @@ public abstract class UITestCase {
     public static void setResetXRandRIfX11AfterClass() {
         resetXRandRIfX11AfterClass = true;
     }
-    
+
     /**
      * Iterates through all outputs and sets the preferred mode and normal rotation using RandR 1.3.
      * <p>
      * With NV drivers, one need to add the Modes in proper order to the Screen's Subsection "Display",
      * otherwise they are either in unsorted resolution order or even n/a!
-     * </p> 
+     * </p>
      */
     @SuppressWarnings("unused")
     public static void resetXRandRIfX11() {
@@ -122,7 +122,7 @@ public abstract class UITestCase {
                     final ProcessBuilder pb = new ProcessBuilder("xrandr", "-q");
                     pb.redirectErrorStream(true);
                     System.err.println("XRandR Query: "+pb.command());
-                    final Process p = pb.start();                    
+                    final Process p = pb.start();
                     final MiscUtils.StreamDump dump = new MiscUtils.StreamDump( out, p.getInputStream(), ioSync );
                     dump.start();
                     while( !dump.eos() ) {
@@ -185,7 +185,7 @@ public abstract class UITestCase {
         }
         return null;
     }
-    
+
     public static int processCommand(String[] cmdline, OutputStream outstream, String outPrefix) {
         int errorCode = 0;
         final Object ioSync = new Object();
@@ -207,9 +207,9 @@ public abstract class UITestCase {
             e.printStackTrace();
             errorCode = Integer.MIN_VALUE;
         }
-        return errorCode;            
+        return errorCode;
     }
-    
+
     public int getMaxTestNameLen() {
         if(0 == maxMethodNameLen) {
             int ml = 0;
@@ -221,13 +221,13 @@ public abstract class UITestCase {
             }
             maxMethodNameLen = ml;
         }
-        return maxMethodNameLen; 
+        return maxMethodNameLen;
     }
-    
+
     public final String getTestMethodName() {
         return _unitTestName.getMethodName();
     }
-    
+
     public final String getSimpleTestName(String separator) {
         return getClass().getSimpleName()+separator+getTestMethodName();
     }
@@ -235,10 +235,10 @@ public abstract class UITestCase {
     public final String getFullTestName(String separator) {
         return getClass().getName()+separator+getTestMethodName();
     }
-    
+
     @BeforeClass
     public static void oneTimeSetUp() {
-        // one-time initialization code                
+        // one-time initialization code
         initSingletonInstance();
     }
 
@@ -259,14 +259,14 @@ public abstract class UITestCase {
             System.err.println(" - "+unsupportedTestMsg);
             Assume.assumeTrue(testSupported); // abort
         }
-        System.err.println();      
+        System.err.println();
     }
 
     @After
     public void tearDown() {
         System.err.println("++++ UITestCase.tearDown: "+getFullTestName(" - "));
     }
-    
+
     public static void waitForKey(String preMessage) {
         BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
         System.err.println(preMessage+"> Press enter to continue");
@@ -274,7 +274,7 @@ public abstract class UITestCase {
             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) {
@@ -284,7 +284,7 @@ public abstract class UITestCase {
         final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1;
         final String simpleTestName = this.getSimpleTestName(".");
         final String filenameBaseName;
-        {            
+        {
             final String accel = caps.getHardwareAccelerated() ? "hw" : "sw" ;
             final String scrnm;
             if(caps.isOnscreen()) {
@@ -307,22 +307,22 @@ public abstract class UITestCase {
             final String aaext = caps.getSampleExtension();
             postSNDetail = null != postSNDetail ? "-"+postSNDetail : "";
 
-            filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-D%02d-St%02d-Sa%02d_%s-%04dx%04d.%s", 
-                    simpleTestName, sn, postSNDetail, caps.getGLProfile().getName(), accel, 
-                    scrnm, dblb, F_pfmt, pfmt, depthBits, stencilBits, samples, aaext,  
+            filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-D%02d-St%02d-Sa%02d_%s-%04dx%04d.%s",
+                    simpleTestName, sn, postSNDetail, caps.getGLProfile().getName(), accel,
+                    scrnm, dblb, F_pfmt, pfmt, depthBits, stencilBits, samples, aaext,
                     width, height, fileSuffix).replace(' ', '_');
         }
-        return null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName;        
+        return null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName;
     }
-    
+
     /**
-     * Takes a snapshot of the drawable's current front framebuffer. Example filenames: 
+     * Takes a snapshot of the drawable's current front framebuffer. Example filenames:
      * <pre>
      * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgba8888_-D24-St00-Sa00_default-0400x0300.png
      * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgba8880-D24-St00-Sa00_default-0200x0150.png
      * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgba5551-D24-St00-Sa00_default-0200x0150.png
      * </pre>
-     * @param sn sequential number 
+     * @param sn sequential number
      * @param postSNDetail optional detail to be added to the filename after <code>sn</code>
      * @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename.
      * @param readBufferUtil the {@link GLReadBufferUtil} to be used to read the pixels for the screenshot.
@@ -330,20 +330,20 @@ public abstract class UITestCase {
      *                   If <code>null</code> the <code>"png"</code> as defined in {@link TextureIO#PNG} is being used.
      * @param destPath Optional platform dependent file path. It shall use {@link File#separatorChar} as is directory separator.
      *                 It shall not end with a directory separator, {@link File#separatorChar}.
-     *                 If <code>null</code> the current working directory is being used.  
+     *                 If <code>null</code> the current working directory is being used.
      */
     public void snapshot(int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
         final GLDrawable drawable = gl.getContext().getGLReadDrawable();
-        final String filename = getSnapshotFilename(sn, postSNDetail, 
-                                                    drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(), 
+        final String filename = getSnapshotFilename(sn, postSNDetail,
+                                                    drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
                                                     readBufferUtil.hasAlpha(), fileSuffix, destPath);
         System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename);
         gl.glFinish(); // just make sure rendering finished ..
         if(readBufferUtil.readPixels(gl, false)) {
             readBufferUtil.write(new File(filename));
-        }                
+        }
     }
-    
+
     public class SnapshotGLEventListener implements GLEventListener {
         private final GLReadBufferUtil screenshot;
         private volatile boolean makeShot = false;
@@ -394,6 +394,6 @@ public abstract class UITestCase {
             postSNDetail = v;
         }
     };
-    
+
 }
 

-- 
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