diff options
author | Sven Gothel <[email protected]> | 2012-09-15 16:54:52 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-09-15 16:54:52 +0200 |
commit | 4dd44b985fe0541be3a3bcd9045d201ed3ca2cc5 (patch) | |
tree | e14c927a1da9f089297aa291dcd69f2f39b4f15e /src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java | |
parent | 9036376b7806a5fc61590bf49404eb71830de92f (diff) |
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].
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java')
-rw-r--r-- | src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java | 76 |
1 files changed, 49 insertions, 27 deletions
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index cc4e1b434..07029f143 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -30,16 +30,15 @@ package jogamp.opengl; import java.io.PrintStream; -import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode; import javax.media.opengl.FPSCounter; import javax.media.opengl.GL; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLAutoDrawableDelegate; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -49,6 +48,7 @@ import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.util.Animator; @@ -61,38 +61,36 @@ import com.jogamp.opengl.util.Animator; * @see GLWindow */ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { - public static final boolean DEBUG = Debug.debug("GLAutoDrawable"); + public static final boolean DEBUG = GLDrawableImpl.DEBUG; protected final GLDrawableHelper helper = new GLDrawableHelper(); protected final FPSCounterImpl fpsCounter = new FPSCounterImpl(); protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access protected GLContextImpl context; - protected final boolean ownDevice; + protected final boolean ownsDevice; protected int additionalCtxCreationFlags = 0; protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking /** - * @param drawable a valid {@link GLDrawableImpl}, may not be realized yet. - * @param context a valid {@link GLContextImpl}, may not be made current (created) yet. - * @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. + * @param drawable upstream {@link GLDrawableImpl} instance, may be null for lazy initialization + * @param context upstream {@link GLContextImpl} instance, may be null for lazy initialization + * @param ownsDevice pass <code>true</code> if {@link AbstractGraphicsDevice#close()} shall be issued, + * otherwise pass <code>false</code>. Closing the device is required in case + * the drawable is created w/ it's own new instance, e.g. offscreen drawables, + * and no further lifecycle handling is applied. */ - public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownDevice) { + public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownsDevice) { this.drawable = drawable; this.context = context; - this.ownDevice = ownDevice; + this.ownsDevice = ownsDevice; resetFPSCounter(); } + /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access. */ protected abstract RecursiveLock getLock(); - /** Returns the delegated GLDrawable */ - public final GLDrawable getDelegatedDrawable() { return drawable; } - /** Default implementation to handle repaint events from the windowing system */ protected final void defaultWindowRepaintOp() { final GLDrawable _drawable = drawable; @@ -103,29 +101,43 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { } } - /** Default implementation to handle resize events from the windowing system */ - protected final void defaultWindowResizedOp() { - final GLDrawable _drawable = drawable; + /** Default implementation to handle resize events from the windowing system. All required locks are being claimed. */ + protected final void defaultWindowResizedOp(int newWidth, int newHeight) throws NativeWindowException, GLException { + GLDrawableImpl _drawable = drawable; if( null!=_drawable ) { if(DEBUG) { - System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+getWidth()+"x"+getHeight()+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { + final RecursiveLock _lock = getLock(); + _lock.lock(); + try { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, newWidth, newHeight); + if(_drawable != _drawableNew) { + // write back + _drawable = _drawableNew; + drawable = _drawableNew; + } + } finally { + _lock.unlock(); + } } sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock if( _drawable.isRealized() ) { if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) { display(); } - } + } } } - + /** * Default implementation to handle destroy notifications from the windowing system. * * <p> * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol} * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default), - * {@link #defaultDestroy()} is being called. + * a thread safe destruction is being induced. * </p> */ protected final void defaultWindowDestroyNotifyOp() { @@ -174,7 +186,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { ctrl.resume(); } } else if (null != ns && ns.isSurfaceLockedByOtherThread()) { - // surface is locked by another thread + // Surface is locked by another thread. // Flag that destroy should be performed on the next // attempt to display. sendDestroy = true; // async, but avoiding deadlock @@ -225,7 +237,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { } _drawable.setRealized(false); } - if( ownDevice ) { + if( ownsDevice ) { _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close(); } } @@ -238,7 +250,6 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { _lock.lock(); try { if(drawable!=null && context != null) { - drawable.swapBuffers(); helper.invokeGL(drawable, context, defaultSwapAction, defaultInitAction); } } finally { @@ -276,7 +287,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { destroy(); return; } - final RecursiveLock _lock = getLock(); + final RecursiveLock _lock = getLock(); _lock.lock(); try { if( null != context ) { @@ -295,6 +306,11 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { } } ; @Override + public final GLDrawable getDelegatedDrawable() { + return drawable; + } + + @Override public final GLContext getContext() { return context; } @@ -305,7 +321,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { 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(); @@ -529,4 +545,10 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { final GLDrawable _drawable = drawable; return null != _drawable ? _drawable.getHandle() : 0; } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + + ", \n\tContext: " + context + /** ", \n\tWindow: "+window+ ", \n\tFactory: "+factory+ */ "]"; + } } |