From 4dd44b985fe0541be3a3bcd9045d201ed3ca2cc5 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Sat, 15 Sep 2012 16:54:52 +0200
Subject: Seamless Integration of an FBObject based GLFBODrawable as
 GLOffscreenAutoDrawable.FBO and as an OffscreenLayerSurface's drawable (OSX)
 - Fix Bugs 569 and 599

Summary:
=========
The new FBObject based GLFBODrawable implementation allows the seamless utilization of
FBO offscreen rendering in single buffer, double buffer and MSAA mode.

The GLFBODrawable uses a parent drawable based on a
dummy surface to allow a GLOffscreenAutoDrawable.FBO creation
or a mutable surface supporting an existing offscreen layer surface (OSX CALayer).

Offscreen GLDrawable's and GLOffscreenAutoDrawable's can be selected via the
GLCapabilities. If simply !onscreen is selected in the caps instance w/o enabling FBO, PBuffer or Bitmap,
the factory will automatically choose regarding availability:
   FBO > PBuffer > Bitmap

Double buffering is supported in MSAA more (intrinsic) and explicit in non MSAA.
It is preferred when delivering resources (texture id's or framebuffer names)
to a shared GLContext.
This is demonstrated in (emulates our OSX CALayer implementation):
  TestFBOOffThreadSharedContextMix2DemosES2NEWT,
  TestFBOOnThreadSharedContext1DemoES2NEWT
and with the OSX JAWT OffscreenLayerSurface itself. FBO is the preferred choice.

+++

Offscreen drawables can be resized while maintaining a bound GLContext (e.g. w/ GLAutoDrawable).
Previously both, drawable and context, needed to be destroyed and recreated at offscreen resize.
Common implementation in GLDrawableHelper is used in the implementations
(NEWT's GLWindow, AWT GLCanvas, SWT GLCanvas).

+++

Tested:
=======

Manually run all unit tests on:
  - Linux x86_64 NVidia/AMD/Mesa3d(ES)
  - OSX x86_64 NVidia
  - Windows x86_64 NVidia
  - Android arm Mali-400/Tegra-2

No regressions.

Disclaimer:
===========
This feature is committed almost in one patch.

Both previous commits were introducing / fixing the capabilities behavior:
 90d45928186f2be99999461cfe45f76a783cc961
 9036376b7806a5fc61590bf49404eb71830de92f

I have to appologize for the huge size and impact (files and platforms) of this commit
however, I could not find a better way to inject this feature in one sane piece.

NativeWindow Details:
=====================

Complete decoupling of platform impl. detail of surfaces
implementing ProxySurface. Used to generalize dummy surfaces and EGL surfaces
on top of a native platform surface.
  - ProxySurface.UpstreamSurfaceHook -> UpstreamSurfaceHook
  - abstract class ProxySurface -> interface ProxySurface + ProxySurfaceImpl
  - Misc. implementations

JOGL Details:
=====================

FBOObject: API Change / Simplification & Usability
  - Removed reference counter to remove complexity, allow user to choose.
  - Add 'dispose' flag for detachColorbuffer(..), allowing to keep attachment alive
  - Fix equals operation of Attachment
  - Check pre-exising GL errors
  - Interface Colobuffer gets lifecycle methods
  - Add static factory methods to create Attachments w/o FBObject instance
  - Reset:
    - Clip min size to 1
    - Keep alive samplingSink, i.e. don't issue resetMSAATexture2DSink(..).
      It gets called at syncFramebuffer()/use(..) later on before actual usage.
      This allows the consumer to utilize the GL_FRONT buffer until (e.g.) swap.
  - misc bugfixes

GLOffscreenAutoDrawable: API Change
  - Reloc and interfacing
  - class com.jogamp.opengl.OffscreenAutoDrawable -> javax.media.opengl.*
    interfaces GLOffscreenAutoDrawable extends GLAutoDrawable
               GLOffscreenAutoDrawable.FBO extends GLOffscreenAutoDrawable, GLFBODrawable
  - Added general implementation and FBO specialization
  - Replacing GLPBuffer (deprecated) .. usable for any offscreen GLDrawable via factory

GLAutoDrawable:
  - Add 'GLDrawable getDelegatedDrawable()'
  - Refine documentation of setContext(..), remove disclaimer and fixme tags

GLDrawableFactory:
  - Refine API doc and it's selection mechanism for offscreen.
  - Add createOffscreenDrawable(..)
  - Add createOffscreenAutoDrawable(..)
  - Add canCreateFBO(..)
  - Mark createGLPbuffer(..) deprectated

Mark GLPBuffer deprecated

New: GLFBODrawable extends GLDrawable

GLCanvas (AWT and SWT): Add offscreen resize support w/o GLContext recreation

GLAutoDrawableBase .. GLWindow:
  - Add offscreen resize support w/o GLContext recreation
  - Remove double swapBuffer call
  -

GLBase/GLContext:
  - Add:
    - boolean hasBasicFBOSupport()
    - boolean hasFullFBOSupport()
    - int getMaxRenderbufferSamples()
    - boolean isTextureFormatBGRA8888Available()

GLContext: Fix version detection and hasGLSL()
  - Version detection in setGLFunctionAvailability(..)
    - Query GL_VERSION ASAP and parse it and compare w/ given major/minor
    - Use parsed version if valid and lower than given _or_ given is invalid.
    - Use validated version for caching (procaddr, ..), version number, etc.

  - Fix hasGLSL()
    Since 'isGL2ES2()' is true if 'isGL2()'
    and the latter simply alows GL 1.*, we confine the result to a GL >= 2.0
    on desktops. FIXME: May consider GL 1.5 w/ extensions.
    -  return isGL2ES2();
    +      return isGLES2() ||
    +             isGL3() ||
    +             isGL2() && ctxMajorVersion>1 ;

GLDrawableImpl:
  - Add 'associateContext(GLContext, boolean)' allowing impl.
    to have a (weak) reference list of bound context.
    This is was pulled up from the OSX specific drawable impl.
  - swapBuffersImpl() -> swapBuffersImpl(boolean doubleBuffered)
    and call it regardless of single buffering.
    This is required to propagate this event to impl. properly,
    i.e. FBODrawable requires a swap notification.
  - Clarify 'contextMadeCurrent(..)' protocol

GLDrawableHelper:
  - Add resize and recreate offscreen drawable util method
  - Simplify required init/reshape calls for GLEventListener
  -

GLGraphicsConfigurationUtil:
  - fixWinAttribBitsAndHwAccel: Reflect sharede context hw-accel bits
  - OSX has no offscreen bitmap, use pbuffer
  - use proper offscreen auto selection if offscreen and no modes are set

EGL Context/Drawable/DrawableFactory: Abstract native platform code out of base classes
  - Use EGLWrappedSurface w/ UpstreamSurfaceHook to handle upstream (X11, WGL, ..)
    lifecycle - in case the EGL resource is hooked up on it.

Invisible dummy surfaces: All platforms
  - size is now reduced to 64x64 and decoupled of actual generic mutable size
  - fix device  lifecycle, no more leaks

+++

OSX
====

Enable support for GLFBODrawableImpl in offscreen CALayer mode
  - NSOpenGLImpl: hooks to calayer native code
  - calayer code:
    - allows pbuffer and texures (FBO)
    - decouple size and draw calls avoiding flickering
    - enable auto resize of calayer tree

MacOSXCGLContext:
  - NSOpenGLImpl:
  - Fix false pbuffer 'usage', validate the pointer
  - If !pbuffer, copy other window mode bits of caps
  -

MacOSXCGLGraphicsConfiguration:
  - Only assume pbuffer if !onscreen
  - Remove reference of native pixelformat pointer

Native code:
  - use 'respondsToSelector:' query before calling 'new' methods
    avoiding an error message where unsuported (prev. OSX versions)
  - if monitor refresh-rate is queried 0, set to default 60hz
  - add missing NSAutoreleasePool decoration

+++

Android / NEWT:
===============

Issue setVisible(..) w/o wait, i.e. queue on EDT,
@Android surfaceChanged() callback. Otherwise we could deadlock:
   setVisible(..) -> EDT -> setVisibleImpl(..) -> 'GL-display'.
the latter may may cause havoc while Android-EDT is blocked [until it's return].
---
 .../classes/javax/media/opengl/GLAutoDrawable.java |  38 +++--
 .../javax/media/opengl/GLAutoDrawableDelegate.java | 144 -----------------
 src/jogl/classes/javax/media/opengl/GLBase.java    |  38 +++++
 src/jogl/classes/javax/media/opengl/GLContext.java |  97 ++++++++++--
 .../javax/media/opengl/GLDrawableFactory.java      | 128 ++++++++++++---
 .../classes/javax/media/opengl/GLFBODrawable.java  | 173 +++++++++++++++++++++
 .../media/opengl/GLOffscreenAutoDrawable.java      |  63 ++++++++
 src/jogl/classes/javax/media/opengl/GLPbuffer.java |   6 +-
 .../classes/javax/media/opengl/awt/GLCanvas.java   | 119 ++++++++------
 .../classes/javax/media/opengl/awt/GLJPanel.java   |  13 +-
 10 files changed, 570 insertions(+), 249 deletions(-)
 delete mode 100644 src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
 create mode 100644 src/jogl/classes/javax/media/opengl/GLFBODrawable.java
 create mode 100644 src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java

(limited to 'src/jogl/classes/javax/media')

diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
index 0b2c664fe..38f1746f9 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
@@ -114,6 +114,12 @@ public interface GLAutoDrawable extends GLDrawable {
     * where you drag the window to another monitor. */
   public static final boolean SCREEN_CHANGE_ACTION_ENABLED = Debug.getBooleanProperty("jogl.screenchange.action", true);
 
+  /**
+   * If the implementation uses delegation, return the delegated {@link GLDrawable} instance,
+   * otherwise return <code>this</code> instance.
+   */
+  public GLDrawable getDelegatedDrawable();
+  
   /**
    * Returns the context associated with this drawable. The returned
    * context will be synchronized.
@@ -124,23 +130,31 @@ public interface GLAutoDrawable extends GLDrawable {
   /**
    * Associate a new context to this drawable and also propagates the context/drawable switch by 
    * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
-   * <code>drawable</code> might be an inner GLDrawable instance if using such a delegation pattern,
-   * or this GLAutoDrawable itself. 
-   * <p>
-   * If the old context's drawable was an {@link GLAutoDrawable}, it's reference to the given drawable
-   * is being cleared by calling 
-   * {@link GLAutoDrawable#setContext(GLContext) ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null)}.
-   * </p>
+   * <code>drawable</code> might be an inner GLDrawable instance if using a delegation pattern,
+   * or this GLAutoDrawable instance.
    * <p>
    * If the old or new context was current on this thread, it is being released before switching the drawable.
    * The new context will be made current afterwards, if it was current before. 
-   * However the user shall take extra care that not other thread
-   * attempts to make this context current. Otherwise a race condition may happen.
+   * However the user shall take extra care that no other thread
+   * attempts to make this context current.
+   * </p>
+   * <p>
+   * Be aware that the old context is still bound to the drawable, 
+   * and that one context can only be bound to one drawable at one time!
    * </p>
    * <p>
-   * <b>Disclaimer</b>: Even though the API may allows this functionality in theory, your mileage may vary 
-   * switching the drawable of an already established GLContext, i.e. which is already made current once.
-   * FIXME: Validate functionality! 
+   * In case you do not intend to use the old context anymore, i.e. 
+   * not assigning it to another drawable, it shall be 
+   * destroyed before setting the new context, i.e.:
+   * <pre>
+            GLContext oldCtx = glad.getContext();
+            if(null != oldCtx) {
+                oldCtx.destroy();
+            }
+            glad.setContext(newCtx);            
+   * </pre> 
+   * This is required, since a context must have a valid drawable at all times
+   * and this API shall not restrict the user in any way. 
    * </p>
    * 
    * @param newCtx the new context
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
deleted file mode 100644
index 67e81270d..000000000
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
- * Copyright 2012 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- * 
- *    1. Redistributions of source code must retain the above copyright notice, this list of
- *       conditions and the following disclaimer.
- * 
- *    2. Redistributions in binary form must reproduce the above copyright notice, this list
- *       of conditions and the following disclaimer in the documentation and/or other materials
- *       provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
- 
-package javax.media.opengl;
-
-import javax.media.nativewindow.AbstractGraphicsDevice;
-
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
-
-import jogamp.opengl.Debug;
-import jogamp.opengl.GLAutoDrawableBase;
-import jogamp.opengl.GLContextImpl;
-import jogamp.opengl.GLDrawableImpl;
-
-
-/**
- * Fully functional {@link GLAutoDrawable} implementation
- * utilizing already created created {@link GLDrawable} and {@link GLContext} instances.
- * <p>
- * Since no native windowing system events are being processed, it is recommended
- * to handle at least:
- * <ul>
- *   <li>{@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint} using {@link #defaultWindowRepaintOp()}</li>
- *   <li>{@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize} using {@link #defaultWindowResizedOp()}</li>
- *   <li>{@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify}  using {@link #defaultWindowDestroyNotifyOp()}</li> 
- * </ul> 
- * </p>
- * <p> 
- * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}.
- * </p>
- */
-public class GLAutoDrawableDelegate extends GLAutoDrawableBase {
-    public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate");
-    
-    /**
-     * @param drawable a valid {@link GLDrawable}, may not be realized yet.
-     * @param context a valid {@link GLContext}, may not be made current (created) yet.
-     * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
-     * @param ownDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued,
-     *                  otherwise pass <code>false</code>. Closing the device is required in case
-     *                  the drawable is created w/ it's own new instance, e.g. offscreen drawables,
-     *                  and no further lifecycle handling is applied.
-     */
-    public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice) {
-        super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice);
-        this.upstreamWidget = null;
-    }
-    
-    //
-    // expose default methods
-    //
-    
-    public final void windowRepaintOp() {
-        super.defaultWindowRepaintOp();
-    }
-    
-    public final void windowResizedOp() {
-        super.defaultWindowResizedOp();
-    }
-    
-    public final void windowDestroyNotifyOp() {
-        super.defaultWindowDestroyNotifyOp();
-    }
-    
-    //
-    // Complete GLAutoDrawable
-    //
-    
-    private final RecursiveLock lock = LockFactory.createRecursiveLock();  // instance wide lock
-    private final Object upstreamWidget;
-    
-    @Override
-    protected final RecursiveLock getLock() { return lock; }
-    
-    @Override
-    public final Object getUpstreamWidget() {
-        return upstreamWidget;
-    }
-    
-    /**
-     * {@inheritDoc}
-     * <p>
-     * This implementation calls {@link #defaultDestroy()}.
-     * </p>
-     * <p>
-     * User still needs to destroy the upstream window, which details are hidden from this aspect.
-     * This can be performed by overriding {@link #destroyImplInLock()}. 
-     * </p>
-     */
-    @Override
-    public final void destroy() {
-        defaultDestroy();
-    }
-
-    @Override
-    public void display() {
-        defaultDisplay();
-    }
-    
-    //
-    // GLDrawable delegation
-    //
-    
-    @Override
-    public final GLDrawableFactory getFactory() {
-        return drawable.getFactory();
-    }
-    
-    @Override
-    public final void setRealized(boolean realized) {
-    }
-
-    @Override
-    public final void swapBuffers() throws GLException {
-         defaultSwapBuffers();
-    }
-        
-}
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index f5831a72d..9bcee819a 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -273,6 +273,42 @@ public interface GLBase {
     */
    public boolean isExtensionAvailable(String glExtensionName);
 
+   /** 
+    * Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>.
+    * <p>
+    * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+    * <code>GL_ARB_ES2_compatibility</code>, <code>GL_ARB_framebuffer_object</code>, <code>GL_EXT_framebuffer_object</code> or <code>GL_OES_framebuffer_object</code>.
+    * </p>
+    * <p>
+    * Basic FBO support may only include one color attachment and no multisampling,
+    * as well as limited internal formats for renderbuffer.
+    * </p>
+    * @see GLContext#hasBasicFBOSupport()
+    */
+   public boolean hasBasicFBOSupport();
+
+   /** 
+    * Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>.
+    * <p>
+    * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+    * <code>ARB_framebuffer_object</code>, or all of
+    * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>, 
+    * <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>.
+    * </p>
+    * <p>
+    * Full FBO support includes multiple color attachments and multisampling.
+    * </p>
+    * @see GLContext#hasFullFBOSupport()
+    */
+   public boolean hasFullFBOSupport();
+
+   /**
+    * Returns the maximum number of FBO RENDERBUFFER samples
+    * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. 
+    * @see GLContext#getMaxRenderbufferSamples()
+    */
+   public int getMaxRenderbufferSamples();
+
    /**
     * Returns true if the GL context supports non power of two (NPOT) textures,
     * otherwise false.
@@ -284,6 +320,8 @@ public interface GLBase {
     */
    public boolean isNPOTTextureAvailable();
 
+   public boolean isTextureFormatBGRA8888Available();
+   
    /** Provides a platform-independent way to specify the minimum swap
        interval for buffer swaps. An argument of 0 disables
        sync-to-vertical-refresh completely, while an argument of 1
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index c2f94b9af..a5e639c74 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -96,6 +96,9 @@ public abstract class GLContext {
    */
   public static final boolean PROFILE_ALIASING = !Debug.isPropertyDefined("jogl.debug.GLContext.NoProfileAliasing", true);
   
+  protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true);
+  protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true);
+  
   public static final boolean DEBUG = Debug.debug("GLContext");
   public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
 
@@ -127,9 +130,9 @@ public abstract class GLContext {
   /** <code>GL_ARB_ES2_compatibility</code> implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
   protected static final int CTX_IMPL_ES2_COMPAT = 1 <<  8;
 
-  /** Context supports basic FBO, details see {@link #hasFBO()}.
+  /** Context supports basic FBO, details see {@link #hasBasicFBOSupport()}.
    * Not a cache key.
-   * @see #hasFBO()
+   * @see #hasBasicFBOSupport()
    * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
    */
   protected static final int CTX_IMPL_FBO        = 1 <<  9;
@@ -178,11 +181,6 @@ public abstract class GLContext {
    * and made current afterwards. However the user shall take extra care that not other thread
    * attempts to make this context current. Otherwise a race condition may happen.
    * </p>
-   * <p>
-   * <b>Disclaimer</b>: Even though the API may allows this functionality in theory, your mileage may vary 
-   * switching the drawable of an already established GLContext, i.e. which is already made current once.
-   * FIXME: Validate functionality! 
-   * </p>
    * @param readWrite the read/write drawable for framebuffer operations.
    * @param setWriteOnly if <code>true</code> and if the current read-drawable differs 
    *        from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}), 
@@ -603,12 +601,23 @@ public abstract class GLContext {
 
   /** 
    * @return true if impl. is a hardware rasterizer, otherwise false.
+   * @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile)
    * @see GLProfile#isHardwareRasterizer() 
    */
   public final boolean isHardwareRasterizer() {
       return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
   }
   
+  /**
+   * @return true if context supports GLSL, i.e. is either {@link #isGLES2()}, {@link #isGL3()} or {@link #isGL2()} <i>and</i> major-version > 1.
+   * @see GLProfile#hasGLSL() 
+   */
+  public final boolean hasGLSL() {
+      return isGLES2() ||
+             isGL3() ||
+             isGL2() && ctxMajorVersion>1 ;
+  }
+
   /** 
    * Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>.
    * <p>
@@ -620,21 +629,54 @@ public abstract class GLContext {
    * as well as limited internal formats for renderbuffer.
    * </p>
    * @see #CTX_IMPL_FBO
-   * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL)
-   * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL)
    */
-  public final boolean hasFBO() {
+  public final boolean hasBasicFBOSupport() {
       return 0 != ( ctxOptions & CTX_IMPL_FBO ) ;
   }
 
+  /** 
+   * Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>.
+   * <p>
+   * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+   * <code>ARB_framebuffer_object</code>, or all of
+   * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>, 
+   * <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>.
+   * </p>
+   * <p>
+   * Full FBO support includes multiple color attachments and multisampling.
+   * </p>
+   */
+  public final boolean hasFullFBOSupport() {        
+      return !FORCE_MIN_FBO_SUPPORT && hasBasicFBOSupport() &&
+              ( isGL3() ||                                                         // GL >= 3.0                
+                isExtensionAvailable(GLExtensions.ARB_framebuffer_object) ||       // ARB_framebuffer_object
+                ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) &&     // All EXT_framebuffer_object*
+                  isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
+                  isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
+                  isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil)
+                )
+              ) ;               
+  }
+  
   /**
-   * @return true if context supports GLSL
-   * @see GLProfile#hasGLSL() 
+   * Returns the maximum number of FBO RENDERBUFFER samples
+   * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. 
    */
-  public final boolean hasGLSL() {
-      return isGL2ES2() ;
+  public final int getMaxRenderbufferSamples() {
+      if( hasFullFBOSupport() ) {
+          final GL gl = getGL();
+          final int[] val = new int[] { 0 } ;
+          gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
+          final int glerr = gl.glGetError();
+          if(GL.GL_NO_ERROR == glerr) {
+              return val[0];
+          } else if(DEBUG) {
+              System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
+          }
+      }
+      return 0;
   }
-
+  
   /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns <code>true</code>. */
   public boolean isNPOTTextureAvailable() {
       return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
@@ -1014,6 +1056,9 @@ public abstract class GLContext {
     validateProfileBits(profile, "profile");
     validateProfileBits(resCtp, "resCtp");
 
+    if(FORCE_NO_FBO_SUPPORT) {
+        resCtp &= ~CTX_IMPL_FBO ;
+    }
     if(DEBUG) {
         System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null));
         // Thread.dumpStack();
@@ -1197,17 +1242,35 @@ public abstract class GLContext {
    * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
    * </p> 
    * <p>
-   * FBO support is queried as described in {@link #hasFBO()}.
+   * FBO support is queried as described in {@link #hasBasicFBOSupport()}.
    * </p>
    *
    * @param device the device to request whether FBO is available for
    * @param glp {@link GLProfile} to check for FBO capabilities
-   * @see GLContext#hasFBO()
+   * @see GLContext#hasBasicFBOSupport()
    */
   public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) {
       return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) );
   }
   
+  /**
+   * @return <code>1</code> if using a hardware rasterizer, <code>0</code> if using a software rasterizer and <code>-1</code> if not determined yet. 
+   * @see GLContext#isHardwareRasterizer()
+   * @see GLProfile#isHardwareRasterizer() 
+   */
+  public static final int isHardwareRasterizer(AbstractGraphicsDevice device, GLProfile glp) {
+      final int r;
+      final int ctp = getAvailableContextProperties(device, glp);
+      if(0 == ctp) { 
+          r = -1;
+      } else if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
+          r = 1;
+      } else {
+          r = 0;
+      }
+      return r;
+  }
+  
   /**
    * @param device the device to request whether the profile is available for
    * @param reqMajor Key Value either 1, 2, 3 or 4
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index 9fd895c1f..b6e7b0576 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -48,13 +48,16 @@ import java.util.List;
 import com.jogamp.common.JogampRuntimeException;
 
 import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.opengl.GLAutoDrawableDelegate;
 
 import javax.media.nativewindow.AbstractGraphicsDevice;
 import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.CapabilitiesImmutable;
 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.UpstreamSurfaceHook;
 
 import jogamp.opengl.Debug;
 
@@ -373,44 +376,63 @@ public abstract class GLDrawableFactory {
   // Methods to create high-level objects
 
   /**
-   * Returns a GLDrawable according to it's chosen Capabilities,<br>
+   * Returns a GLDrawable according to it's chosen {@link GLCapabilitiesImmutable},<br>
    * which determines pixel format, on- and offscreen incl. PBuffer type.
    * <p>
-   * The native platform's chosen Capabilties are referenced within the target
-   * NativeSurface's AbstractGraphicsConfiguration.<p>
-   *
-   * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is true,<br>
-   * an onscreen GLDrawable will be realized.
+   * The chosen {@link GLCapabilitiesImmutable} are referenced within the target
+   * {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.<p>
+   * </p>
    * <p>
-   * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is false,<br>
-   * either a Pbuffer drawable is created if target's {@link javax.media.opengl.GLCapabilities#isPBuffer()} is true,<br>
-   * or a simple pixmap/bitmap drawable is created. The latter is unlikely to be hardware accelerated.<br>
+   * An onscreen GLDrawable is created if {@link CapabilitiesImmutable#isOnscreen() caps.isOnscreen()} is true.
+   * </p>
    * <p>
-   *
+   * A FBO drawable is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()}
+   * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true.
+   * </p>
+   * <p>
+   * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
+   * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+   * </p>
+   * <p>
+   * If not onscreen and neither FBO nor Pbuffer is available, 
+   * a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.
+   * </p>
+   * 
    * @throws IllegalArgumentException if the passed target is null
    * @throws GLException if any window system-specific errors caused
    *         the creation of the GLDrawable to fail.
    *
+   * @see #canCreateGLPbuffer(AbstractGraphicsDevice)
+   * @see GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile)
+   * @see javax.media.opengl.GLCapabilities#isOnscreen()
+   * @see javax.media.opengl.GLCapabilities#isFBO()
+   * @see javax.media.opengl.GLCapabilities#isPBuffer()
    * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
    */
   public abstract GLDrawable createGLDrawable(NativeSurface target)
     throws IllegalArgumentException, GLException;
-
+  
   /**
-   * Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
+   * Creates an {@link GLOffscreenAutoDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
    * <p>
-   * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below.
+   * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is realized and it's {@link GLContext} assigned but not yet made current.
    * </p>
    * <p>
-   * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()}
+   * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
+   * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} <code> == true</code>,
+   * it is auto-configured. The latter will set offscreen and also FBO <i>or</i> Pbuffer, whichever is available in that order.
+   * </p>
+   * <p>
+   * A FBO based auto drawable, {@link GLOffscreenAutoDrawable.FBO}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()}
    * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true.
    * </p>
    * <p>
-   * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()}
-   * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+   * A Pbuffer based auto drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
+   * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
    * </p>
    * <p>
-   * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.
+   * If neither FBO nor Pbuffer is available, 
+   * a simple pixmap/bitmap auto drawable is created, which is unlikely to be hardware accelerated.
    * </p>
    *
    * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
@@ -418,17 +440,55 @@ public abstract class GLDrawableFactory {
    * @param chooser the custom chooser, may be null for default
    * @param width the requested offscreen width
    * @param height the requested offscreen height
+   * @return the created and initialized offscreen {@link GLOffscreenAutoDrawable} instance
    *
-   * @return the created offscreen GLDrawable
+   * @throws GLException if any window system-specific errors caused
+   *         the creation of the Offscreen to fail.
+   *         
+   * @see #createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int)
+   */
+  public abstract GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice device,
+                                                                      GLCapabilitiesImmutable caps,
+                                                                      GLCapabilitiesChooser chooser,
+                                                                      int width, int height,
+                                                                      GLContext shareWith) throws GLException;
+  /**
+   * Creates a offscreen {@link GLDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
+   * <p>
+   * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
+   * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} <code> == true</code>,
+   * it is auto-configured. The latter will set offscreen and also FBO <i>or</i> Pbuffer, whichever is available in that order.
+   * </p>
+   * <p>
+   * A resizeable FBO drawable, {@link GLFBODrawable.Resizeable}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()}
+   * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true.
+   * </p>
+   * <p>
+   * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()}
+   * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
+   * </p>
+   * <p>
+   * If neither FBO nor Pbuffer is available, 
+   * a simple pixmap/bitmap drawable is created, which is unlikely to be hardware accelerated.
+   * </p>
+   *
+   * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be <code>null</code> for the platform's default device.
+   * @param caps the requested GLCapabilties
+   * @param chooser the custom chooser, may be null for default
+   * @param width the requested offscreen width
+   * @param height the requested offscreen height
+   *
+   * @return the created offscreen {@link GLDrawable}
    *
    * @throws GLException if any window system-specific errors caused
    *         the creation of the Offscreen to fail.
+   *         
+   * @see #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)
    */
   public abstract GLDrawable createOffscreenDrawable(AbstractGraphicsDevice device,
-                                                     GLCapabilitiesImmutable capabilities,
+                                                     GLCapabilitiesImmutable caps,
                                                      GLCapabilitiesChooser chooser,
-                                                     int width, int height)
-    throws GLException;
+                                                     int width, int height) throws GLException;
 
   /**
    * Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance. 
@@ -458,6 +518,21 @@ public abstract class GLDrawableFactory {
                                                   long windowHandle, 
                                                   GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
 
+  /**
+   * Returns true if it is possible to create an <i>framebuffer object</i> (FBO).
+   * <p>
+   * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
+   * </p> 
+   * <p>
+   * FBO support is queried as described in {@link GLContext#hasBasicFBOSupport()}.
+   * </p>
+   *
+   * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device.
+   * @param glp {@link GLProfile} to check for FBO capabilities
+   * @see GLContext#hasBasicFBOSupport()
+   */
+  public abstract boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp);
+
   /**
    * Returns true if it is possible to create a GLPbuffer. Some older
    * graphics cards do not have this capability.
@@ -467,7 +542,10 @@ public abstract class GLDrawableFactory {
   public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
 
   /**
-   * Creates a GLPbuffer with the given capabilites and dimensions. <P>
+   * Creates a GLPbuffer {@link GLAutoDrawable} with the given capabilites and dimensions.
+   * <p>
+   * The GLPbuffer drawable is realized and initialized eagerly.
+   * </p>
    *
    * See the note in the overview documentation on
    * <a href="../../../overview-summary.html#SHARING">context sharing</a>.
@@ -479,10 +557,12 @@ public abstract class GLDrawableFactory {
    * @param initialHeight initial height of pbuffer
    * @param shareWith a shared GLContext this GLPbuffer shall use
    *
-   * @return the new {@link GLPbuffer} specific {@link GLAutoDrawable}
+   * @return the created and initialized {@link GLPbuffer} instance
    *
    * @throws GLException if any window system-specific errors caused
    *         the creation of the GLPbuffer to fail.
+   *         
+   * @deprecated {@link GLPbuffer} is deprecated, use {@link #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)}
    */
   public abstract GLPbuffer createGLPbuffer(AbstractGraphicsDevice device,
                                             GLCapabilitiesImmutable capabilities,
diff --git a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
new file mode 100644
index 000000000..45fd3b686
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java
@@ -0,0 +1,173 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.opengl;
+
+import javax.media.nativewindow.NativeWindowException;
+
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.TextureAttachment;
+
+/** 
+ * Platform-independent {@link GLDrawable} specialization,
+ * exposing {@link FBObject} functionality.
+ *
+ * <p>
+ * A {@link GLFBODrawable} is uninitialized until a {@link GLContext} is bound 
+ * and made current the first time.
+ * </p>
+ * 
+ * <p>
+ * MSAA is used if {@link GLCapabilitiesImmutable#getNumSamples() requested}.
+ * </p>
+ * <p>
+ * Double buffering is used if {@link GLCapabilitiesImmutable#getDoubleBuffered() requested}.
+ * </p>
+ * <p>
+ * In MSAA mode, it always uses the implicit 2nd {@link FBObject framebuffer} {@link FBObject#getSamplingSinkFBO() sink}. 
+ * Hence double buffering is always the case w/ MSAA.
+ * </p>
+ * <p>
+ * In non MSAA a second explicit {@link FBObject framebuffer} is being used.
+ * This method allows compliance w/ the spec, i.e. read and draw framebuffer selection
+ * and double buffer usage for e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}.
+ * This method also allows usage of both textures seperately.
+ * </p>
+ * <p>
+ * It would be possible to implement double buffering simply using 
+ * {@link FBObject.TextureAttachment texture attachment}s with one {@link FBObject framebuffer}.
+ * This would require mode selection and hence complicate the API. Besides, it would
+ * not support differentiation of read and write framebuffer and hence not be spec compliant.
+ * </p>
+ * <p>
+ * Actual swapping of the {@link FBObject.TextureAttachment texture}s or {@link FBObject framebuffer}
+ * is performed either in the {@link #contextMadeCurrent(boolean) context current hook}
+ * or when {@link #swapBuffersImpl(boolean) swapping buffers}, whatever comes first.<br/>
+ * </p>
+ */ 
+public interface GLFBODrawable extends GLDrawable {
+    // public enum DoubleBufferMode { NONE, TEXTURE, FBO }; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
+    
+    /**
+     * @return <code>true</code> if initialized, i.e. a {@link GLContext} is bound and made current once, otherwise <code>false</code>.
+     */
+    public boolean isInitialized();
+    
+    /**
+     * Notify this instance about upstream size change
+     * to reconfigure the {@link FBObject}.
+     * @param gl GL context object bound to this drawable, will be made current during operation. 
+     *           A prev. current context will be make current after operation. 
+     * @throws GLException if resize operation failed
+     */
+    void resetSize(GL gl) throws GLException;
+    
+    /**
+     * @return the used texture unit
+     */
+    int getTextureUnit();
+    
+    /**
+     * 
+     * @param unit the texture unit to be used
+     */
+    void setTextureUnit(int unit);
+    
+    /**
+     * Set a new sample size
+     * @param gl GL context object bound to this drawable, will be made current during operation. 
+     *           A prev. current context will be make current after operation. 
+     * @param newSamples new sample size
+     * @throws GLException if resetting the FBO failed
+     */
+    void setNumSamples(GL gl, int newSamples) throws GLException;
+    
+    /**
+     * @return the number of sample buffers if using MSAA, otherwise 0
+     */
+    int getNumSamples();
+    
+    /**
+     * @return the used {@link DoubleBufferMode} 
+     */
+    // DoubleBufferMode getDoubleBufferMode(); // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
+    
+    /**
+     * Sets the {@link DoubleBufferMode}. Must be called before {@link #isInitialized() initialization},
+     * otherwise an exception is thrown.
+     * <p>
+     * This call has no effect is MSAA is selected, since MSAA always forces the mode to {@link DoubleBufferMode#FBO FBO}.
+     * Also setting the mode to {@link DoubleBufferMode#NONE NONE} where double buffering is {@link GLCapabilitiesImmutable#getDoubleBuffered() requested}
+     * or setting a double buffering mode w/o {@link GLCapabilitiesImmutable#getDoubleBuffered() request} will be ignored.
+     * </p>
+     * <p>
+     * Since {@link DoubleBufferMode#TEXTURE TEXTURE} mode is currently not implemented, this method has no effect.
+     * </p>
+     * @throws GLException if already initialized, see {@link #isInitialized()}.
+     */
+    // void setDoubleBufferMode(DoubleBufferMode mode) throws GLException; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
+    
+    /**
+     * If MSAA is being used and {@link GL#GL_FRONT} is requested,
+     * the internal {@link FBObject} {@link FBObject#getSamplingSinkFBO() sample sink} is being returned. 
+     * 
+     * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names
+     * @return the named {@link FBObject}
+     * @throws IllegalArgumentException if an illegal buffer name is being used
+     */
+    FBObject getFBObject(int bufferName) throws IllegalArgumentException;
+
+    /**
+     * Returns the named texture buffer.
+     * <p>
+     * If MSAA is being used, only the {@link GL#GL_FRONT} buffer is accessible 
+     * and an exception is being thrown if {@link GL#GL_BACK} is being requested.
+     * </p>
+     * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names
+     * @return the named {@link TextureAttachment}
+     * @throws IllegalArgumentException if using MSAA and {@link GL#GL_BACK} is requested or an illegal buffer name is being used
+     */
+    FBObject.TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException;
+
+    /** Resizeable {@link GLFBODrawable} specialization */     
+    public interface Resizeable extends GLFBODrawable {
+        /**
+         * Resize this drawable.
+         * <p>
+         * This drawable is being locked during operation.
+         * </p>
+         * @param context the {@link GLContext} bound to this drawable, will be made current during operation 
+         *                A prev. current context will be make current after operation. 
+         * @param newWidth
+         * @param newHeight
+         * @throws NativeWindowException in case the surface could no be locked
+         * @throws GLException in case an error during the resize operation occurred
+         */
+        void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException;                
+    }
+}
diff --git a/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java
new file mode 100644
index 000000000..6fe76a3f4
--- /dev/null
+++ b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.opengl;
+
+import javax.media.nativewindow.NativeWindowException;
+
+import com.jogamp.opengl.FBObject;
+
+/** 
+ * Platform-independent {@link GLAutoDrawable} specialization,
+ * exposing offscreen functionality.
+ * <p>
+ * This class distinguishes itself from {@link GLAutoDrawable}
+ * with it's {@link #setSize(int, int)} functionality.
+ * </p>
+ */
+public interface GLOffscreenAutoDrawable extends GLAutoDrawable {
+    
+    /**
+     * Resize this auto drawable.
+     * @param newWidth
+     * @param newHeight
+     * @throws NativeWindowException in case the surface could no be locked
+     * @throws GLException in case of an error during the resize operation
+     */
+    void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException;
+
+    /**
+     * Set the upstream UI toolkit object.
+     * @see #getUpstreamWidget()
+     */
+    void setUpstreamWidget(Object newUpstreamWidget);
+    
+    /** {@link FBObject} based {@link GLOffscreenAutoDrawable} specialization */ 
+    public interface FBO extends GLOffscreenAutoDrawable, GLFBODrawable {      
+    }    
+}
diff --git a/src/jogl/classes/javax/media/opengl/GLPbuffer.java b/src/jogl/classes/javax/media/opengl/GLPbuffer.java
index 273a992cf..de7731a3b 100644
--- a/src/jogl/classes/javax/media/opengl/GLPbuffer.java
+++ b/src/jogl/classes/javax/media/opengl/GLPbuffer.java
@@ -45,7 +45,11 @@ package javax.media.opengl;
     contains experimental methods for accessing the pbuffer's contents
     as a texture map and enabling rendering to floating-point frame
     buffers. These methods are not guaranteed to be supported on all
-    platforms and may be deprecated in a future release. */
+    platforms and may be deprecated in a future release.
+    
+    @deprecated Use {@link GLOffscreenAutoDrawable} w/ {@link GLCapabilities#setFBO(boolean)} 
+                via {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) GLDrawableFactory.createOffscreenAutoDrawable(..)}.
+  */
 
 public interface GLPbuffer extends GLAutoDrawable {
   /** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 033591fe3..329cf9e3f 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -98,6 +98,7 @@ import jogamp.common.awt.AWTEDTExecutor;
 import jogamp.opengl.Debug;
 import jogamp.opengl.GLContextImpl;
 import jogamp.opengl.GLDrawableHelper;
+import jogamp.opengl.GLDrawableImpl;
 
 // FIXME: Subclasses need to call resetGLFunctionAvailability() on their
 // context whenever the displayChanged() function is called on our
@@ -109,6 +110,16 @@ import jogamp.opengl.GLDrawableHelper;
     interfaces when adding a heavyweight doesn't work either because
     of Z-ordering or LayoutManager problems.
  *
+ * <h5><A NAME="java2dgl">Offscreen Layer Remarks</A></h5>
+ * 
+ * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
+ * maybe called to use an offscreen drawable (FBO or PBuffer) allowing 
+ * the underlying JAWT mechanism to composite the image, if supported.
+ * <p>
+ * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
+ * is being called if {@link GLCapabilitiesImmutable#isOnscreen()} is <code>false</code>.
+ * </p>
+ * 
  * <h5><A NAME="java2dgl">Java2D OpenGL Remarks</A></h5>
  *
  * To avoid any conflicts with a potential Java2D OpenGL context,<br>
@@ -145,7 +156,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   private final RecursiveLock lock = LockFactory.createRecursiveLock();
   private final GLDrawableHelper helper = new GLDrawableHelper();
   private AWTGraphicsConfiguration awtConfig;
-  private volatile GLDrawable drawable; // volatile: avoid locking for read-only access
+  private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
   private volatile JAWTWindow jawtWindow; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
   private GLContextImpl context;
   private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking
@@ -237,6 +248,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
         // don't allow the user to change data
         capsReqUser = (GLCapabilitiesImmutable) capsReqUser.cloneMutable();
     }
+    if(!capsReqUser.isOnscreen()) {
+        setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported
+    }
 
     if(null==device) {
         GraphicsConfiguration gc = super.getGraphicsConfiguration();
@@ -451,11 +465,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   /** Overridden to cause OpenGL rendering to be performed during
       repaint cycles. Subclasses which override this method must call
       super.paint() in their paint() method in order to function
-      properly. <P>
-
-      <B>Overrides:</B>
-      <DL><DD><CODE>paint</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
-    @Override
+      properly.
+    */
+  @Override
   public void paint(Graphics g) {
     if (Beans.isDesignTime()) {
       // Make GLCanvas behave better in NetBeans GUI builder
@@ -544,7 +556,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
     jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
     jawtWindow.lockSurface();
     try {
-        drawable = GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
+        drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
         context = (GLContextImpl) drawable.createContext(shareWith);
         context.setContextCreationFlags(additionalCtxCreationFlags);
     } finally {
@@ -561,13 +573,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
         if (!Beans.isDesignTime() &&
              0 < _drawable.getWidth() * _drawable.getHeight() ) {
             // make sure drawable realization happens on AWT EDT, due to AWTTree lock
-            AWTEDTExecutor.singleton.invoke(true, setRealizedOnEDTAction);
-            sendReshape=true; // ensure a reshape is being send ..
-            if(DEBUG) {
-                System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString());
-                Thread.dumpStack();
+            AWTEDTExecutor.singleton.invoke(getTreeLock(), true, setRealizedOnEDTAction);
+            if( _drawable.isRealized() ) {
+                sendReshape=true; // ensure a reshape is being send ..
+                if(DEBUG) {
+                    System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString());
+                    Thread.dumpStack();
+                }
+                return true;
             }
-            return true;
         }
     }
     return false;
@@ -575,7 +589,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   private Runnable setRealizedOnEDTAction = new Runnable() {
       @Override
     public void run() {
-          drawable.setRealized(true);
+          final GLDrawable _drawable = drawable;
+          if ( null != _drawable && 0 < _drawable.getWidth() * _drawable.getHeight() ) {
+              _drawable.setRealized(true);
+          }
       } };
 
   /** <p>Overridden to track when this component is removed from a
@@ -620,22 +637,37 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
     @SuppressWarnings("deprecation")
     @Override
   public void reshape(int x, int y, int width, int height) {
-    super.reshape(x, y, width, height);
-    final GLDrawable _drawable = drawable;
-    if(null != _drawable && _drawable.isRealized() && !_drawable.getChosenGLCapabilities().isOnscreen()) {
-        dispose(true);
-    } else {
-        sendReshape = true;
+    synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape
+        super.reshape(x, y, width, height);
+        
+        GLDrawableImpl _drawable = drawable;
+        if( null != _drawable ) {
+            if(DEBUG) {
+                System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+            }
+            if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
+                final RecursiveLock _lock = lock;
+                _lock.lock();
+                try {
+                    final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, width, height);
+                    if(_drawable != _drawableNew) {
+                        // write back 
+                        drawable = _drawableNew;
+                    }
+                } finally {
+                   _lock.unlock();
+                }
+            }
+            sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
+        }
     }
   }
 
-  /** <B>Overrides:</B>
-      <DL><DD><CODE>update</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
   /**
    * Overridden from Canvas to prevent the AWT's clearing of the
    * canvas from interfering with the OpenGL rendering.
    */
-    @Override
+  @Override
   public void update(Graphics g) {
     paint(g);
   }
@@ -681,7 +713,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
       _lock.lock();
       try {
           final GLContext oldCtx = context;
-          final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+          final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
           context=(GLContextImpl)newCtx;
           if(newCtxCurrent) {
               context.makeCurrent();
@@ -692,6 +724,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
       }
   }
 
+  @Override
+  public final GLDrawable getDelegatedDrawable() {
+    return drawable;
+  }
+  
   @Override
   public GLContext getContext() {
     return context;
@@ -866,7 +903,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
         
             if(!disposeRegenerate) {
                 if(null != awtConfig) {
-                    disposeAbstractGraphicsDevice();
+                    AWTEDTExecutor.singleton.invoke(getTreeLock(), true, disposeAbstractGraphicsDeviceActionOnEDT);
                 }
                 awtConfig=null;
             }
@@ -881,7 +918,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
     }
   };
 
-  private final Runnable disposeAbstractGraphicsDeviceAction = new Runnable() {
+  /**
+   * Disposes the AbstractGraphicsDevice within EDT,
+   * since resources created (X11: Display), must be destroyed in the same thread, where they have been created.
+   *
+   * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice)
+   */
+  private final Runnable disposeAbstractGraphicsDeviceActionOnEDT = new Runnable() {
     @Override
     public void run() {
       if(null != awtConfig) {
@@ -900,27 +943,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
       }
     }
   };
-
-  /**
-   * Disposes the AbstractGraphicsDevice within EDT,
-   * since resources created (X11: Display), must be destroyed in the same thread, where they have been created.
-   *
-   * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice)
-   */
-  private void disposeAbstractGraphicsDevice()  {
-    if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) {
-        disposeAbstractGraphicsDeviceAction.run();
-    } else {
-        try {
-            EventQueue.invokeAndWait(disposeAbstractGraphicsDeviceAction);
-        } catch (InvocationTargetException e) {
-            throw new GLException(e.getTargetException());
-        } catch (InterruptedException e) {
-            throw new GLException(e);
-        }
-    }
-  }
-
+  
   private final Runnable initAction = new Runnable() {
     @Override
     public void run() {
@@ -1046,7 +1069,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
    * @param device
    * @return the chosen AWTGraphicsConfiguration
    *
-   * @see #disposeAbstractGraphicsDevice()
+   * @see #disposeAbstractGraphicsDeviceActionOnEDT
    */
   private AWTGraphicsConfiguration chooseGraphicsConfiguration(final GLCapabilitiesImmutable capsChosen,
                                                                final GLCapabilitiesImmutable capsRequested,
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index acb8f2183..6d4a5861f 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -121,7 +121,7 @@ import com.jogamp.opengl.util.GLBuffers;
  *  </P>
 */
 
-@SuppressWarnings("serial")
+@SuppressWarnings({ "serial", "deprecation" })
 public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol {
   private static final boolean DEBUG = Debug.debug("GLJPanel");
 
@@ -396,7 +396,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
       their reshape() method in order to function properly. <P>
 
       <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
-  @SuppressWarnings("deprecation")
   @Override
   public void reshape(int x, int y, int width, int height) {
     super.reshape(x, y, width, height);
@@ -471,7 +470,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
           return null;
       }
       final GLContext oldCtx = backend.getContext();
-      final boolean newCtxCurrent = helper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags);
+      final boolean newCtxCurrent = GLDrawableHelper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags);
       backend.setContext(newCtx);
       if(newCtxCurrent) {
           newCtx.makeCurrent();
@@ -480,6 +479,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   }
 
 
+  @Override
+  public final GLDrawable getDelegatedDrawable() {
+    if (backend == null) {
+      return null;
+    }
+    return backend.getDrawable();
+  }
+  
   @Override
   public GLContext getContext() {
     if (backend == null) {
-- 
cgit v1.2.3