From 4dd44b985fe0541be3a3bcd9045d201ed3ca2cc5 Mon Sep 17 00:00:00 2001 From: Sven Gothel 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]. --- src/jogl/classes/jogamp/opengl/GLDrawableImpl.java | 80 +++++++++++++++------- 1 file changed, 54 insertions(+), 26 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl/GLDrawableImpl.java') diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index abf2bf557..311690f1d 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -43,6 +43,7 @@ package jogamp.opengl; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GL; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -76,31 +77,46 @@ public abstract class GLDrawableImpl implements GLDrawable { if( !realized ) { return; // destroyed already } - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); - if ( caps.getDoubleBuffered() ) { - if(!surface.surfaceSwap()) { - int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] - if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { - return; + int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] + if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { + return; + } + try { + if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { + updateHandle(); + } + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); + if ( caps.getDoubleBuffered() ) { + if(!surface.surfaceSwap()) { + swapBuffersImpl(true); } - try { - if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { - updateHandle(); - } - swapBuffersImpl(); - } finally { - unlockSurface(); + } else { + final GLContext ctx = GLContext.getCurrent(); + if(null!=ctx && ctx.getGLDrawable()==this) { + ctx.getGL().glFlush(); } + swapBuffersImpl(false); } - } else { - GLContext ctx = GLContext.getCurrent(); - if(null!=ctx && ctx.getGLDrawable()==this) { - ctx.getGL().glFinish(); - } - } + } finally { + unlockSurface(); + } surface.surfaceUpdated(this, surface, System.currentTimeMillis()); } - protected abstract void swapBuffersImpl(); + + /** + * Platform and implementation depending surface swap. + *

The surface is locked.

+ *

+ * If doubleBuffered is true, + * an actual platform dependent surface swap shall be executed. + *

+ *

+ * If doubleBuffered is false, + * {@link GL#glFlush()} has been called already and + * the implementation may execute implementation specific code. + *

+ */ + protected abstract void swapBuffersImpl(boolean doubleBuffered); public final static String toHexString(long hex) { return "0x" + Long.toHexString(hex); @@ -181,6 +197,9 @@ public abstract class GLDrawableImpl implements GLDrawable { System.err.println(getThreadName() + ": setRealized: "+getClass().getName()+" "+this.realized+" == "+realizedArg); } } + /** + * Platform specific realization of drawable + */ protected abstract void setRealizedImpl(); /** @@ -189,7 +208,7 @@ public abstract class GLDrawableImpl implements GLDrawable { * If realized is true, the context has just been created and made current. *

*

- * If realized is false, the context is still current and will be release and destroyed after this method returns. + * If realized is false, the context is still current and will be released and destroyed after this method returns. *

*

* @see #contextMadeCurrent(GLContext, boolean) @@ -199,18 +218,27 @@ public abstract class GLDrawableImpl implements GLDrawable { /** * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: makeCurrent, release. *

- * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered. - *

- *

* If current is true, the context has just been made current. *

*

* If current is false, the context is still current and will be release after this method returns. *

+ *

+ * Note: Will also be called after {@link #contextRealized(GLContext, boolean) contextRealized(ctx, true)} + * but not at context destruction, i.e. {@link #contextRealized(GLContext, boolean) contextRealized(ctx, false)}. + *

* @see #contextRealized(GLContext, boolean) */ protected void contextMadeCurrent(GLContext glc, boolean current) { } + /** + * Callback for special implementations, allowing to associate bound context to this drawable (bound == true) + * or to remove such association (bound == false). + * @param ctx the just bounded or unbounded context + * @param bound if true create an association, otherwise remove it + */ + protected void associateContext(GLContext ctx, boolean bound) { } + /** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/ protected int getDefaultDrawFramebuffer() { return 0; } /** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */ @@ -245,8 +273,8 @@ public abstract class GLDrawableImpl implements GLDrawable { public String toString() { return getClass().getSimpleName()+"[Realized "+isRealized()+ ",\n\tFactory "+getFactory()+ - ",\n\thandle "+toHexString(getHandle())+ - ",\n\tWindow "+getNativeSurface()+"]"; + ",\n\tHandle "+toHexString(getHandle())+ + ",\n\tSurface "+getNativeSurface()+"]"; } protected static String getThreadName() { -- cgit v1.2.3