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:
+ *
+ * - {@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, 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