diff options
author | Sven Gothel <[email protected]> | 2013-03-13 07:12:59 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-03-13 07:12:59 +0100 |
commit | e2506d7663b752f00f0a98f793ebad52e65bd1e3 (patch) | |
tree | 66e669f22824892aec2d157aca5c384f1bd348c4 | |
parent | c225285e09f0a29fca418601bf1aa07cafb54339 (diff) |
Bug 665: Allow re-association of GLContext/GLEventListener to a GLDrawable (Part 5)
- GLAutoDrawableBase:
- Add 'setPreserveGLStateAtDestroy(..)' to preserve the GLEventListenerState at destroy() operation,
and impl. details pullGLEventListenerState()/pushGLEventListenerState().
pullGLEventListenerState() is called automatic at destroyImplInLock(),
where pushGLEventListenerState() has to be called after drawable realization
instead of context creation.
- Note/TODO: Method will become public in GLAutoDrawable in general!
- NEWT/GLWindow:
- Use GLEventListenerState preservation for reparenting case w/ destruction,
i.e. keep GLContext/GLEventListener alive while reparenting in recreation mode.
Scenario: NewtCanvasAWT Child <-> Top on OSX w/ CALayer
-rw-r--r-- | src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java | 56 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/opengl/GLWindow.java | 20 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/WindowImpl.java | 30 |
3 files changed, 89 insertions, 17 deletions
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index ad67f8281..cab768e3a 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -68,6 +68,8 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access protected GLContextImpl context; + protected boolean preserveGLELSAtDestroy; + protected GLEventListenerState glels; protected final boolean ownsDevice; protected int additionalCtxCreationFlags = 0; protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking @@ -88,6 +90,8 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownsDevice) { this.drawable = drawable; this.context = context; + this.preserveGLELSAtDestroy = false; + this.glels = null; this.ownsDevice = ownsDevice; if(null != context && null != drawable) { context.setGLDrawable(drawable, false); @@ -97,6 +101,54 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access. */ protected abstract RecursiveLock getLock(); + + + /** + * If set to <code>true</code>, the next {@link #destroy()} operation will + * {@link #pullGLEventListenerState() pull} to preserve the {@link GLEventListenerState}. + */ + public final void setPreserveGLStateAtDestroy(boolean value) { + preserveGLELSAtDestroy = value; + } + + /** + * Pulls the {@link GLEventListenerState} from this {@link GLAutoDrawable}. + * + * @return <code>true</code> if the {@link GLEventListenerState} is pulled successfully from this {@link GLAutoDrawable}, + * otherwise <code>false</code>. + * + * @throws IllegalStateException if the {@link GLEventListenerState} is already pulled + * + * @see #pushGLEventListenerState() + */ + protected final boolean pullGLEventListenerState() throws IllegalStateException { + if( null != glels ) { + throw new IllegalStateException("GLEventListenerState already pulled"); + } + if( null != context && context.isCreated() ) { + glels = GLEventListenerState.moveFrom(this); + return null != glels; + } + return false; + } + + /** + * Pushes a previously {@link #pullGLEventListenerState() pulled} {@link GLEventListenerState} to this {@link GLAutoDrawable}. + * + * @return <code>true</code> if the {@link GLEventListenerState} was previously {@link #pullGLEventListenerState() pulled} + * and is pushed successfully to this {@link GLAutoDrawable}, + * otherwise <code>false</code>. + * + * @see #pullGLEventListenerState() + */ + protected final boolean pushGLEventListenerState() { + if( null != glels ) { + glels.moveTo(this); + glels = null; + return true; + } + return false; + } /** Default implementation to handle repaint events from the windowing system */ protected final void defaultWindowRepaintOp() { @@ -229,6 +281,10 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { * In such case call <code>super.destroyImplInLock</code> first.</p> */ protected void destroyImplInLock() { + if( preserveGLELSAtDestroy ) { + preserveGLELSAtDestroy = false; + pullGLEventListenerState(); + } if( null != context ) { if( context.isCreated() ) { // Catch dispose GLExceptions by GLEventListener, just 'print' them diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index ce50d95dd..33f136460 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -421,6 +421,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind protected class GLLifecycleHook implements WindowImpl.LifecycleHook { @Override + public void setPreserveResourcesAtDestroy() { + GLWindow.this.setPreserveGLStateAtDestroy(true); + } + + @Override public synchronized void destroyActionPreLock() { // nop } @@ -433,7 +438,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind //Exception e1 = new Exception(msg); //e1.printStackTrace(); } - + destroyImplInLock(); if(Window.DEBUG_IMPLEMENTATION) { @@ -479,8 +484,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } drawable = (GLDrawableImpl) factory.createGLDrawable(nw); drawable.setRealized(true); - context = (GLContextImpl) drawable.createContext(sharedContext); - context.setContextCreationFlags(additionalCtxCreationFlags); + + if( !GLWindow.this.pushGLEventListenerState() ) { + context = (GLContextImpl) drawable.createContext(sharedContext); + context.setContextCreationFlags(additionalCtxCreationFlags); + } } if(Window.DEBUG_IMPLEMENTATION) { System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", fin: dt "+ (System.nanoTime()-t0)/1e6 +"ms"); @@ -512,7 +520,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind // private GLContext sharedContext = null; - + @Override protected final RecursiveLock getLock() { return window.getLock(); @@ -571,10 +579,6 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } @Override - public final void setRealized(boolean realized) { - } - - @Override public final void swapBuffers() throws GLException { defaultSwapBuffers(); } diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index af0bde179..dfaa55679 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -222,6 +222,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer */ void setVisibleActionPost(boolean visible, boolean nativeWindowCreated); + /** + * Notifies the receiver to preserve resources (GL, ..) + * for the next destroy*() calls (only). + */ + void setPreserveResourcesAtDestroy(); + /** * Invoked before Window destroy action, * allows releasing of resources depending on the native Window.<br> @@ -953,6 +959,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer runOnEDTIfAvail(true, destroyAction); } + protected void destroy(boolean preserveResources) { + if( preserveResources && null != WindowImpl.this.lifecycleHook ) { + WindowImpl.this.lifecycleHook.setPreserveResourcesAtDestroy(); + } + destroy(); + } + /** * @param cWin child window, must not be null * @param pWin parent window, may be null @@ -1053,9 +1066,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if(null==newParentWindowNEWT) { throw new NativeWindowException("Reparenting with non NEWT Window type only available after it's realized: "+newParentWindow); } - // Destroy this window and use parent's Screen. + // Destroy this window and use parent's Screen, while trying to preserve resources. // It may be created properly when the parent is made visible. - destroy(); + destroy(true); setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() ); operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING; } else if(newParentWindow != getParent()) { @@ -1078,9 +1091,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING; } } else if ( forceDestroyCreate || !NewtFactory.isScreenCompatible(newParentWindow, screen) ) { - // Destroy this window, may create a new compatible Screen/Display, - // and mark it for creation. - destroy(); + // Destroy this window, may create a new compatible Screen/Display, while trying to preserve resources. + destroy(true); if(null!=newParentWindowNEWT) { setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() ); } else { @@ -1109,8 +1121,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // Already Top Window operation = ReparentOperation.ACTION_NOP; } else if( !isNativeValid() || forceDestroyCreate ) { - // Destroy this window and mark it for [pending] creation. - destroy(); + // Destroy this window and mark it for [pending] creation, while trying to preserve resources. + destroy(true); if( 0 < width && 0 < height ) { operation = ReparentOperation.ACTION_NATIVE_CREATION; } else { @@ -1213,11 +1225,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } if(!ok) { - // native reparent failed -> try creation + // native reparent failed -> try creation, while trying to preserve resources. if(DEBUG_IMPLEMENTATION) { System.err.println("Window.reparent: native reparenting failed ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentWindowHandle)+" - Trying recreation"); } - destroy(); + destroy(true); operation = ReparentOperation.ACTION_NATIVE_CREATION ; } } |