From 3ad03e41a0cda81119c23f350c00b064a4de70c2 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 22 Mar 2013 10:29:54 +0100 Subject: Add GLStateKeeper handling GLEventListenerState preservation and restauration for GLAutoDrawable - New GLStateKeeper interface, package com.jogamp.opengl Implemented by: - GLAutoDrawableBase Currently supported by: - NEWT GLWindow - GLEventListenerState package move: com.jogamp.opengl.util -> com.jogamp.opengl --- .../com/jogamp/opengl/GLEventListenerState.java | 375 +++++++++++++++++++++ .../classes/com/jogamp/opengl/GLStateKeeper.java | 87 +++++ .../com/jogamp/opengl/util/GLDrawableUtil.java | 2 + .../jogamp/opengl/util/GLEventListenerState.java | 365 -------------------- .../classes/jogamp/opengl/GLAutoDrawableBase.java | 48 ++- .../classes/com/jogamp/newt/opengl/GLWindow.java | 7 +- src/newt/classes/jogamp/newt/WindowImpl.java | 4 +- .../acore/glels/GLContextDrawableSwitchBase.java | 2 +- .../glels/TestGLContextDrawableSwitch10NEWT.java | 2 +- .../TestGLContextDrawableSwitch11NewtAWT.java | 2 +- .../glels/TestGLContextDrawableSwitch12AWT.java | 2 +- .../TestGLContextDrawableSwitch21Newt2AWT.java | 2 +- 12 files changed, 513 insertions(+), 385 deletions(-) create mode 100644 src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java create mode 100644 src/jogl/classes/com/jogamp/opengl/GLStateKeeper.java delete mode 100644 src/jogl/classes/com/jogamp/opengl/util/GLEventListenerState.java diff --git a/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java b/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java new file mode 100644 index 000000000..5c0954584 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java @@ -0,0 +1,375 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl; + +import java.util.ArrayList; +import java.util.List; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.VisualIDHolder; +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLRunnable; + +import jogamp.opengl.Debug; + +import com.jogamp.nativewindow.MutableGraphicsConfiguration; + +/** + * GLEventListenerState is holding {@link GLAutoDrawable} components crucial + * to relocating all its {@link GLEventListener} w/ their operating {@link GLContext}, etc. + * The components are: + * + *

+ * A GLEventListenerState instance can be created while components are {@link #moveFrom(GLAutoDrawable) moved from} a {@link GLAutoDrawable} + * to the new instance, which gains {@link #isOwner() ownership} of the moved components. + *

+ *

+ * A GLEventListenerState instance's components can be {@link #moveTo(GLAutoDrawable) moved to} a {@link GLAutoDrawable}, + * while loosing {@link #isOwner() ownership} of the moved components. + *

+ *

+ */ +public class GLEventListenerState { + private static final boolean DEBUG = Debug.debug("GLDrawable"); + + private GLEventListenerState(AbstractGraphicsScreen upstreamScreen, boolean proxyOwnsUpstreamDevice, AbstractGraphicsScreen screen, GLCapabilitiesImmutable caps, + GLContext context, int count, GLAnimatorControl anim, boolean animStarted) { + this.upstreamScreen = upstreamScreen; + this.proxyOwnsUpstreamDevice = proxyOwnsUpstreamDevice; + this.screen = screen; + this.caps = caps; + this.context = context; + this.listeners = new GLEventListener[count]; + this.listenersInit = new boolean[count]; + this.anim = anim; + this.animStarted = animStarted; + + this.owner = true; + } + /** + * Returns true, if this instance is the current owner of the components, + * otherwise false. + *

+ * Ownership is lost if {@link #moveTo(GLAutoDrawable)} is being called successfully + * and all components are transferred to the new {@link GLAutoDrawable}. + *

+ */ + public final boolean isOwner() { return owner; } + + public final int listenerCount() { return listeners.length; } + + public final AbstractGraphicsScreen upstreamScreen; + public final boolean proxyOwnsUpstreamDevice; + public final AbstractGraphicsScreen screen; + public final GLCapabilitiesImmutable caps; + public final GLContext context; + public final GLEventListener[] listeners; + public final boolean[] listenersInit; + public final GLAnimatorControl anim; + public final boolean animStarted; + + private boolean owner; + + /** + * Last resort to destroy and loose ownership + */ + public void destroy() { + if( owner ) { + final int aSz = listenerCount(); + for(int i=0; i + * Note that all components are removed from the {@link GLAutoDrawable}, + * i.e. the {@link GLContext}, all {@link GLEventListener}. + *

+ *

+ * If the {@link GLAutoDrawable} was added to a {@link GLAnimatorControl}, it is removed + * and the {@link GLAnimatorControl} added to the GLEventListenerState. + *

+ *

+ * The returned GLEventListenerState instance is the {@link #isOwner() owner of the components}. + *

+ * + * @param a {@link GLAutoDrawable} source to move components from + * @return new GLEventListenerState instance {@link #isOwner() owning} moved components. + * + * @see #moveTo(GLAutoDrawable) + */ + public static GLEventListenerState moveFrom(GLAutoDrawable a) { + final int aSz = a.getGLEventListenerCount(); + + // Create new AbstractGraphicsScreen w/ cloned AbstractGraphicsDevice for future GLAutoDrawable + // allowing this AbstractGraphicsDevice to loose ownership -> not closing display/device! + final NativeSurface aSurface = a.getNativeSurface(); + final AbstractGraphicsConfiguration aCfg = aSurface.getGraphicsConfiguration(); + final AbstractGraphicsScreen aScreen1 = aCfg.getScreen(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities(); + final AbstractGraphicsScreen aScreen2 = cloneScreen(aScreen1); + if( DEBUG ) { + System.err.println("GLEventListenerState.moveFrom.0: "+aSurface.getClass().getName()+", "+aSurface); + } + aScreen1.getDevice().clearHandleOwner(); // don't close device handle + + final AbstractGraphicsScreen aUpScreen2; + final boolean proxyOwnsUpstreamDevice; + { + AbstractGraphicsScreen _aUpScreen2=null; + if(aSurface instanceof ProxySurface) { + final ProxySurface aProxy = (ProxySurface)aSurface; + proxyOwnsUpstreamDevice = aProxy.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + final NativeSurface aUpSurface = aProxy.getUpstreamSurface(); + if(DEBUG && null != aUpSurface) { + System.err.println("GLEventListenerState.moveFrom.1: "+aUpSurface.getClass().getName()+", "+aUpSurface); + } + if(null != aUpSurface) { + final AbstractGraphicsScreen aUpScreen1 = aUpSurface.getGraphicsConfiguration().getScreen(); + _aUpScreen2 = cloneScreen(aUpScreen1); + if(null != aUpScreen1) { + aUpScreen1.getDevice().clearHandleOwner(); // don't close device handle + } + if(DEBUG) { + System.err.println("GLEventListenerState.moveFrom.2: "+aSurface.getClass().getName()+", "+aSurface); + System.err.println("GLEventListenerState.moveFrom.3: "+aUpSurface.getClass().getName()+", "+aUpSurface); + } + } + } else { + proxyOwnsUpstreamDevice = false; + } + aUpScreen2=_aUpScreen2; + } + + final GLAnimatorControl aAnim = a.getAnimator(); + final boolean aAnimStarted; + if( null != aAnim ) { + aAnimStarted = aAnim.isStarted(); + aAnim.remove(a); // also handles ECT + } else { + aAnimStarted = false; + } + + final GLEventListenerState glls = new GLEventListenerState(aUpScreen2, proxyOwnsUpstreamDevice, aScreen2, caps, a.getContext(), aSz, aAnim, aAnimStarted); + + // + // remove and cache all GLEventListener and their init-state + // + for(int i=0; i + * If the previous {@link GLAutoDrawable} was removed from a {@link GLAnimatorControl} by previous {@link #moveFrom(GLAutoDrawable)}, + * the given {@link GLAutoDrawable} is added to the cached {@link GLAnimatorControl}. + * This operation is skipped, if the given {@link GLAutoDrawable} is already added to a {@link GLAnimatorControl} instance. + *

+ *

+ * Note: After this operation, the GLEventListenerState reference should be released. + *

+ * + * @param a {@link GLAutoDrawable} destination to move GLEventListenerState components to + * + * @throws GLException if the {@link GLAutoDrawable}'s configuration is incompatible, i.e. different {@link GLCapabilitiesImmutable}. + * + * @see #moveFrom(GLAutoDrawable) + * @see #isOwner() + */ + public final void moveTo(GLAutoDrawable a) { + final List aGLCmds = new ArrayList(); + final int aSz = listenerCount(); + + final NativeSurface aSurface = a.getNativeSurface(); + final MutableGraphicsConfiguration aCfg = (MutableGraphicsConfiguration) aSurface.getGraphicsConfiguration(); + final GLCapabilitiesImmutable aCaps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities(); + if( caps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) != aCaps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) || + caps.getVisualID(VisualIDHolder.VIDType.NATIVE) != aCaps.getVisualID(VisualIDHolder.VIDType.NATIVE) ) { + throw new GLException("Incompatible Capabilities - Prev-Holder: "+caps+", New-Holder "+caps); + } + // Destroy and remove currently associated GLContext, if any (will be replaced) + a.setContext( null, true ); + final boolean aRealized = a.isRealized(); + if( aRealized ) { + a.setRealized(false); + } + // Set new Screen and close previous one + { + if( DEBUG ) { + System.err.println("GLEventListenerState.moveTo.0: "+aSurface.getClass().getName()+", "+aSurface); + } + final AbstractGraphicsScreen aScreen1 = aCfg.getScreen(); + aCfg.setScreen( screen ); + aScreen1.getDevice().close(); + if( DEBUG ) { + System.err.println("GLEventListenerState.moveTo.1: "+aSurface.getClass().getName()+", "+aSurface); + } + } + + // If using a ProxySurface w/ an upstream surface, set new Screen and close previous one on it + { + boolean upstreamSet = false; + if(aSurface instanceof ProxySurface) { + final ProxySurface aProxy = (ProxySurface)aSurface; + final NativeSurface aUpSurface = aProxy.getUpstreamSurface(); + if(null != aUpSurface) { + final MutableGraphicsConfiguration aUpCfg = (MutableGraphicsConfiguration) aUpSurface.getGraphicsConfiguration(); + if( null != upstreamScreen ) { + if( DEBUG ) { + System.err.println("GLEventListenerState.moveTo.2: "+aUpSurface.getClass().getName()+", "+aUpSurface+", "+aProxy.getUpstreamOptionBits(null).toString()); + } + aUpCfg.getScreen().getDevice().close(); + aUpCfg.setScreen( upstreamScreen ); + if( proxyOwnsUpstreamDevice ) { + aProxy.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + upstreamSet = true; + if( DEBUG ) { + System.err.println("GLEventListenerState.moveTo.3: "+aUpSurface.getClass().getName()+", "+aUpSurface+", "+aProxy.getUpstreamOptionBits(null).toString()); + } + } else { + throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = false, New-Holder = true"); + } + } + } + if( !upstreamSet && null != upstreamScreen ) { + throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = true, New-Holder = false"); + } + } + + if( aRealized ) { + a.setRealized(true); + } + final boolean surfaceLocked = false; // NativeSurface.LOCK_SURFACE_NOT_READY < aSurface.lockSurface(); + try { + a.setContext( context, false ); + } finally { + if( surfaceLocked ) { + aSurface.unlockSurface(); + } + } + owner = false; + + // + // Trigger GL-Viewport reset and reshape of all initialized GLEventListeners + // + aGLCmds.add(setViewport); + for(int i=0; i + * Implementing classes {@link #isGLStatePreservationSupported() may support} preservation + * of the {@link GLContext} state and it's associated {@link GLEventListener}. + *

+ */ +public interface GLStateKeeper { + + /** Listener for preserve and restore notifications. */ + public static interface Listener { + /** Invoked before preservation. */ + void glStatePreserveNotify(GLStateKeeper glsk); + /** Invoked after restoration. */ + void glStateRestored(GLStateKeeper glsk); + } + + /** + * Sets a {@link Listener}, overriding the old one. + * @param l the new {@link Listener}. + * @return the previous {@link Listener}. + */ + public Listener setGLStateKeeperListener(Listener l); + + /** + * @return true if GL state preservation is supported in implementation and on current platform, false otherwise. + * @see #preserveGLStateAtDestroy(boolean) + * @see #getPreservedGLState() + */ + public boolean isGLStatePreservationSupported(); + + /** + * If set to true, the next {@link GLAutoDrawable#destroy()} operation will + * {@link #pullGLEventListenerState() pull} to preserve the {@link GLEventListenerState}. + *

+ * This is a one-shot flag, i.e. after preserving the {@link GLEventListenerState}, + * the flag is cleared. + *

+ *

+ * A preserved {@link GLEventListenerState} will be {@link #pushGLEventListenerState() pushed} + * if realized again. + *

+ * @return true if supported and successful, false otherwise. + * @see #isGLStatePreservationSupported() + * @see #getPreservedGLState() + */ + public boolean preserveGLStateAtDestroy(boolean value); + + /** + * Returns the preserved {@link GLEventListenerState} if preservation was performed, + * otherwise null. + * @see #isGLStatePreservationSupported() + * @see #preserveGLStateAtDestroy(boolean) + */ + public GLEventListenerState getPreservedGLState(); + +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java index 1d68a402a..68d94d2e2 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java @@ -33,6 +33,8 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLEventListener; +import com.jogamp.opengl.GLEventListenerState; + import jogamp.opengl.Debug; /** diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLEventListenerState.java b/src/jogl/classes/com/jogamp/opengl/util/GLEventListenerState.java deleted file mode 100644 index 5b02e1fec..000000000 --- a/src/jogl/classes/com/jogamp/opengl/util/GLEventListenerState.java +++ /dev/null @@ -1,365 +0,0 @@ -/** - * Copyright 2013 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.opengl.util; - -import java.util.ArrayList; -import java.util.List; - -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.AbstractGraphicsScreen; -import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.NativeWindowFactory; -import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.VisualIDHolder; -import javax.media.opengl.GLAnimatorControl; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLException; -import javax.media.opengl.GLRunnable; - -import jogamp.opengl.Debug; - -import com.jogamp.nativewindow.MutableGraphicsConfiguration; - -/** - * GLEventListenerState is holding {@link GLAutoDrawable} components crucial - * to relocating all its {@link GLEventListener} w/ their operating {@link GLContext}, etc. - * The components are: - *
    - *
  • {@link GLContext}
  • - *
  • All {@link GLEventListener}, incl. their init state
  • - *
  • {@link GLAnimatorControl}
  • - *
  • {@link GLCapabilitiesImmutable} for compatibility check
  • - *
  • {@link AbstractGraphicsScreen} for compatibility check and preserving the {@link AbstractGraphicsDevice}
  • - *
- *

- * A GLEventListenerState instance can be created while components are {@link #moveFrom(GLAutoDrawable) moved from} a {@link GLAutoDrawable} - * to the new instance, which gains {@link #isOwner() ownership} of the moved components. - *

- *

- * A GLEventListenerState instance's components can be {@link #moveTo(GLAutoDrawable) moved to} a {@link GLAutoDrawable}, - * while loosing {@link #isOwner() ownership} of the moved components. - *

- *

- */ -public class GLEventListenerState { - private static final boolean DEBUG = Debug.debug("GLDrawable"); - - private GLEventListenerState(AbstractGraphicsScreen upstreamScreen, boolean proxyOwnsUpstreamDevice, AbstractGraphicsScreen screen, GLCapabilitiesImmutable caps, - GLContext context, int count, GLAnimatorControl anim) { - this.upstreamScreen = upstreamScreen; - this.proxyOwnsUpstreamDevice = proxyOwnsUpstreamDevice; - this.screen = screen; - this.caps = caps; - this.context = context; - this.listeners = new GLEventListener[count]; - this.listenersInit = new boolean[count]; - this.anim = anim; - this.owner = true; - } - /** - * Returns true, if this instance is the current owner of the components, - * otherwise false. - *

- * Ownership is lost if {@link #moveTo(GLAutoDrawable)} is being called successfully - * and all components are transferred to the new {@link GLAutoDrawable}. - *

- */ - public final boolean isOwner() { return owner; } - - public final int listenerCount() { return listeners.length; } - - public final AbstractGraphicsScreen upstreamScreen; - public final boolean proxyOwnsUpstreamDevice; - public final AbstractGraphicsScreen screen; - public final GLCapabilitiesImmutable caps; - public final GLContext context; - public final GLEventListener[] listeners; - public final boolean[] listenersInit; - public final GLAnimatorControl anim; - - private boolean owner; - - /** - * Last resort to destroy and loose ownership - */ - public void destroy() { - if( owner ) { - final int aSz = listenerCount(); - for(int i=0; i - * Note that all components are removed from the {@link GLAutoDrawable}, - * i.e. the {@link GLContext}, all {@link GLEventListener}. - *

- *

- * If the {@link GLAutoDrawable} was added to a {@link GLAnimatorControl}, it is removed - * and the {@link GLAnimatorControl} added to the GLEventListenerState. - *

- *

- * The returned GLEventListenerState instance is the {@link #isOwner() owner of the components}. - *

- * - * @param a {@link GLAutoDrawable} source to move components from - * @return new GLEventListenerState instance {@link #isOwner() owning} moved components. - * - * @see #moveTo(GLAutoDrawable) - */ - public static GLEventListenerState moveFrom(GLAutoDrawable a) { - final int aSz = a.getGLEventListenerCount(); - - // Create new AbstractGraphicsScreen w/ cloned AbstractGraphicsDevice for future GLAutoDrawable - // allowing this AbstractGraphicsDevice to loose ownership -> not closing display/device! - final NativeSurface aSurface = a.getNativeSurface(); - final AbstractGraphicsConfiguration aCfg = aSurface.getGraphicsConfiguration(); - final AbstractGraphicsScreen aScreen1 = aCfg.getScreen(); - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities(); - final AbstractGraphicsScreen aScreen2 = cloneScreen(aScreen1); - if( DEBUG ) { - System.err.println("GLEventListenerState.moveFrom.0: "+aSurface.getClass().getName()+", "+aSurface); - } - aScreen1.getDevice().clearHandleOwner(); // don't close device handle - - final AbstractGraphicsScreen aUpScreen2; - final boolean proxyOwnsUpstreamDevice; - { - AbstractGraphicsScreen _aUpScreen2=null; - if(aSurface instanceof ProxySurface) { - final ProxySurface aProxy = (ProxySurface)aSurface; - proxyOwnsUpstreamDevice = aProxy.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); - final NativeSurface aUpSurface = aProxy.getUpstreamSurface(); - if(DEBUG && null != aUpSurface) { - System.err.println("GLEventListenerState.moveFrom.1: "+aUpSurface.getClass().getName()+", "+aUpSurface); - } - if(null != aUpSurface) { - final AbstractGraphicsScreen aUpScreen1 = aUpSurface.getGraphicsConfiguration().getScreen(); - _aUpScreen2 = cloneScreen(aUpScreen1); - if(null != aUpScreen1) { - aUpScreen1.getDevice().clearHandleOwner(); // don't close device handle - } - if(DEBUG) { - System.err.println("GLEventListenerState.moveFrom.2: "+aSurface.getClass().getName()+", "+aSurface); - System.err.println("GLEventListenerState.moveFrom.3: "+aUpSurface.getClass().getName()+", "+aUpSurface); - } - } - } else { - proxyOwnsUpstreamDevice = false; - } - aUpScreen2=_aUpScreen2; - } - - final GLAnimatorControl aAnim = a.getAnimator(); - if( null != aAnim ) { - aAnim.remove(a); // also handles ECT - } - - final GLEventListenerState glls = new GLEventListenerState(aUpScreen2, proxyOwnsUpstreamDevice, aScreen2, caps, a.getContext(), aSz, aAnim); - - // - // remove and cache all GLEventListener and their init-state - // - for(int i=0; i - * If the previous {@link GLAutoDrawable} was removed from a {@link GLAnimatorControl} by previous {@link #moveFrom(GLAutoDrawable)}, - * the given {@link GLAutoDrawable} is added to the cached {@link GLAnimatorControl}. - * This operation is skipped, if the given {@link GLAutoDrawable} is already added to a {@link GLAnimatorControl} instance. - *

- *

- * Note: After this operation, the GLEventListenerState reference should be released. - *

- * - * @param a {@link GLAutoDrawable} destination to move GLEventListenerState components to - * - * @throws GLException if the {@link GLAutoDrawable}'s configuration is incompatible, i.e. different {@link GLCapabilitiesImmutable}. - * - * @see #moveFrom(GLAutoDrawable) - * @see #isOwner() - */ - public final void moveTo(GLAutoDrawable a) { - final List aGLCmds = new ArrayList(); - final int aSz = listenerCount(); - - final NativeSurface aSurface = a.getNativeSurface(); - final MutableGraphicsConfiguration aCfg = (MutableGraphicsConfiguration) aSurface.getGraphicsConfiguration(); - final GLCapabilitiesImmutable aCaps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities(); - if( caps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) != aCaps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) || - caps.getVisualID(VisualIDHolder.VIDType.NATIVE) != aCaps.getVisualID(VisualIDHolder.VIDType.NATIVE) ) { - throw new GLException("Incompatible Capabilities - Prev-Holder: "+caps+", New-Holder "+caps); - } - // Destroy and remove currently associated GLContext, if any (will be replaced) - a.setContext( null, true ); - final boolean aRealized = a.isRealized(); - if( aRealized ) { - a.setRealized(false); - } - // Set new Screen and close previous one - { - if( DEBUG ) { - System.err.println("GLEventListenerState.moveTo.0: "+aSurface.getClass().getName()+", "+aSurface); - } - final AbstractGraphicsScreen aScreen1 = aCfg.getScreen(); - aCfg.setScreen( screen ); - aScreen1.getDevice().close(); - if( DEBUG ) { - System.err.println("GLEventListenerState.moveTo.1: "+aSurface.getClass().getName()+", "+aSurface); - } - } - - // If using a ProxySurface w/ an upstream surface, set new Screen and close previous one on it - { - boolean upstreamSet = false; - if(aSurface instanceof ProxySurface) { - final ProxySurface aProxy = (ProxySurface)aSurface; - final NativeSurface aUpSurface = aProxy.getUpstreamSurface(); - if(null != aUpSurface) { - final MutableGraphicsConfiguration aUpCfg = (MutableGraphicsConfiguration) aUpSurface.getGraphicsConfiguration(); - if( null != upstreamScreen ) { - if( DEBUG ) { - System.err.println("GLEventListenerState.moveTo.2: "+aUpSurface.getClass().getName()+", "+aUpSurface+", "+aProxy.getUpstreamOptionBits(null).toString()); - } - aUpCfg.getScreen().getDevice().close(); - aUpCfg.setScreen( upstreamScreen ); - if( proxyOwnsUpstreamDevice ) { - aProxy.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); - } - upstreamSet = true; - if( DEBUG ) { - System.err.println("GLEventListenerState.moveTo.3: "+aUpSurface.getClass().getName()+", "+aUpSurface+", "+aProxy.getUpstreamOptionBits(null).toString()); - } - } else { - throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = false, New-Holder = true"); - } - } - } - if( !upstreamSet && null != upstreamScreen ) { - throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = true, New-Holder = false"); - } - } - - if( aRealized ) { - a.setRealized(true); - } - final boolean surfaceLocked = false; // NativeSurface.LOCK_SURFACE_NOT_READY < aSurface.lockSurface(); - try { - a.setContext( context, false ); - } finally { - if( surfaceLocked ) { - aSurface.unlockSurface(); - } - } - owner = false; - - // - // Trigger GL-Viewport reset and reshape of all initialized GLEventListeners - // - aGLCmds.add(setViewport); - for(int i=0; itrue, the next {@link #destroy()} operation will - * {@link #pullGLEventListenerState() pull} to preserve the {@link GLEventListenerState}. - */ - public final void setPreserveGLStateAtDestroy(boolean value) { - if( DEBUG ) { - System.err.println("GLAutoDrawableBase.setPreserveGLStateAtDestroy: ("+Thread.currentThread().getName()+"): "+preserveGLELSAtDestroy+" -> "+value+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + @Override + public final boolean preserveGLStateAtDestroy(boolean value) { + final boolean res = isGLStatePreservationSupported() ? true : false; + if( res ) { + if( DEBUG ) { + System.err.println("GLAutoDrawableBase.setPreserveGLStateAtDestroy: ("+Thread.currentThread().getName()+"): "+preserveGLELSAtDestroy+" -> "+value+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + preserveGLELSAtDestroy = value; + } else { + } - preserveGLELSAtDestroy = value; + return res; } + @Override + public boolean isGLStatePreservationSupported() { return false; } + + @Override + public final GLEventListenerState getPreservedGLState() { + return glels; + } + /** * Pulls the {@link GLEventListenerState} from this {@link GLAutoDrawable}. * @@ -130,6 +150,9 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { throw new IllegalStateException("GLEventListenerState already pulled"); } if( null != context && context.isCreated() ) { + if( null!= glStateKeeperListener) { + glStateKeeperListener.glStatePreserveNotify(this); + } glels = GLEventListenerState.moveFrom(this); return null != glels; } @@ -149,6 +172,9 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { if( null != glels ) { glels.moveTo(this); glels = null; + if( null!= glStateKeeperListener) { + glStateKeeperListener.glStateRestored(this); + } return true; } return false; @@ -286,7 +312,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { */ protected void destroyImplInLock() { if( preserveGLELSAtDestroy ) { - setPreserveGLStateAtDestroy(false); + preserveGLStateAtDestroy(false); pullGLEventListenerState(); } if( null != context ) { diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 33f136460..a6c655915 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -421,8 +421,8 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind protected class GLLifecycleHook implements WindowImpl.LifecycleHook { @Override - public void setPreserveResourcesAtDestroy() { - GLWindow.this.setPreserveGLStateAtDestroy(true); + public void preserveGLStateAtDestroy() { + GLWindow.this.preserveGLStateAtDestroy(true); } @Override @@ -567,6 +567,9 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind setVisible(true); } } + + @Override + public final boolean isGLStatePreservationSupported() { return true; } //---------------------------------------------------------------------- // GLDrawable methods diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index e1636ffcd..e5dd783ca 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -231,7 +231,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * Notifies the receiver to preserve resources (GL, ..) * for the next destroy*() calls (only). */ - void setPreserveResourcesAtDestroy(); + void preserveGLStateAtDestroy(); /** * Invoked before Window destroy action, @@ -966,7 +966,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected void destroy(boolean preserveResources) { if( preserveResources && null != WindowImpl.this.lifecycleHook ) { - WindowImpl.this.lifecycleHook.setPreserveResourcesAtDestroy(); + WindowImpl.this.lifecycleHook.preserveGLStateAtDestroy(); } destroy(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java index da86c8741..300b4ec85 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java @@ -44,11 +44,11 @@ import jogamp.nativewindow.jawt.JAWTUtil; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.GLEventListenerState; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.GLEventListenerState; import org.junit.Assert; import org.junit.Assume; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java index 694b40214..2bba76ee7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java @@ -46,8 +46,8 @@ import javax.media.opengl.GLProfile; import com.jogamp.opengl.GLAutoDrawableDelegate; +import com.jogamp.opengl.GLEventListenerState; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.util.GLEventListenerState; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java index 269af714d..68f74a27a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java @@ -34,8 +34,8 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; +import com.jogamp.opengl.GLEventListenerState; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.util.GLEventListenerState; import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java index 129b2e80e..684208909 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java @@ -35,8 +35,8 @@ import javax.media.opengl.GLProfile; import jogamp.nativewindow.jawt.JAWTUtil; +import com.jogamp.opengl.GLEventListenerState; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.util.GLEventListenerState; import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java index 4f21d1626..87057f5a9 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java @@ -34,8 +34,8 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; +import com.jogamp.opengl.GLEventListenerState; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.util.GLEventListenerState; import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; -- cgit v1.2.3