From c225285e09f0a29fca418601bf1aa07cafb54339 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 13 Mar 2013 06:35:30 +0100 Subject: Bug 665: Allow re-association of GLContext/GLEventListener to a GLDrawable (Part 4) Note: - GLEventListenerState preservs the GLAutoDrawable state, i.e. GLContext, all GLEventListener and the GLAnimatorControl association. - GLEventListenerState may be utilized to move the state from a dying GLAutoDrawable, to be moved to a new created GLAutoDrawable at a later time. - GLEventListenerState will be made public soon. +++ Exessive unit tests cover the new feature, tested manually on GNU/Linux/X11 and OSX(Java6/Java7). +++ - GLAutoDrawable - Change 'setContext(..)' to allow the destruction of the unbound old context: 'setContext(GLContext newCtx)' -> 'setContext(GLContext newCtx, boolean destroyPrevCtx)' - Implementations: Properly implement 'setRealized(..)' incl. obeying threading constraints if exists. Method is being utilized at least for GLEventListenerState.moveTo(..) to unrealize and realize the drawable resources. +++ Fix propagation of GLContext/GLDrawable association change (Bottom -> Top): GLDrawableImpl.associateContext GLContextImpl.associateDrawable GLContextImpl.makeCurrent GLContextImpl.destroy GLContext.setGLDrawable ... GLDrawableHelper.switchContext GLAutoDrawble.setContext associateDrawable(..)/associateContext(..) unifies and hence: - GLContextImpl.contextRealized() (removed) - GLDrawableImpl.contextRealized() (removed) - GLDrawableImpl.associateContext(..) (merged) - MacOSXCGLContext.drawableChangedNotify(..) (removed) +++ - EGLUpstreamSurfaceHook.evalUpstreamSurface() validates the surface's device for reusage, which is valid in case of GLEventListenerState.moveTo(..) - MacOSXCGLContext.NSOpenGLImpl: pixelFormat replaces NSOpenGLLayerPfmt and has simplified lifecycle [create..destroy], while native NSOpenGLLayer code only holds the reference until released. --- .../classes/jogamp/opengl/GLDrawableHelper.java | 45 ++++++++++++---------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl/GLDrawableHelper.java') diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index 3eedf918e..1caa942ba 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -59,7 +59,7 @@ import javax.media.opengl.GLFBODrawable; import javax.media.opengl.GLRunnable; /** Encapsulates the implementation of most of the GLAutoDrawable's - methods to be able to share it between GLCanvas and GLJPanel. */ + methods to be able to share it between GLAutoDrawable implementations like GLAutoDrawableBase, GLCanvas and GLJPanel. */ public class GLDrawableHelper { /** true if property jogl.debug.GLDrawable.PerfStats is defined. */ private static final boolean PERF_STATS = Debug.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true); @@ -113,6 +113,9 @@ public class GLDrawableHelper { return sb.toString(); } + /** Limit release calls of {@link #forceNativeRelease(GLContext)} to {@value}. */ + private static final int MAX_RELEASE_ITER = 512; + /** * Since GLContext's {@link GLContext#makeCurrent()} and {@link GLContext#release()} * is recursive, a call to {@link GLContext#release()} may not natively release the context. @@ -122,18 +125,25 @@ public class GLDrawableHelper { * @param ctx */ public static final void forceNativeRelease(GLContext ctx) { + int releaseCount = 0; do { ctx.release(); + releaseCount++; if (DEBUG) { - System.err.println("GLDrawableHelper.forceNativeRelease() -- currentThread "+Thread.currentThread()+" -> "+GLContext.getCurrent()); + System.err.println("GLDrawableHelper.forceNativeRelease() #"+releaseCount+" -- currentThread "+Thread.currentThread()+" -> "+GLContext.getCurrent()); } - } while( ctx == GLContext.getCurrent() ); + } while( MAX_RELEASE_ITER > releaseCount && ctx.isCurrent() ); + + if( ctx.isCurrent() ) { + throw new GLException("Context still current after "+MAX_RELEASE_ITER+" releases: "+ctx); + } } /** * Switch {@link GLContext} / {@link GLDrawable} association. *

- * Dis-associate oldCtx from drawable + * The oldCtx will be destroyed if destroyPrevCtx is true, + * otherwise dis-associate oldCtx from drawable * via {@link GLContext#setGLDrawable(GLDrawable, boolean) oldCtx.setGLDrawable(null, true);}. *

*

@@ -149,31 +159,25 @@ public class GLDrawableHelper { * * @param drawable the drawable which context is changed * @param oldCtx the old context, maybe null. + * @param destroyOldCtx if true, destroy the oldCtx * @param newCtx the new context, maybe null for dis-association. * @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)} - * @return true if the new context was current, otherwise false * - * @see GLAutoDrawable#setContext(GLContext) + * @see GLAutoDrawable#setContext(GLContext, boolean) */ - public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) { + public static final void switchContext(GLDrawable drawable, GLContext oldCtx, boolean destroyOldCtx, GLContext newCtx, int newCtxCreationFlags) { if( null != oldCtx ) { - if( oldCtx.isCurrent() ) { - oldCtx.release(); + if( destroyOldCtx ) { + oldCtx.destroy(); + } else { + oldCtx.setGLDrawable(null, true); // dis-associate old pair } - oldCtx.setGLDrawable(null, true); // dis-associate old pair } - final boolean newCtxCurrent; + if(null!=newCtx) { - newCtxCurrent = newCtx.isCurrent(); - if(newCtxCurrent) { - newCtx.release(); - } newCtx.setContextCreationFlags(newCtxCreationFlags); - newCtx.setGLDrawable(drawable, true); // re-associate new pair - } else { - newCtxCurrent = false; + newCtx.setGLDrawable(drawable, true); // re-associate new pair } - return newCtxCurrent; } /** @@ -208,7 +212,6 @@ public class GLDrawableHelper { context.makeCurrent(); } context.getGL().glFinish(); - context.release(); context.setGLDrawable(null, true); // dis-associate } @@ -837,7 +840,7 @@ public class GLDrawableHelper { if( null != exclusiveContextThread ) { throw new GLException("Release current exclusive Context Thread "+exclusiveContextThread+" first"); } - if( null != context && GLContext.getCurrent() == context ) { + if( null != context && context.isCurrent() ) { try { forceNativeRelease(context); } catch (Throwable ex) { -- cgit v1.2.3