From 20bf031db719f7baa4c6e74734fc999061e08fe2 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Thu, 19 Jul 2012 21:15:10 +0200
Subject: Bug 599 - FBObject / Offscreen Support - Part 1

- New FBObject implementation handling FBO and it's attachments  *** API CHANGE: Util -> Core ***
  while it's size and sample-count can be reconfigured on the fly.
    - com.jogamp.opengl.util.FBObject -> com.jogamp.opengl.FBObject
    - agnostic to texture unit
    - separate attachments using OO hierarchy reflecting FBO
    - handling MSAA and blitting
    - no FBO destruction for reconfig (attach/detach)

- New GLFBODrawableImpl impl. an FBObject based GLDrawable
   - Instantiated by a dummy native surface (onscreen and invisible)
     hooked up to a dummy GLDrawable, which is the delegation for context creation.

   - Utilizies ProxySurface.UpstreamSurfaceHook for dummy surface
     avoiding specialization for native platforms.

   - TODO: Allow to utilize common surface interface as a
     dummy-surface to supporting API seperation of
     windowing/GL. The latter allows impl. of createGLDrawable(NativeSurface)
     with FBO.

- New OffscreenAutoDrawable (extends GLAutoDrawableDelegate)
  for all offscreen drawables. Shall replace GLPbuffer.

- New GLCapabilities*.isFBO() / setFBO(boolean) to request FBO offscreen,
  similar to isPBuffer(). Rule: if both are requested, FBO shall be favored.

- GLContext adds raw FBO availability query (min. FBO avail),
  FBObject contains fine grained queries (TODO: Move parts to GLContext for efficiency).

- Add framebuffer tracking, allowing fast querying:
  - GLBase/GLContext:
      public int getBoundFramebuffer(int target);
      public int getDefaultDrawFramebuffer();
      public int getDefaultReadFramebuffer();

  - GLContextImpl
      public final void setBoundFramebuffer(int target, int framebufferName)
      .. called by GL impl bind framebuffer

- GL: getDefaultDrawFramebuffer(), getDefaultReadFramebuffer()
  Adding default framebuffer queries being issued by
  GL.glBindFramebuffer(target, 0) w/ a default framebuffer, o.e. zero.
  This allows a transparent use of a custom FBO even in case the applications
  attempts to reset FBO to zero.
    Value flow: GL <- GLContext <- GLDrawable,

- GLCapabilities handle fbo/pbuffer seperate, don't disable the other

- GLContext/GL track read/write framebuffer to be queried by FBObject
  to determine whether to bind/unbind  a framebuffer

- Test cases for multiple FBO w/ and w/o MSAA

Other Features:

- New interface ProxySurface.UpstreamSurfaceHook,
  allowing to hook an upstream surface of unknown type
  providing lifecycle and information (size, ..) callbacks.
  Used for all new dummy NativeSurface impl and SWT GLCanvas.

  - GLContext -> GLDrawable propagation context/drawable lifecycle
    via ProxySurface.UpstreamSurfaceHook allowing dynamic resources
    to react (create, init, ..)
    - contextRealized()
    - contextMadeCurrent()

- SurfaceChangeable -> MutableSurface
  currently only contains setting the surface handle.

  TODO: May need to move ProxySurface.UpstreamSurfaceHook -> MutableSurface.UpstreamSurfaceHook,
        allowing other impl. classes (NEWT OffscreenWindow) to utilize the new
        upstream hookup mechanism - will allow FBO/Dummy window to work.

- SWT GLCanvas using ProxySurface.UpstreamSurfaceHook for proper size
  propagation.

- New GLAutoDrawable::getUpstreamWidget(), allowing GLEventListener
  to fetch the owning Java side UI element (NEWT, SWT, AWT, ..).

- GLDrawableFactory: Removed createOffscreenSurface() - unused and not GL related

- EGLDrawableFactory handles device/profile avail. mapping
  while actually creating context/drawable.
  This allows us to learn whether the ES context is software/hardware as well as FBO avail.

- EGLDrawable: Removed secret buckets of EGL configs :)
  Employ native surface (X11, WGL, ..) to EGL 'mapping' in
  EGLDrawableFactory utilizing new EGLUpstreamSurfaceHook (implements ProxySurface.UpstreamSurfaceHook).

Other Bugs:

- Add CTX_OPTION_DEBUG to ctx/extension cache key since only a debug ctx
  may expose the ARB debug capability.
  This bug caused lack of ARB/AMD debug functionality.

- Fix GLProfile deadlock (debug mode, w/ EGL/ES, no X11),
  dump availability information _after_ lock.

- ImmModeSink draw(): Use GL's glDrawElements(..), don't cast for GL2ES1.
  Fixes use for GL2ES2.

- Fix KeyEvent.getKeyChar() comment (-> only stable for keyTyped(..))

Misc:

- Refined alot of API doc

- New GLExtensions holds commonly used GL extension strings,
  allows better referencing and usage lookup.

- Move GL (interface) decl. to GLBase

- GLBuffers: Cleanup API doc (format, types)

- TextureIO: Add PAM and PPM static suffix identifier

- GLCapabilities getNumSamples() returns 0 if sampleBuffers is disabled, this seems to be more natural.

- finalized a lot
---
 src/jogl/classes/jogamp/opengl/egl/EGLContext.java |  76 +++--
 .../classes/jogamp/opengl/egl/EGLDisplayUtil.java  |  27 +-
 .../classes/jogamp/opengl/egl/EGLDrawable.java     | 214 +++++---------
 .../jogamp/opengl/egl/EGLDrawableFactory.java      | 307 ++++++++++++++++++---
 .../opengl/egl/EGLGraphicsConfiguration.java       |   2 +-
 .../egl/EGLGraphicsConfigurationFactory.java       |  65 ++---
 .../jogamp/opengl/egl/EGLOnscreenDrawable.java     |   4 +-
 .../jogamp/opengl/egl/EGLPbufferDrawable.java      |  34 +--
 .../jogamp/opengl/egl/EGLUpstreamSurfaceHook.java  |  56 ++++
 9 files changed, 505 insertions(+), 280 deletions(-)
 create mode 100644 src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java

(limited to 'src/jogl/classes/jogamp/opengl/egl')

diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
index 65a4c3ece..c5d0df645 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
@@ -110,14 +110,8 @@ public abstract class EGLContext extends GLContextImpl {
 
     @Override
     protected void makeCurrentImpl() throws GLException {
-        if(EGL.EGL_NO_DISPLAY==((EGLDrawable)drawable).getDisplay() ) {
-            throw new GLException("drawable not properly initialized, NO DISPLAY: "+drawable);
-        }
         if (EGL.eglGetCurrentContext() != contextHandle) {
-            if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
-                                    drawable.getHandle(),
-                                    drawableRead.getHandle(),
-                                    contextHandle)) {
+            if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
                 throw new GLException("Error making context 0x" +
                                       Long.toHexString(contextHandle) + " current: error code 0x" + Integer.toHexString(EGL.eglGetError()));
             }
@@ -126,10 +120,7 @@ public abstract class EGLContext extends GLContextImpl {
 
     @Override
     protected void releaseImpl() throws GLException {
-      if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
-                              EGL.EGL_NO_SURFACE,
-                              EGL.EGL_NO_SURFACE,
-                              EGL.EGL_NO_CONTEXT)) {
+      if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT)) {
             throw new GLException("Error freeing OpenGL context 0x" +
                                   Long.toHexString(contextHandle) + ": error code 0x" + Integer.toHexString(EGL.eglGetError()));
       }
@@ -137,7 +128,7 @@ public abstract class EGLContext extends GLContextImpl {
 
     @Override
     protected void destroyImpl() throws GLException {
-      if (!EGL.eglDestroyContext(((EGLDrawable)drawable).getDisplay(), contextHandle)) {
+      if (!EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), contextHandle)) {
           final int eglError = EGL.eglGetError();
           if(EGL.EGL_SUCCESS != eglError) { /* oops, Mesa EGL impl. may return false, but has no EGL error */
               throw new GLException("Error destroying OpenGL context 0x" +
@@ -158,16 +149,16 @@ public abstract class EGLContext extends GLContextImpl {
 
     @Override
     protected boolean createImpl(GLContextImpl shareWith) throws GLException {
-        long eglDisplay = ((EGLDrawable)drawable).getDisplay();
-        EGLGraphicsConfiguration config = ((EGLDrawable)drawable).getGraphicsConfiguration();
-        GLProfile glProfile = drawable.getGLProfile();
-        long eglConfig = config.getNativeConfig();
+        final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
+        final long eglDisplay = config.getScreen().getDevice().getHandle();
+        final GLProfile glProfile = drawable.getGLProfile();
+        final long eglConfig = config.getNativeConfig();
         long shareWithHandle = EGL.EGL_NO_CONTEXT;
 
-        if (eglDisplay == 0) {
+        if ( 0 == eglDisplay ) {
             throw new GLException("Error: attempted to create an OpenGL context without a display connection");
         }
-        if (eglConfig == 0) {
+        if ( 0 == eglConfig ) {
             throw new GLException("Error: attempted to create an OpenGL context without a graphics configuration");
         }
 
@@ -217,10 +208,7 @@ public abstract class EGLContext extends GLContextImpl {
                                ",\n\t"+this+
                                ",\n\tsharing with 0x" + Long.toHexString(shareWithHandle));
         }
-        if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
-                                drawable.getHandle(),
-                                drawableRead.getHandle(),
-                                contextHandle)) {
+        if (!EGL.eglMakeCurrent(eglDisplay, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
             throw new GLException("Error making context 0x" +
                                   Long.toHexString(contextHandle) + " current: error code " + EGL.eglGetError());
         }
@@ -269,8 +257,7 @@ public abstract class EGLContext extends GLContextImpl {
           eglQueryStringInitialized = true;
         }
         if (eglQueryStringAvailable) {
-            final String ret = EGL.eglQueryString(((EGLDrawable)drawable).getDisplay(),
-                                                  EGL.EGL_EXTENSIONS);
+            final String ret = EGL.eglQueryString(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_EXTENSIONS);
             if (DEBUG) {
               System.err.println("EGL extensions: " + ret);
             }
@@ -291,7 +278,7 @@ public abstract class EGLContext extends GLContextImpl {
             }
             return false;
         }
-        return EGL.eglSwapInterval(((EGLDrawable)drawable).getDisplay(), interval);
+        return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval);
     }
 
     @Override
@@ -300,6 +287,45 @@ public abstract class EGLContext extends GLContextImpl {
     @Override
     public abstract void releasePbufferFromTexture();
 
+    //
+    // Accessible ..
+    //
+    
+    /**
+     * If context is an ES profile, map it to the given device 
+     * via {@link GLContext#mapAvailableGLVersion(AbstractGraphicsDevice, int, int, int, int, int)}.
+     * <p>
+     * We intentionally override a non native EGL device ES profile mapping,
+     * i.e. this will override/modify an already 'set' X11/WGL/.. mapping.
+     * </p> 
+     * 
+     * @param device
+     */
+    protected void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) {
+        mapCurrentAvailableGLVersionImpl(device, ctxMajorVersion, ctxMinorVersion, ctxOptions);
+    }
+        
+    protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) {
+        int ctp = ( 2 == major ) ? ( GLContext.CTX_PROFILE_ES | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) : ( GLContext.CTX_PROFILE_ES );  
+        mapCurrentAvailableGLVersionImpl(device, major, 0, ctp);
+    }
+    private static void mapCurrentAvailableGLVersionImpl(AbstractGraphicsDevice device, int major, int minor, int ctp) {
+        if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) {
+            // ES1 or ES2
+            final int reqMajor = major;
+            final int reqProfile = GLContext.CTX_PROFILE_ES;
+            GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
+                                            major, minor, ctp);
+        }
+    }
+    
+    protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+        return GLContext.getAvailableGLVersionsSet(device);
+    }
+    protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+        GLContext.setAvailableGLVersionsSet(device);
+    }
+    
     protected static String toHexString(int hex) {
         return GLContext.toHexString(hex);
     }
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
index 7f10d3bd9..432010f49 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
@@ -136,7 +136,17 @@ public class EGLDisplayUtil {
         return res;
     }
     
-    public static final EGLGraphicsDevice.EGLTerminateCallback eglTerminateCallback = new EGLGraphicsDevice.EGLTerminateCallback() {
+    public static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() {
+        public long eglGetAndInitDisplay(long nativeDisplayID) {
+            long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID);
+            if (eglDisplay == EGL.EGL_NO_DISPLAY) {
+                throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+            }
+            if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
+                throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+            }
+            return eglDisplay;
+        }
         public void eglTerminate(long eglDisplayHandle) {
             EGLDisplayUtil.eglTerminate(eglDisplayHandle);
         }
@@ -148,17 +158,12 @@ public class EGLDisplayUtil {
      * @param unitID
      * @return an initialized EGLGraphicsDevice 
      * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails
-     * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLTerminateCallback) 
+     * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLDisplayLifecycleCallback) 
      */
     public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID)  {
-        long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID);
-        if (eglDisplay == EGL.EGL_NO_DISPLAY) {
-            throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError()));
-        }
-        if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
-            throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError()));
-        }
-        return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, connection, unitID, eglTerminateCallback);
+        final EGLGraphicsDevice eglDisplay = new EGLGraphicsDevice(nativeDisplayID, 0, connection, unitID, eglLifecycleCallback);
+        eglDisplay.open();
+        return eglDisplay;
     }
     
     /**
@@ -189,6 +194,6 @@ public class EGLDisplayUtil {
             throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError()));
         }
         final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice();
-        return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglTerminateCallback);                                            
+        return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglLifecycleCallback);                                            
     }
 }
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
index d777c4f04..383b61f88 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
@@ -36,82 +36,65 @@
 
 package jogamp.opengl.egl;
 
-import jogamp.opengl.GLDynamicLookupHelper;
-import jogamp.opengl.GLDrawableImpl;
+import javax.media.nativewindow.MutableSurface;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
 
-import javax.media.nativewindow.*;
-import javax.media.nativewindow.VisualIDHolder.VIDType;
-import javax.media.opengl.*;
+import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.GLDynamicLookupHelper;
 
-import com.jogamp.nativewindow.egl.*;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
 
 public abstract class EGLDrawable extends GLDrawableImpl {
-    private boolean ownEGLDisplay = false; // for destruction
     private boolean ownEGLSurface = false; // for destruction
-    private EGLGraphicsConfiguration eglConfig;
-    private EGLGraphicsDevice eglDevice;
-    private long eglSurface;
 
-    protected EGLDrawable(EGLDrawableFactory factory,
-                       NativeSurface component) throws GLException {
+    protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException {
         super(factory, component, false);
-        eglSurface=EGL.EGL_NO_SURFACE;
-        eglDevice=null;
-    }
-
-    public final long getDisplay() {
-        return null != eglDevice ? eglDevice.getHandle() : 0;
-    }
-
-    @Override
-    public final long getHandle() {
-        return eglSurface;
-    }
-
-    public final EGLGraphicsConfiguration getGraphicsConfiguration() {
-        return eglConfig;
-    }
-
-    @Override
-    public final GLCapabilitiesImmutable getChosenGLCapabilities() {
-        return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilitiesImmutable)eglConfig.getChosenCapabilities();
     }
 
     @Override
     public abstract GLContext createContext(GLContext shareWith);
 
-    protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle);
+    protected abstract long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle);
 
     private final void recreateSurface() {
-        // create a new EGLSurface ..
-        if(EGL.EGL_NO_SURFACE!=eglSurface) {
-            EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface);
-        }
-
+        final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration();
+        final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice();
         if(DEBUG) {
-            System.err.println(getThreadName() + ": createSurface using "+eglDevice+", "+eglConfig);
+            System.err.println(getThreadName() + ": createSurface using "+eglConfig);
+        }        
+        if( EGL.EGL_NO_SURFACE != surface.getSurfaceHandle() ) {
+            EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle());
         }
-
-        eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surface.getSurfaceHandle());
-        int eglError0 = EGL.EGL_SUCCESS;
+        
+        final EGLUpstreamSurfaceHook upstreamHook = (EGLUpstreamSurfaceHook) ((ProxySurface)surface).getUpstreamSurfaceHook();
+        final NativeSurface upstreamSurface = upstreamHook.getUpstreamSurface();
+        long eglSurface = createSurface(eglConfig, upstreamSurface.getSurfaceHandle());
+        
+        int eglError0;
         if (EGL.EGL_NO_SURFACE == eglSurface) {
             eglError0 = EGL.eglGetError();
             if(EGL.EGL_BAD_NATIVE_WINDOW == eglError0) {
                 // Try window handle if available and differs (Windows HDC / HWND).
                 // ANGLE impl. required HWND on Windows.
-                if(surface instanceof NativeWindow) {
-                    final NativeWindow nw = (NativeWindow) surface;
+                if(upstreamSurface instanceof NativeWindow) {
+                    final NativeWindow nw = (NativeWindow) upstreamSurface;
                     if(nw.getWindowHandle() != nw.getSurfaceHandle()) {
                         if(DEBUG) {
                             System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle");
                         }
-                        eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), nw.getWindowHandle());
+                        eglSurface = createSurface(eglConfig, nw.getWindowHandle());
                         if (EGL.EGL_NO_SURFACE == eglSurface) {
                             eglError0 = EGL.eglGetError();
                         }
                     }
                 }
             }
+        } else {
+            eglError0 = EGL.EGL_SUCCESS;
         }
         if (EGL.EGL_NO_SURFACE == eglSurface) {
             throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0));
@@ -120,6 +103,8 @@ public abstract class EGLDrawable extends GLDrawableImpl {
         if(DEBUG) {
             System.err.println(getThreadName() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface));
         }
+        
+        ((MutableSurface)surface).setSurfaceHandle(eglSurface);
     }
 
     @Override
@@ -131,123 +116,71 @@ public abstract class EGLDrawable extends GLDrawableImpl {
 
     @Override
     protected final void setRealizedImpl() {
+        final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration();
+        final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice();
         if (realized) {
-            AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration();
-            AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice();
-            if(aDevice instanceof EGLGraphicsDevice) {
+            final long eglDisplayHandle = eglDevice.getHandle();
+            if (EGL.EGL_NO_DISPLAY == eglDisplayHandle) {
+                throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice);
+            }
+            int[] tmp = new int[1];
+            boolean eglSurfaceValid = 0 != surface.getSurfaceHandle();
+            if(eglSurfaceValid) {
+                eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0);
+                if(!eglSurfaceValid) {
+                    if(DEBUG) {
+                        System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl eglQuerySuface failed: "+toHexString(EGL.eglGetError())+", "+surface);
+                    }                    
+                }
+            }
+            if(eglSurfaceValid) {
+                // surface holds valid EGLSurface
                 if(DEBUG) {
-                    System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): using existing EGL config - START");
+                    System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl re-using component's EGLSurface: handle "+toHexString(surface.getSurfaceHandle()));
+                }
+                ownEGLSurface=false;
+            } else {
+                // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface();
+                // However .. let's validate the surface object first
+                if( ! (surface instanceof ProxySurface) ) {
+                    throw new InternalError("surface not ProxySurface: "+surface.getClass().getName()+", "+surface);
                 }
-                // just fetch the data .. trust but verify ..
-                ownEGLDisplay = false;
-                eglDevice = (EGLGraphicsDevice) aDevice;
-                if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) {
-                    throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice);
+                final ProxySurface.UpstreamSurfaceHook upstreamHook = ((ProxySurface)surface).getUpstreamSurfaceHook();
+                if( null == upstreamHook ) {
+                    throw new InternalError("null upstreamHook of: "+surface);
                 }
-                if(aConfig instanceof EGLGraphicsConfiguration) {
-                    eglConfig = (EGLGraphicsConfiguration) aConfig; // done ..
-                    if (null == eglConfig) {
-                        throw new GLException("Null EGLGraphicsConfiguration from "+aConfig);
-                    }
-
-                    int[] tmp = new int[1];
-                    if ( 0 != surface.getSurfaceHandle() &&
-                         EGL.eglQuerySurface(eglDevice.getHandle(), surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) {
-                        // surface holds static EGLSurface
-                        eglSurface = surface.getSurfaceHandle();
-                        if(DEBUG) {
-                            System.err.println(getThreadName() + ": setSurface re-using component's EGLSurface: handle "+toHexString(eglSurface));
-                        }
-                        ownEGLSurface=false;
-                    } else {
-                        // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface();
-                        ownEGLSurface=true;
-                    }
-                } else {
-                    throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig);
+                if( ! (upstreamHook instanceof EGLUpstreamSurfaceHook) ) {
+                    throw new InternalError("upstreamHook not EGLUpstreamSurfaceHook: Surface: "+surface.getClass().getName()+", "+surface+"; UpstreamHook: "+upstreamHook.getClass().getName()+", "+upstreamHook);
                 }
-            } else {
-                if(DEBUG) {
-                    System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): creating new EGL config - START");
+                if( null == ((EGLUpstreamSurfaceHook)upstreamHook).getUpstreamSurface() ) {
+                    throw new InternalError("null upstream surface");
                 }
-                // create a new EGL config ..
-                ownEGLDisplay=true;
-                // EGLSurface is ours ..
                 ownEGLSurface=true;
-
-                eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true);
-                AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex());
-                final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
-                if(aConfig instanceof EGLGraphicsConfiguration) {
-                    final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities();
-                    if(0 == capsChosen.getEGLConfig()) {
-                        // 'refresh' the native EGLConfig handle
-                        capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID()));
-                        if(0 == capsChosen.getEGLConfig()) {
-                            throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig);
-                        }
-                    }
-                    eglConfig  = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null);
-                    if(DEBUG) {
-                        System.err.println(getThreadName() + ": Reusing chosenCaps: "+eglConfig);
-                    }
-                } else {
-                    eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
-                            capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false);
-
-                    if (null == eglConfig) {
-                        throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen);
-                    } else if(DEBUG) {
-                        System.err.println(getThreadName() + ": Chosen eglConfig: "+eglConfig);
-                    }
+                if(DEBUG) {
+                    System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl owning EGLSurface");
                 }
-                // subsequent updateHandle() will issue recreateSurface();
-            }
-            if(DEBUG) {
-                System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): END: ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface);
             }
-        } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) {
+        } else if (ownEGLSurface && surface.getSurfaceHandle() != EGL.EGL_NO_SURFACE) {
             if(DEBUG) {
-                System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(eglSurface));
+                System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(surface.getSurfaceHandle()));
             }
             // Destroy the window surface
-            if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) {
+            if (!EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle())) {
                 throw new GLException("Error destroying window surface (eglDestroySurface)");
             }
-            eglSurface = EGL.EGL_NO_SURFACE;
-            eglConfig=null;
-            eglDevice.close();
-            eglDevice=null;
+            ((MutableSurface)surface).setSurfaceHandle(EGL.EGL_NO_SURFACE);
         }
     }
 
     @Override
     protected final void swapBuffersImpl() {
+        final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
         // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers()
-        if(!EGL.eglSwapBuffers(eglDevice.getHandle(), eglSurface)) {
+        if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) {
             throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this);
         }
     }
 
-    /**
-     * Surface not realizes yet (onscreen) .. Quering EGL surface size only makes sense for external drawable.
-     * Leave it here for later impl. of an EGLExternalDrawable.
-    public int getWidth() {
-        int[] tmp = new int[1];
-        if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) {
-            throw new GLException("Error querying surface width, eglError "+toHexString(EGL.eglGetError()));
-        }
-        return tmp[0];
-    }
-
-    public int getHeight() {
-        int[] tmp = new int[1];
-        if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) {
-            throw new GLException("Error querying surface height, eglError "+toHexString(EGL.eglGetError()));
-        }
-        return tmp[0];
-    } */
-
     @Override
     public GLDynamicLookupHelper getGLDynamicLookupHelper() {
         if (getGLProfile().usesNativeGLES2()) {
@@ -263,10 +196,9 @@ public abstract class EGLDrawable extends GLDrawableImpl {
     public String toString() {
         return getClass().getName()+"[realized "+isRealized()+
                     ",\n\tfactory    "+getFactory()+
-                    ",\n\tdevice     "+eglDevice+
                     ",\n\tsurface    "+getNativeSurface()+
-                    ",\n\teglSurface "+toHexString(eglSurface)+
-                    ",\n\teglConfig  "+eglConfig+
+                    ",\n\teglSurface "+toHexString(surface.getSurfaceHandle())+
+                    ",\n\teglConfig  "+surface.getGraphicsConfiguration()+
                     ",\n\trequested  "+getRequestedGLCapabilities()+
                     ",\n\tchosen     "+getChosenGLCapabilities()+"]";
     }
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index f4fa1f13f..c848e3e5c 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -46,21 +46,29 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration;
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.AbstractGraphicsScreen;
 import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.MutableSurface;
 import javax.media.nativewindow.NativeSurface;
 import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
 import javax.media.nativewindow.VisualIDHolder;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLCapabilitiesChooser;
 import javax.media.opengl.GLCapabilitiesImmutable;
 import javax.media.opengl.GLContext;
 import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
 import javax.media.opengl.GLException;
 import javax.media.opengl.GLProfile;
 import javax.media.opengl.GLProfile.ShutdownType;
 
+import jogamp.opengl.Debug;
 import jogamp.opengl.GLDrawableFactoryImpl;
 import jogamp.opengl.GLDrawableImpl;
 import jogamp.opengl.GLDynamicLookupHelper;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
 
 import com.jogamp.common.JogampRuntimeException;
 import com.jogamp.common.os.Platform;
@@ -69,6 +77,9 @@ import com.jogamp.nativewindow.WrappedSurface;
 import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
 
 public class EGLDrawableFactory extends GLDrawableFactoryImpl {
+    /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true);
+    /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true);
+    
     private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null;
     private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null;
     private static boolean isANGLE = false;
@@ -231,7 +242,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
       // final EGLContext getContextES1() { return contextES1; }
       // final EGLContext getContextES2() { return contextES2; }
       final boolean wasES1ContextAvailable() { return wasES1ContextCreated; }
-      final boolean wasES2ContextAvailable() { return wasES2ContextCreated; }
+      final boolean wasES2ContextAvailable() { return wasES2ContextCreated; }      
     }
 
     @Override
@@ -245,35 +256,98 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
       return null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper;
     }
 
-    /**
-    private boolean isEGLContextAvailable(EGLGraphicsDevice sharedDevice, String profile) {
-        boolean madeCurrent = false;
-        final GLCapabilities caps = new GLCapabilities(GLProfile.get(profile));
-        caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
-        caps.setDoubleBuffered(false);
-        caps.setOnscreen(false);
-        caps.setPBuffer(true);
-        final EGLDrawable drawable = (EGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) );
-        if(null!=drawable) {
+    private boolean isEGLContextAvailable(AbstractGraphicsDevice adevice, EGLGraphicsDevice sharedEGLDevice, String profileString) {
+        if( !GLProfile.isAvailable(adevice, profileString) ) {
+            return false;
+        }
+        final GLProfile glp = GLProfile.get(adevice, profileString) ;
+        final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory();
+        EGLGraphicsDevice eglDevice = null;
+        NativeSurface surface = null;
+        ProxySurface upstreamSurface = null; // X11, GLX, ..
+        boolean success = false;
+        boolean deviceFromUpstreamSurface = false;
+        try {            
+            final GLCapabilities caps = new GLCapabilities(glp);
+            caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
+            if(adevice instanceof EGLGraphicsDevice || null == desktopFactory || !QUERY_EGL_ES_NATIVE_TK) {
+                eglDevice = sharedEGLDevice; // reuse
+                surface = createDummySurfaceImpl(eglDevice, false, caps, null, 64, 64); // egl pbuffer offscreen
+                upstreamSurface = (ProxySurface)surface;
+                upstreamSurface.createNotify();
+                deviceFromUpstreamSurface = false;
+            } else {
+                surface = desktopFactory.createDummySurface(adevice, caps, null, 64, 64); // X11, WGL, .. dummy window
+                upstreamSurface = ( surface instanceof ProxySurface ) ? (ProxySurface)surface : null ;
+                if(null != upstreamSurface) {
+                    upstreamSurface.createNotify();
+                }                    
+                eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true);
+                deviceFromUpstreamSurface = true;
+            }
+            
+            final EGLDrawable drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface );
+            drawable.setRealized(true);
             final EGLContext context = (EGLContext) drawable.createContext(null);
             if (null != context) {
-                context.setSynchronized(true);
                 try {
                     context.makeCurrent(); // could cause exception
-                    madeCurrent = context.isCurrent();
+                    success = context.isCurrent();
+                    if(success) {
+                        final String glVersion = context.getGL().glGetString(GL.GL_VERSION);
+                        if(null == glVersion) {
+                            // Oops .. something is wrong
+                            if(DEBUG) {
+                                System.err.println("EGLDrawableFactory.isEGLContextAvailable: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!");                                
+                            }
+                            success = false;
+                        }
+                    }
+                    if(success) {
+                        context.mapCurrentAvailableGLVersion(eglDevice);
+                        if(eglDevice != adevice) {
+                            context.mapCurrentAvailableGLVersion(adevice);
+                        }
+                    }
                 } catch (GLException gle) {
                     if (DEBUG) {
-                        System.err.println("EGLDrawableFactory.createShared: INFO: makeCurrent failed");
+                        System.err.println("EGLDrawableFactory.createShared: INFO: context create/makeCurrent failed");
                         gle.printStackTrace();
                     }
                 } finally {
                     context.destroy();
                 }
             }
-            drawable.destroy();
+            drawable.setRealized(false);
+        } catch (Throwable t) {
+            if(DEBUG) {
+                System.err.println("Catched Exception:");
+                t.printStackTrace();
+            }
+            success = false;
+        } finally {
+            if(eglDevice == sharedEGLDevice) {
+                if(null != upstreamSurface) {
+                    upstreamSurface.destroyNotify();
+                }                
+            } else if( deviceFromUpstreamSurface ) {
+                if(null != eglDevice) {
+                    eglDevice.close();
+                }
+                if(null != upstreamSurface) {
+                    upstreamSurface.destroyNotify();
+                }
+            } else {
+                if(null != upstreamSurface) {
+                    upstreamSurface.destroyNotify();
+                }                
+                if(null != eglDevice) {
+                    eglDevice.close();
+                }
+            }
         }
-        return madeCurrent;
-    } */
+        return success;
+    }
 
     /* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) {
         if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) {
@@ -285,18 +359,41 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
             sr = sharedMap.get(connection);
         }
         if(null==sr) {
-            final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, connection, adevice.getUnitID());
+            final boolean madeCurrentES1;            
+            final boolean madeCurrentES2;
+            final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
             
-            // final boolean madeCurrentES1 = isEGLContextAvailable(sharedDevice, GLProfile.GLES1);
-            // final boolean madeCurrentES2 = isEGLContextAvailable(sharedDevice, GLProfile.GLES2);
-            final boolean madeCurrentES1 = true; // FIXME
-            final boolean madeCurrentES2 = true; // FIXME
+            if(QUERY_EGL_ES) {
+                madeCurrentES1 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES1);
+                madeCurrentES2 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES2);                
+            } else {            
+                madeCurrentES1 = true;            
+                madeCurrentES2 = true;
+                EGLContext.mapStaticGLESVersion(sharedDevice, 1);
+                if(sharedDevice != adevice) {
+                    EGLContext.mapStaticGLESVersion(adevice, 1);
+                }
+                EGLContext.mapStaticGLESVersion(sharedDevice, 2);
+                if(sharedDevice != adevice) {
+                    EGLContext.mapStaticGLESVersion(adevice, 2);
+                }
+            }
+            
+            if( !EGLContext.getAvailableGLVersionsSet(adevice) ) {
+                // Even though we override the non EGL native mapping intentionally,
+                // avoid exception due to double 'set' - carefull exception of the rule. 
+                EGLContext.setAvailableGLVersionsSet(adevice);
+            }
             sr = new SharedResource(sharedDevice, madeCurrentES1, madeCurrentES2);
+            
             synchronized(sharedMap) {
                 sharedMap.put(connection, sr);
+                if(adevice != sharedDevice) {
+                    sharedMap.put(sharedDevice.getConnection(), sr);
+                }
             }
             if (DEBUG) {
-                System.err.println("EGLDrawableFactory.createShared: device:  " + sharedDevice);
+                System.err.println("EGLDrawableFactory.createShared: devices:  queried " + QUERY_EGL_ES + "[nativeTK "+QUERY_EGL_ES_NATIVE_TK+"], " + adevice + ", " + sharedDevice);
                 System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1);
                 System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2);
             }
@@ -367,8 +464,51 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
         if (target == null) {
           throw new IllegalArgumentException("Null target");
         }
-        return new EGLOnscreenDrawable(this, target);
+        return new EGLOnscreenDrawable(this, getEGLSurface(target));
+    }
+    
+    protected static NativeSurface getEGLSurface(NativeSurface surface) {
+        AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration();
+        AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice();
+        if( aDevice instanceof EGLGraphicsDevice && aConfig instanceof EGLGraphicsConfiguration ) {
+            // already in native EGL format
+            if(DEBUG) {
+                System.err.println(getThreadName() + ": getEGLSurface - already in EGL format - use as-is: "+aConfig);
+            }
+            return surface;
+        }
+        // create EGL instance out of platform native types
+        final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true);
+        final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex());
+        final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
+        final EGLGraphicsConfiguration eglConfig;
+        if( aConfig instanceof EGLGraphicsConfiguration ) {
+            // Config is already in EGL type - reuse ..
+            final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities();
+            if( 0 == capsChosen.getEGLConfig() ) {
+                // 'refresh' the native EGLConfig handle
+                capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID()));
+                if( 0 == capsChosen.getEGLConfig() ) {
+                    throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig);
+                }
+            }
+            eglConfig  = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null);
+            if(DEBUG) {
+                System.err.println(getThreadName() + ": getEGLSurface - Reusing chosenCaps: "+eglConfig);
+            }
+        } else {
+            eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
+                    capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false);
+
+            if (null == eglConfig) {
+                throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen);
+            } else if(DEBUG) {
+                System.err.println(getThreadName() + ": getEGLSurface - Chosen eglConfig: "+eglConfig);
+            }
+        }
+        return new WrappedSurface(eglConfig, EGL.EGL_NO_SURFACE, surface.getWidth(), surface.getHeight(), new EGLUpstreamSurfaceHook(surface));
     }
+    static String getThreadName() { return Thread.currentThread().getName(); }
 
     @Override
     protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) {
@@ -390,22 +530,115 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
     }
 
     @Override
-    protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) {
-        final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq;
-        final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID());
-        WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser));
-        ns.surfaceSizeChanged(width, height);
-        return ns;
+    protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, 
+                                                    GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, 
+                                                    GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) {
+        final EGLGraphicsDevice device;
+        if(createNewDevice) {
+            final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq;
+            device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID());
+        } else {
+            device = (EGLGraphicsDevice) deviceReq;
+        }
+        final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+        final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
+        if(null == config) {
+            throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); 
+        }    
+        return new WrappedSurface(config, 0, width, height, lifecycleHook);
+    }
+    
+    @Override
+    public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, 
+                                                     GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+        final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq));        
+        return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook);
+    }
+    private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() {
+        @Override
+        public final void create(ProxySurface s) {
+            if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) {
+                final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice();
+                if(0 == eglDevice.getHandle()) {
+                    eglDevice.open();
+                    s.setImplBitfield(ProxySurface.OWN_DEVICE);
+                }
+                createPBufferSurfaceImpl(s, false);
+                if(DEBUG) {
+                    System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s);
+                }
+            }
+        }
+        @Override
+        public final void destroy(ProxySurface s) {
+            if( EGL.EGL_NO_SURFACE != s.getSurfaceHandle() ) {
+                final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) s.getGraphicsConfiguration();
+                final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice();
+                EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle());
+                s.setSurfaceHandle(EGL.EGL_NO_SURFACE);
+                if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) {
+                    eglDevice.close();
+                }
+                if(DEBUG) {
+                    System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s);
+                }
+            }
+        }
+        @Override
+        public final int getWidth(ProxySurface s) {
+            return s.initialWidth;
+        }
+        @Override
+        public final int getHeight(ProxySurface s) {
+            return s.initialHeight;
+        }
+        @Override
+        public String toString() {
+            return "EGLSurfaceLifecycleHook[]";
+        }
+        
+    };
+    
+    /**
+     * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface. 
+     *           It will also hold the resulting pbuffer surface handle. 
+     * @param useTexture
+     * @return the passed {@link MutableSurface} which now has the EGL pbuffer surface set as it's handle
+     */
+    protected static MutableSurface createPBufferSurfaceImpl(MutableSurface ms, boolean useTexture) {
+        final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) ms.getGraphicsConfiguration();
+        final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice();
+        final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+        final int texFormat;
+
+        if(useTexture) {
+            texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ;
+        } else {
+            texFormat = EGL.EGL_NO_TEXTURE;
+        }
+
+        if (DEBUG) {
+          System.out.println("Pbuffer config: " + config);
+        }
+
+        final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(ms.getWidth(), ms.getHeight(), texFormat);
+        final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs, 0);
+        if (EGL.EGL_NO_SURFACE==surf) {
+            throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+ms.getWidth()+"x"+ms.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+        } else if(DEBUG) {
+            System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf));
+        }
+        ms.setSurfaceHandle(surf);
+        return ms;
     }
 
     @Override
-    protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
-        // FIXME device/windowHandle -> screen ?!
-        EGLGraphicsDevice device = (EGLGraphicsDevice) adevice;
-        DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
-        EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
-        WrappedSurface ns = new WrappedSurface(cfg, windowHandle);
-        return ns;
+    protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+        final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq;
+        final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID());
+        final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
+        final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
+        return new WrappedSurface(cfg, windowHandle, 0, 0, upstream);
     }
 
     @Override
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
index 56e7a4d22..214b36493 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
@@ -151,7 +151,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
     public static EGLGLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config,
                                                            boolean relaxed, boolean onscreen, boolean usePBuffer, boolean forceTransparentFlag) {
         List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>();
-        final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
+        final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
         if( EGLConfig2Capabilities(bucket, glp, display, config, winattrmask, forceTransparentFlag) ) {
             return (EGLGLCapabilities) bucket.get(0);
         } else if ( relaxed && EGLConfig2Capabilities(bucket, glp, display, config, GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag) ) {
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
index 809e2b688..6be9cb547 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
@@ -38,7 +38,6 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.AbstractGraphicsScreen;
 import javax.media.nativewindow.CapabilitiesChooser;
 import javax.media.nativewindow.CapabilitiesImmutable;
-import javax.media.nativewindow.DefaultGraphicsScreen;
 import javax.media.nativewindow.GraphicsConfigurationFactory;
 import javax.media.nativewindow.VisualIDHolder;
 import javax.media.nativewindow.VisualIDHolder.VIDType;
@@ -47,6 +46,7 @@ import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.GLCapabilitiesChooser;
 import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
 import javax.media.opengl.GLException;
 import javax.media.opengl.GLProfile;
 import javax.media.opengl.GLDrawableFactory;
@@ -180,6 +180,9 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
         }
         EGLGraphicsDevice eglDevice = sharedResource.getDevice();
         long eglDisplay = eglDevice.getHandle();
+        if(0 == eglDisplay) {
+            throw new GLException("null eglDisplay");
+        }
 
         List<GLCapabilitiesImmutable> availableCaps = null;
         IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
@@ -236,11 +239,9 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
             ownEGLDisplay = true;
         }
 
-        EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory();
-        capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(absDevice) );
-
-        GLProfile glp = capsChosen.getGLProfile();
-        GLCapabilities fixedCaps;
+        final GLProfile glp = capsChosen.getGLProfile();
+        final EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory();
+        capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(absDevice, glp), factory.canCreateGLPbuffer(absDevice) );
 
         EGLGraphicsConfiguration res = eglChooseConfig(eglDevice.getHandle(), capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag);
         if(null==res) {
@@ -251,13 +252,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
             // Last try .. add a fixed embedded profile [ATI, Nokia, Intel, ..]
             //
             // rgb888 - d16, s4
-            fixedCaps = new GLCapabilities(glp);
+            final GLCapabilities fixedCaps = new GLCapabilities(glp);
             fixedCaps.setRedBits(8);
             fixedCaps.setGreenBits(8);
             fixedCaps.setBlueBits(8);
             fixedCaps.setDepthBits(16);
             fixedCaps.setSampleBuffers(true);
             fixedCaps.setNumSamples(4);
+            if( !capsChosen.isOnscreen() ) {
+                fixedCaps.setOnscreen(false);
+                fixedCaps.setPBuffer(capsChosen.isPBuffer());
+                fixedCaps.setFBO(capsChosen.isFBO());
+            }            
             if(DEBUG) {
                 System.err.println("trying fixed caps (1): "+fixedCaps);
             }
@@ -266,11 +272,16 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
         if(null==res) {
             //
             // rgb565 - d16, s0
-            fixedCaps = new GLCapabilities(glp);
+            final GLCapabilities fixedCaps = new GLCapabilities(glp);
             fixedCaps.setRedBits(5);
             fixedCaps.setGreenBits(6);
             fixedCaps.setBlueBits(5);
             fixedCaps.setDepthBits(16);
+            if( !capsChosen.isOnscreen() ) {
+                fixedCaps.setOnscreen(false);
+                fixedCaps.setPBuffer(capsChosen.isPBuffer());
+                fixedCaps.setFBO(capsChosen.isFBO());
+            }            
             if(DEBUG) {
                 System.err.println("trying fixed caps (2): "+fixedCaps);
             }
@@ -279,13 +290,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
         if(null==res) {
             //
             // rgb565 - d16, s4
-            fixedCaps = new GLCapabilities(glp);
+            final GLCapabilities fixedCaps = new GLCapabilities(glp);
             fixedCaps.setRedBits(5);
             fixedCaps.setGreenBits(6);
             fixedCaps.setBlueBits(5);
             fixedCaps.setDepthBits(16);
             fixedCaps.setSampleBuffers(true);
             fixedCaps.setNumSamples(4);
+            if( !capsChosen.isOnscreen() ) {
+                fixedCaps.setOnscreen(false);
+                fixedCaps.setPBuffer(capsChosen.isPBuffer());
+                fixedCaps.setFBO(capsChosen.isFBO());
+            }            
             if(DEBUG) {
                 System.err.println("trying fixed caps (3): "+fixedCaps);
             }
@@ -309,7 +325,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
         final GLProfile glp = capsChosen.getGLProfile();
         final boolean onscreen = capsChosen.isOnscreen();
         final boolean usePBuffer = capsChosen.isPBuffer();
-        final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
+        final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, false);
         List<GLCapabilitiesImmutable> availableCaps = null;
         int recommendedIndex = -1;
         long recommendedEGLConfig = -1;
@@ -322,8 +338,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
             throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: Get maxConfigs (eglGetConfigs) no configs");
         }
         if (DEBUG) {
-            System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig maxConfigs: "+numConfigs.get(0));
-            System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglDisplay "+toHexString(eglDisplay)+", "+capsChosen+", nativeVisualID "+toHexString(nativeVisualID));
+            System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig eglDisplay "+toHexString(eglDisplay)+", nativeVisualID "+toHexString(nativeVisualID)+", onscreen "+onscreen+", usePBuffer "+usePBuffer+", "+capsChosen+", numConfigs "+numConfigs.get(0));
         }
 
         final IntBuffer attrs = Buffers.newDirectIntBuffer(EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen));
@@ -362,7 +377,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
                 throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: #2 Get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
             }
             if (numConfigs.get(0) > 0) {
-                availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);
+                availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);                
             }
         }
 
@@ -370,6 +385,8 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
             if(DEBUG) {
                 // FIXME: this happens on a ATI PC Emulation ..
                 System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #2 Graphics configuration 1st choice and 2nd choice failed - no configs");
+                availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag);
+                printCaps("AllCaps", availableCaps, System.err);
             }
             return null;
         }
@@ -428,27 +445,5 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
             out.println(prefix+"["+i+"] "+caps.get(i));
         }
     }
-
-    static EGLGraphicsConfiguration createOffscreenGraphicsConfiguration(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser) {
-        if(capsChosen.isOnscreen()) {
-            throw new GLException("Error: Onscreen set: "+capsChosen);
-        }
-
-        if(capsChosen.getDoubleBuffered()) {
-            // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN
-            GLCapabilities caps2 = (GLCapabilities) capsChosen.cloneMutable();
-            caps2.setDoubleBuffered(false);
-            capsChosen = caps2;
-        }
-
-        DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
-        EGLGraphicsConfiguration eglConfig = chooseGraphicsConfigurationStatic(capsChosen, capsReq, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
-        if (null == eglConfig) {
-            throw new GLException("Couldn't create EGLGraphicsConfiguration from "+screen);
-        } else if(DEBUG) {
-            System.err.println("Chosen eglConfig: "+eglConfig);
-        }
-        return eglConfig;
-    }
 }
 
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
index 3768f1588..d54057775 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
@@ -54,8 +54,8 @@ public class EGLOnscreenDrawable extends EGLDrawable {
     }
 
     @Override
-    protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) {
-        return EGL.eglCreateWindowSurface(eglDpy, eglNativeCfg, surfaceHandle, null);
+    protected long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle) {
+        return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), config.getNativeConfig(), nativeSurfaceHandle, null);
     }
 }
 
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
index b2217c095..4a36625bd 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
@@ -40,15 +40,11 @@
 
 package jogamp.opengl.egl;
 
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
 import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
-import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.nativewindow.MutableSurface;
 import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
 
 public class EGLPbufferDrawable extends EGLDrawable {
-    private int texFormat;
     protected static final boolean useTexture = false; // No yet ..
 
     protected EGLPbufferDrawable(EGLDrawableFactory factory, NativeSurface target) {
@@ -56,30 +52,12 @@ public class EGLPbufferDrawable extends EGLDrawable {
     }
 
     @Override
-    protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) {
-        final AbstractGraphicsConfiguration config = getNativeSurface().getGraphicsConfiguration();
-        final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
-
-        if(useTexture) {
-            texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ;
-        } else {
-            texFormat = EGL.EGL_NO_TEXTURE;
-        }
-
-        if (DEBUG) {
-          System.out.println("Pbuffer config: " + config);
-        }
-
-        NativeSurface nw = getNativeSurface();
-        int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(nw.getWidth(), nw.getHeight(), texFormat);
-        long surf = EGL.eglCreatePbufferSurface(eglDpy, eglNativeCfg, attrs, 0);
-        if (EGL.EGL_NO_SURFACE==surf) {
-            throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+nw.getWidth()+"x"+nw.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError()));
-        } else if(DEBUG) {
-            System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf));
+    protected long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle) {
+        final MutableSurface ms = (MutableSurface)getNativeSurface();
+        if(config != ms.getGraphicsConfiguration()) {
+            throw new InternalError("Not same: "+config.hashCode()+", "+ms.getGraphicsConfiguration()+": "+config+", "+ms.getGraphicsConfiguration());
         }
-        ((SurfaceChangeable)nw).setSurfaceHandle(surf);
-        return surf;
+        return EGLDrawableFactory.createPBufferSurfaceImpl(ms, useTexture).getSurfaceHandle();
     }
 
     @Override
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
new file mode 100644
index 000000000..42c6e100e
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
@@ -0,0 +1,56 @@
+package jogamp.opengl.egl;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GLException;
+
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+
+public class EGLUpstreamSurfaceHook implements ProxySurface.UpstreamSurfaceHook {
+    private final NativeSurface upstreamSurface;
+    
+    public EGLUpstreamSurfaceHook(NativeSurface upstream) {
+        upstreamSurface = upstream;
+    }
+    
+    public final NativeSurface getUpstreamSurface() { return upstreamSurface; }
+    
+    @Override
+    public final void create(ProxySurface surface) {
+        if(upstreamSurface instanceof ProxySurface) {
+            ((ProxySurface)upstreamSurface).createNotify();
+            if(NativeSurface.LOCK_SURFACE_NOT_READY >= upstreamSurface.lockSurface()) {
+                throw new GLException("Could not lock: "+upstreamSurface);
+            }
+        }
+        final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
+        eglDevice.open();
+    }
+
+    @Override
+    public final void destroy(ProxySurface surface) {
+        final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
+        eglDevice.close();
+        if(upstreamSurface instanceof ProxySurface) {
+            upstreamSurface.unlockSurface();
+            ((ProxySurface)upstreamSurface).destroyNotify();
+        }
+    }
+
+    @Override
+    public final int getWidth(ProxySurface s) {
+        return upstreamSurface.getWidth();
+    }
+
+    @Override
+    public final int getHeight(ProxySurface s) {
+        return upstreamSurface.getHeight();
+    }
+    
+    @Override
+    public String toString() {
+        final String us_s = null != upstreamSurface ? ( upstreamSurface.getClass().getName() + ": " + upstreamSurface ) : "nil"; 
+        return "EGLUpstreamSurfaceHook[upstream: "+us_s+"]";
+    }
+
+}
-- 
cgit v1.2.3