diff options
author | Sven Gothel <sgothel@jausoft.com> | 2012-11-08 18:07:19 +0100 |
---|---|---|
committer | Sven Gothel <sgothel@jausoft.com> | 2012-11-08 18:07:19 +0100 |
commit | d0f91a8ed17fbb1a7b56511c4e53a29e576f01af (patch) | |
tree | 3e3f906f794ba1abe340190a4dfac12dadf5c921 /src/jogl/classes | |
parent | 9ce042df68b70a0e62b21b93d2a1a64722e1e49e (diff) |
Fix GLAutoDrawable.dispose(): Dispose drawable even w/o context; JAWTWindow.lockSurface(): Check AWT component's native peer
- Fix GLAutoDrawable.dispose(): Dispose drawable even w/o context
- It is possible to have the GLContext not being created (not made current),
so drawable shall be disposed independent.
- Merge Runnable 'postDisposeOnEDTAction' to dispose Runnable for clarity
- GLDrawableHelper: Split disposeGL from invokeGLImpl for clarity
- JAWTWindow.lockSurface(): Check AWT component's native peer
- W/o a native peer (!isDisplayable()), JAWT locking cannot succeed.
- On OSX OpenJDK 1.7, attempting to JAWT lock a peer-less component crashes the VM
- MacOSXJAWTWindow.lockSurfaceImpl(): Remove redundant null checks
Diffstat (limited to 'src/jogl/classes')
5 files changed, 198 insertions, 193 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 755a7c392..e80079c20 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -173,45 +173,49 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { /* * Disposes of OpenGL resources */ - private final Runnable postDisposeGLAction = new Runnable() { - @Override - public void run() { - context = null; - if (null != drawable) { - drawable.setRealized(false); - drawable = null; - } - } - }; - private final Runnable disposeOnEDTGLAction = new Runnable() { @Override public void run() { final RecursiveLock _lock = lock; _lock.lock(); try { - if (null != drawable && null != context) { - boolean animatorPaused = false; - final GLAnimatorControl animator = getAnimator(); - if (null != animator) { - animatorPaused = animator.pause(); - } - - if(context.isCreated()) { - helper.disposeGL(GLCanvas.this, drawable, context, postDisposeGLAction); - } - - if (animatorPaused) { - animator.resume(); - } + final GLAnimatorControl animator = getAnimator(); + final boolean animatorPaused; + if(null!=animator) { + // can't remove us from animator for recreational addNotify() + animatorPaused = animator.pause(); + } else { + animatorPaused = false; + } + + if ( null != context ) { + if( context.isCreated() ) { + // Catch dispose GLExceptions by GLEventListener, just 'print' them + // so we can continue with the destruction. + try { + helper.disposeGL(GLCanvas.this, context); + } catch (GLException gle) { + gle.printStackTrace(); + } + } + context = null; + } + if ( null != drawable ) { + drawable.setRealized(false); + drawable = null; } // SWT is owner of the device handle, not us. // Hence close() operation is a NOP. if (null != device) { - device.close(); - device = null; + device.close(); + device = null; } SWTAccessor.setRealized(GLCanvas.this, false); // unrealize .. + + if (animatorPaused) { + animator.resume(); + } + } finally { _lock.unlock(); } diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 1d8666e6a..a40cdcf88 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -888,33 +888,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // private boolean disposeRegenerate; - private final Runnable postDisposeOnEDTAction = new Runnable() { - @Override - public void run() { - context=null; - if(null!=drawable) { - drawable.setRealized(false); - drawable=null; - if(null!=jawtWindow) { - jawtWindow.destroy(); - jawtWindow=null; - } - } - - if(disposeRegenerate) { - // Similar process as in addNotify()! - - // Recreate GLDrawable/GLContext to reflect it's new graphics configuration - createDrawableAndContext(); - - if(DEBUG) { - System.err.println(getThreadName()+": GLCanvas.dispose(true): new drawable: "+drawable); - } - validateGLDrawable(); // immediate attempt to recreate the drawable - } - } - }; - private final Runnable disposeOnEDTAction = new Runnable() { @Override public void run() { @@ -929,31 +902,64 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing Thread.dumpStack(); } - if(null!=drawable && null!=context) { - boolean animatorPaused = false; - if(null!=animator) { - // can't remove us from animator for recreational addNotify() - animatorPaused = animator.pause(); - } - - if(context.isCreated()) { - helper.disposeGL(GLCanvas.this, drawable, context, postDisposeOnEDTAction); + final boolean animatorPaused; + if(null!=animator) { + // can't remove us from animator for recreational addNotify() + animatorPaused = animator.pause(); + } else { + animatorPaused = false; + } + + if( null != context ) { + if( context.isCreated() ) { + // Catch dispose GLExceptions by GLEventListener, just 'print' them + // so we can continue with the destruction. + try { + helper.disposeGL(GLCanvas.this, context); + } catch (GLException gle) { + gle.printStackTrace(); + } + } + context=null; + } + if( null != drawable ) { + drawable.setRealized(false); + if(DEBUG) { + System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - 1: "+drawable); } - - if(animatorPaused) { - animator.resume(); + drawable=null; + } + if( null != jawtWindow ) { + jawtWindow.destroy(); + if(DEBUG) { + System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - 2: "+jawtWindow); } + jawtWindow=null; } - - if(!disposeRegenerate) { + + if(disposeRegenerate) { + // Similar process as in addNotify()! + + // Recreate GLDrawable/GLContext to reflect it's new graphics configuration + createDrawableAndContext(); + + if(DEBUG) { + System.err.println(getThreadName()+": GLCanvas.dispose(true): new drawable: "+drawable); + } + validateGLDrawable(); // immediate attempt to recreate the drawable + } else { if(null != awtConfig) { AWTEDTExecutor.singleton.invoke(getTreeLock(), true, disposeAbstractGraphicsDeviceActionOnEDT); } awtConfig=null; } + if(animatorPaused) { + animator.resume(); + } + if(DEBUG) { - System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - END, "+animator); + System.err.println(getThreadName()+": dispose("+disposeRegenerate+") - END, animator "+animator); } } finally { diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 58b1baa65..dcfc1f0dd 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -757,21 +757,26 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return "AWT-GLJPanel[ "+((null!=backend)?backend.getDrawable().getClass().getName():"null-drawable")+"]"; } - private final Runnable postDisposeAction = new Runnable() { - @Override - public void run() { - if (backend != null && !backend.isUsingOwnThreadManagment()) { - backend.destroy(); - backend = null; - isInitialized = false; - } - } - }; - private final Runnable disposeAction = new Runnable() { @Override public void run() { - helper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction); + if ( null != backend ) { + final GLContext _context = backend.getContext(); + if( null != _context && _context.isCreated() ) { + // Catch dispose GLExceptions by GLEventListener, just 'print' them + // so we can continue with the destruction. + try { + helper.disposeGL(GLJPanel.this, _context); + } catch (GLException gle) { + gle.printStackTrace(); + } + } + if ( !backend.isUsingOwnThreadManagment() ) { + backend.destroy(); + backend = null; + isInitialized = false; + } + } } }; diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index 7bcd37ecd..68fbe3dd5 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -223,27 +223,26 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { * In such case call <code>super.destroyImplInLock</code> first.</p> */ protected void destroyImplInLock() { - final GLContext _context = context; - final GLDrawable _drawable = drawable; - if( null != _drawable ) { - if( _drawable.isRealized() ) { - if( null != _context && _context.isCreated() ) { - // Catch dispose GLExceptions by GLEventListener, just 'print' them - // so we can continue with the destruction. - try { - helper.disposeGL(this, _drawable, _context, null); - } catch (GLException gle) { - gle.printStackTrace(); - } + if( null != context ) { + if( context.isCreated() ) { + // Catch dispose GLExceptions by GLEventListener, just 'print' them + // so we can continue with the destruction. + try { + helper.disposeGL(this, context); + } catch (GLException gle) { + gle.printStackTrace(); } - _drawable.setRealized(false); } + context = null; + } + if( null != drawable ) { + final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); + drawable.setRealized(false); + drawable = null; if( ownsDevice ) { - _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close(); + device.close(); } - } - context = null; - drawable = null; + } } public final void defaultSwapBuffers() throws GLException { diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index 36dc933ab..f7f846b05 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -397,8 +397,8 @@ public class GLDrawableHelper { * otherwise maked uninitialized. * </p> * <p> - * Please consider using {@link #disposeAllGLEventListener(GLAutoDrawable, GLDrawable, GLContext)} - * or {@link #disposeGL(GLAutoDrawable, GLDrawable, GLContext, Runnable)} + * Please consider using {@link #disposeAllGLEventListener(GLAutoDrawable, GLContext, boolean)} + * or {@link #disposeGL(GLAutoDrawable, GLContext)} * for correctness, i.e. encapsulating all calls w/ makeCurrent etc. * </p> * @param autoDrawable @@ -483,8 +483,7 @@ public class GLDrawableHelper { * * @param autoDrawable * @param context - * @param listener - * @param initAction + * @param remove */ public final void disposeAllGLEventListener(final GLAutoDrawable autoDrawable, final GLDrawable drawable, @@ -505,29 +504,6 @@ public class GLDrawableHelper { } } - /** - * Principal helper method which runs - * {@link #disposeAllGLEventListener(GLAutoDrawable, boolean) disposeAllGLEventListener(autoDrawable, false)} - * with the context made current <b>and</b> destroys the context afterwards while holding the lock. - * @param autoDrawable - * @param drawable - * @param context - * @param postAction - */ - public final void disposeGL(final GLAutoDrawable autoDrawable, - final GLDrawable drawable, - final GLContext context, - final Runnable postAction) { - if(PERF_STATS) { - invokeGLImplStats(drawable, context, null, null, autoDrawable); - } else { - invokeGLImpl(drawable, context, null, null, autoDrawable); - } - if(null != postAction) { - postAction.run(); - } - } - private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { l.init(drawable); if(sendReshape) { @@ -842,21 +818,66 @@ public class GLDrawableHelper { } if(PERF_STATS) { - invokeGLImplStats(drawable, context, runnable, initAction, null); + invokeGLImplStats(drawable, context, runnable, initAction); } else { - invokeGLImpl(drawable, context, runnable, initAction, null); + invokeGLImpl(drawable, context, runnable, initAction); } } + /** + * Principal helper method which runs + * {@link #disposeAllGLEventListener(GLAutoDrawable, boolean) disposeAllGLEventListener(autoDrawable, false)} + * with the context made current <b>and</b> destroys the context afterwards while holding the lock. + * @param autoDrawable + * @param context + */ + public final void disposeGL(final GLAutoDrawable autoDrawable, + final GLContext context) { + // Support for recursive makeCurrent() calls as well as calling + // other drawables' display() methods from within another one's + GLContext lastContext = GLContext.getCurrent(); + Runnable lastInitAction = null; + if (lastContext != null) { + if (lastContext == context) { + lastContext = null; // utilize recursive locking + } else { + lastInitAction = perThreadInitAction.get(); + lastContext.release(); + } + } + int res = GLContext.CONTEXT_NOT_CURRENT; + + try { + res = context.makeCurrent(); + if (GLContext.CONTEXT_NOT_CURRENT != res) { + if(GLContext.CONTEXT_CURRENT_NEW == res) { + throw new GLException(Thread.currentThread().getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context); + } + if( listeners.size() > 0 && null != autoDrawable ) { + disposeAllGLEventListener(autoDrawable, false); + } + } + } finally { + try { + context.destroy(); + flushGLRunnables(); + } catch (Exception e) { + System.err.println("Catched: "+e.getMessage()); + e.printStackTrace(); + } + if (lastContext != null) { + final int res2 = lastContext.makeCurrent(); + if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) { + lastInitAction.run(); + } + } + } + } + private final void invokeGLImpl(final GLDrawable drawable, final GLContext context, final Runnable runnable, - final Runnable initAction, - final GLAutoDrawable disposeAutoDrawable) { - final Thread currentThread = Thread.currentThread(); - - final boolean isDisposeAction = null==initAction ; - + final Runnable initAction) { // Support for recursive makeCurrent() calls as well as calling // other drawables' display() methods from within another one's GLContext lastContext = GLContext.getCurrent(); @@ -874,35 +895,21 @@ public class GLDrawableHelper { try { res = context.makeCurrent(); if (GLContext.CONTEXT_NOT_CURRENT != res) { - if(!isDisposeAction) { - perThreadInitAction.set(initAction); - if (GLContext.CONTEXT_CURRENT_NEW == res) { - if (DEBUG) { - System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction"); - } - initAction.run(); - } - runnable.run(); - if (autoSwapBufferMode) { - drawable.swapBuffers(); - } - } else { - if(GLContext.CONTEXT_CURRENT_NEW == res) { - throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context); - } - if( listeners.size() > 0 && null != disposeAutoDrawable ) { - disposeAllGLEventListener(disposeAutoDrawable, false); - } + perThreadInitAction.set(initAction); + if (GLContext.CONTEXT_CURRENT_NEW == res) { + if (DEBUG) { + System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction"); + } + initAction.run(); + } + runnable.run(); + if ( autoSwapBufferMode ) { + drawable.swapBuffers(); } } } finally { try { - if(isDisposeAction) { - context.destroy(); - flushGLRunnables(); - } else if( GLContext.CONTEXT_NOT_CURRENT != res ) { - context.release(); - } + context.release(); } catch (Exception e) { System.err.println("Catched: "+e.getMessage()); e.printStackTrace(); @@ -919,12 +926,9 @@ public class GLDrawableHelper { private final void invokeGLImplStats(final GLDrawable drawable, final GLContext context, final Runnable runnable, - final Runnable initAction, - final GLAutoDrawable disposeAutoDrawable) { + final Runnable initAction) { final Thread currentThread = Thread.currentThread(); - final boolean isDisposeAction = null==initAction ; - // Support for recursive makeCurrent() calls as well as calling // other drawables' display() methods from within another one's int res = GLContext.CONTEXT_NOT_CURRENT; @@ -956,41 +960,28 @@ public class GLDrawableHelper { ctxClaimed = true; } if (res != GLContext.CONTEXT_NOT_CURRENT) { - if(!isDisposeAction) { - perThreadInitAction.set(initAction); - if (res == GLContext.CONTEXT_CURRENT_NEW) { - if (DEBUG) { - System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction"); - } - initAction.run(); - } - tdR = System.currentTimeMillis(); - tdA = tdR - t0; // makeCurrent - runnable.run(); - tdS = System.currentTimeMillis(); - tdR = tdS - tdR; // render time - if (autoSwapBufferMode) { - drawable.swapBuffers(); - tdX = System.currentTimeMillis(); - tdS = tdX - tdS; // swapBuffers - } - } else { - if(res == GLContext.CONTEXT_CURRENT_NEW) { - throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context); - } - if( listeners.size() > 0 && null != disposeAutoDrawable ) { - disposeAllGLEventListener(disposeAutoDrawable, false); - } + perThreadInitAction.set(initAction); + if (res == GLContext.CONTEXT_CURRENT_NEW) { + if (DEBUG) { + System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction"); + } + initAction.run(); + } + tdR = System.currentTimeMillis(); + tdA = tdR - t0; // makeCurrent + runnable.run(); + tdS = System.currentTimeMillis(); + tdR = tdS - tdR; // render time + if (autoSwapBufferMode) { + drawable.swapBuffers(); + tdX = System.currentTimeMillis(); + tdS = tdX - tdS; // swapBuffers } } } finally { try { - if(isDisposeAction) { - context.destroy(); - flushGLRunnables(); - ctxDestroyed = true; - } else if( res != GLContext.CONTEXT_NOT_CURRENT && - (null == skipContextReleaseThread || currentThread != skipContextReleaseThread) ) { + if( res != GLContext.CONTEXT_NOT_CURRENT && + (null == skipContextReleaseThread || currentThread != skipContextReleaseThread) ) { context.release(); ctxReleased = true; } |