diff options
Diffstat (limited to 'src/jogl')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java | 332 |
1 files changed, 191 insertions, 141 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java b/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java index 2914a1bf9..21dafecb1 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java +++ b/src/jogl/classes/com/jogamp/opengl/GLEventListenerState.java @@ -32,11 +32,9 @@ import java.util.List; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsDevice; 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; @@ -57,8 +55,8 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration; * <li>{@link GLContext}</li> * <li>All {@link GLEventListener}, incl. their init state</li> * <li>{@link GLAnimatorControl}</li> - * <li>{@link GLCapabilitiesImmutable} for compatibility check</li> - * <li>{@link AbstractGraphicsScreen} for compatibility check and preserving the {@link AbstractGraphicsDevice}</li> + * <!--li>{@link GLCapabilitiesImmutable} for compatibility check</li--> + * <li>{@link AbstractGraphicsDevice} for compatibility check and preserving the native device handle incl. ownership</li> * </ul> * <p> * A GLEventListenerState instance can be created while components are {@link #moveFrom(GLAutoDrawable) moved from} a {@link GLAutoDrawable} @@ -68,16 +66,16 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration; * A GLEventListenerState instance's components can be {@link #moveTo(GLAutoDrawable) moved to} a {@link GLAutoDrawable}, * while loosing {@link #isOwner() ownership} of the moved components. * </p> - * <p> */ public class GLEventListenerState { - private static final boolean DEBUG = Debug.debug("GLDrawable"); + private static final boolean DEBUG = Debug.debug("GLDrawable") || Debug.debug("GLEventListenerState"); - private GLEventListenerState(AbstractGraphicsScreen upstreamScreen, boolean proxyOwnsUpstreamDevice, AbstractGraphicsScreen screen, GLCapabilitiesImmutable caps, + private GLEventListenerState(AbstractGraphicsDevice upstreamDevice, boolean proxyOwnsUpstreamDevice, AbstractGraphicsDevice device, + GLCapabilitiesImmutable caps, GLContext context, int count, GLAnimatorControl anim, boolean animStarted) { - this.upstreamScreen = upstreamScreen; + this.upstreamDevice = upstreamDevice; this.proxyOwnsUpstreamDevice = proxyOwnsUpstreamDevice; - this.screen = screen; + this.device = device; this.caps = caps; this.context = context; this.listeners = new GLEventListener[count]; @@ -99,9 +97,9 @@ public class GLEventListenerState { public final int listenerCount() { return listeners.length; } - public final AbstractGraphicsScreen upstreamScreen; + public final AbstractGraphicsDevice upstreamDevice; public final boolean proxyOwnsUpstreamDevice; - public final AbstractGraphicsScreen screen; + public final AbstractGraphicsDevice device; public final GLCapabilitiesImmutable caps; public final GLContext context; public final GLEventListener[] listeners; @@ -121,14 +119,13 @@ public class GLEventListenerState { listeners[i] = null; } // context.destroy(); - NPE (null drawable) - screen.getDevice().close(); + device.close(); owner = false; } } - private static AbstractGraphicsScreen cloneScreen(AbstractGraphicsScreen aScreen) { - final AbstractGraphicsDevice aDevice2 = (AbstractGraphicsDevice) aScreen.getDevice().clone(); - return NativeWindowFactory.createScreen( aDevice2, aScreen.getIndex() ); + private static AbstractGraphicsDevice cloneDevice(AbstractGraphicsDevice aDevice) { + return (AbstractGraphicsDevice) aDevice.clone(); } /** @@ -152,51 +149,6 @@ public class GLEventListenerState { * @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); - aScreen1.getDevice().clearHandleOwner(); // don't close device handle - if( DEBUG ) { - System.err.println("GLEventListenerState.moveFrom.0a: orig 0x"+Integer.toHexString(aScreen1.getDevice().hashCode())+", "+aScreen1.getDevice()); - System.err.println("GLEventListenerState.moveFrom.0b: pres 0x"+Integer.toHexString(aScreen2.getDevice().hashCode())+", "+aScreen2.getDevice()); - System.err.println("GLEventListenerState.moveFrom.1: "+aSurface.getClass().getName()+", "+aSurface); - } - 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.2: "+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.3a: up-orig 0x"+Integer.toHexString(aUpScreen1.getDevice().hashCode())+", "+aUpScreen1.getDevice()); - System.err.println("GLEventListenerState.moveFrom.3b: up-pres 0x"+Integer.toHexString(_aUpScreen2.getDevice().hashCode())+", "+_aUpScreen2.getDevice()); - System.err.println("GLEventListenerState.moveFrom.3c: "+aSurface.getClass().getName()+", "+aSurface); - System.err.println("GLEventListenerState.moveFrom.3d: "+aUpSurface.getClass().getName()+", "+aUpSurface); - } - } - } else { - proxyOwnsUpstreamDevice = false; - } - aUpScreen2=_aUpScreen2; - } - final GLAnimatorControl aAnim = a.getAnimator(); final boolean aAnimStarted; if( null != aAnim ) { @@ -206,23 +158,75 @@ public class GLEventListenerState { 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<aSz; i++) { - final GLEventListener l = a.getGLEventListener(0); - glls.listenersInit[i] = a.getGLEventListenerInitState(l); - glls.listeners[i] = a.removeGLEventListener( l ); - } - - // - // trigger glFinish to sync GL ctx - // - a.invoke(true, glFinish); - - a.setContext( null, false ); + final GLEventListenerState glls; + final NativeSurface aSurface = a.getNativeSurface(); + final boolean surfaceLocked = false; // NativeSurface.LOCK_SURFACE_NOT_READY < aSurface.lockSurface(); + try { + 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 AbstractGraphicsConfiguration aCfg = aSurface.getGraphicsConfiguration(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities(); + final AbstractGraphicsDevice aDevice1 = aCfg.getScreen().getDevice(); + final AbstractGraphicsDevice aDevice2 = cloneDevice(aDevice1); + aDevice1.clearHandleOwner(); // don't close device handle + if( DEBUG ) { + System.err.println("GLEventListenerState.moveFrom.0a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1); + System.err.println("GLEventListenerState.moveFrom.0b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2); + System.err.println("GLEventListenerState.moveFrom.1: "+aSurface.getClass().getName()/*+", "+aSurface*/); + } + final AbstractGraphicsDevice aUpDevice2; + final boolean proxyOwnsUpstreamDevice; + { + AbstractGraphicsDevice _aUpDevice2 = 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.2: "+aUpSurface.getClass().getName()+", "+aUpSurface); + } + if(null != aUpSurface) { + final AbstractGraphicsDevice aUpDevice1 = aUpSurface.getGraphicsConfiguration().getScreen().getDevice(); + _aUpDevice2 = cloneDevice(aUpDevice1); + aUpDevice1.clearHandleOwner(); // don't close device handle + if(DEBUG) { + System.err.println("GLEventListenerState.moveFrom.3a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1); + System.err.println("GLEventListenerState.moveFrom.3b: up-pres 0x"+Integer.toHexString(_aUpDevice2.hashCode())+", "+_aUpDevice2); + System.err.println("GLEventListenerState.moveFrom.3c: "+aSurface.getClass().getName()+", "+aSurface); + System.err.println("GLEventListenerState.moveFrom.3d: "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString()); + } + } + } else { + proxyOwnsUpstreamDevice = false; + } + aUpDevice2 = _aUpDevice2; + } + + glls = new GLEventListenerState(aUpDevice2, proxyOwnsUpstreamDevice, aDevice2, caps, a.getContext(), aSz, aAnim, aAnimStarted); + + // + // remove and cache all GLEventListener and their init-state + // + for(int i=0; i<aSz; i++) { + final GLEventListener l = a.getGLEventListener(0); + glls.listenersInit[i] = a.getGLEventListenerInitState(l); + glls.listeners[i] = a.removeGLEventListener( l ); + } + + // + // trigger glFinish to sync GL ctx + // + a.invoke(true, glFinish); + + a.setContext( null, false ); + + } finally { + if( surfaceLocked ) { + aSurface.unlockSurface(); + } + } return glls; } @@ -241,84 +245,123 @@ public class GLEventListenerState { * * @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}. + * <!-- @throws GLException if the {@link GLAutoDrawable}'s configuration is incompatible, i.e. different {@link GLCapabilitiesImmutable}. --> + * @throws GLException if this preserved {@link AbstractGraphicsDevice} is incompatible w/ the given destination one. * * @see #moveFrom(GLAutoDrawable) * @see #isOwner() */ public final void moveTo(GLAutoDrawable a) { + final GLAnimatorControl aAnim = a.getAnimator(); + final boolean hasAnimator = null != aAnim; + final boolean aPaused; + if( hasAnimator ) { + aPaused = aAnim.pause(); + aAnim.remove(a); // also handles ECT + if( aPaused ) { + aAnim.resume(); + } + } else { + aPaused = false; + } + final List<GLRunnable> aGLCmds = new ArrayList<GLRunnable>(); 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 - { - final AbstractGraphicsScreen aScreen1 = aCfg.getScreen(); - if( DEBUG ) { - System.err.println("GLEventListenerState.moveTo.0a: orig 0x"+Integer.toHexString(aScreen1.getDevice().hashCode())+", "+aScreen1.getDevice()); - System.err.println("GLEventListenerState.moveTo.0b: pres 0x"+Integer.toHexString(screen.getDevice().hashCode())+", "+screen.getDevice()); + final boolean surfaceLocked = false; // NativeSurface.LOCK_SURFACE_NOT_READY < aSurface.lockSurface(); + final boolean aRealized; + try { + + 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); + } */ + final DefaultGraphicsDevice aDevice1 = (DefaultGraphicsDevice) aCfg.getScreen().getDevice(); + final DefaultGraphicsDevice aDevice2 = (DefaultGraphicsDevice) device; + if( !aDevice1.getUniqueID().equals( aDevice2.getUniqueID() ) ) { + throw new GLException("Incompatible devices: Preserved <"+aDevice2.getUniqueID()+">, target <"+aDevice1.getUniqueID()+">"); + } + + // collect optional upstream surface info + final ProxySurface aProxy; + final NativeSurface aUpSurface; + if(aSurface instanceof ProxySurface) { + aProxy = (ProxySurface)aSurface; + aUpSurface = aProxy.getUpstreamSurface(); + } else { + aProxy = null; + aUpSurface = null; } - aCfg.setScreen( screen ); - aScreen1.getDevice().close(); if( DEBUG ) { - System.err.println("GLEventListenerState.moveTo.1a: orig 0x"+Integer.toHexString(aScreen1.getDevice().hashCode())+", "+aScreen1.getDevice()); - System.err.println("GLEventListenerState.moveTo.1b: pres 0x"+Integer.toHexString(screen.getDevice().hashCode())+", "+screen.getDevice()); + System.err.println("GLEventListenerState.moveTo.0 : has aProxy "+(null!=aProxy)); + System.err.println("GLEventListenerState.moveTo.0 : has aUpSurface "+(null!=aUpSurface)); } - } - - // 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 ) { - final AbstractGraphicsScreen aUpScreen1 = aUpCfg.getScreen(); - if( DEBUG ) { - System.err.println("GLEventListenerState.moveTo.2a: up-orig 0x"+Integer.toHexString(aUpScreen1.getDevice().hashCode())+", "+aUpScreen1.getDevice()); - System.err.println("GLEventListenerState.moveTo.2b: up-pres 0x"+Integer.toHexString(upstreamScreen.getDevice().hashCode())+", "+upstreamScreen.getDevice()); - System.err.println("GLEventListenerState.moveTo.2c: "+aUpSurface.getClass().getName()+", "+aUpSurface+", "+aProxy.getUpstreamOptionBits(null).toString()); - } - aUpScreen1.getDevice().close(); - aUpCfg.setScreen( upstreamScreen ); - if( proxyOwnsUpstreamDevice ) { - aProxy.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); - } - upstreamSet = true; - if( DEBUG ) { - System.err.println("GLEventListenerState.moveTo.3a: up-orig 0x"+Integer.toHexString(aUpScreen1.getDevice().hashCode())+", "+aUpScreen1.getDevice()); - System.err.println("GLEventListenerState.moveTo.3b: up-pres 0x"+Integer.toHexString(upstreamScreen.getDevice().hashCode())+", "+upstreamScreen.getDevice()); - System.err.println("GLEventListenerState.moveTo.3c: "+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( null==aUpSurface && null != upstreamDevice ) { + throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = true, New-Holder = false"); + } + + // Destroy and remove currently associated GLContext, if any (will be replaced) + a.setContext( null, true ); + aRealized = a.isRealized(); + if( aRealized && null != aUpSurface ) { + // Unrealize due to device dependencies of an upstream surface, e.g. EGLUpstreamSurfaceHook + a.getDelegatedDrawable().setRealized(false); + } + + // Set new Screen and close previous one + { + if( DEBUG ) { + System.err.println("GLEventListenerState.moveTo.0a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1); + System.err.println("GLEventListenerState.moveTo.0b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2); + } + DefaultGraphicsDevice.swapDeviceHandleAndOwnership(aDevice1, aDevice2); + aDevice2.close(); + if( DEBUG ) { + System.err.println("GLEventListenerState.moveTo.1a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1); + System.err.println("GLEventListenerState.moveTo.1b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2); + } + } + + // If using a ProxySurface w/ an upstream surface, set new Screen and close previous one on it + if( null != aUpSurface ) { + final MutableGraphicsConfiguration aUpCfg = (MutableGraphicsConfiguration) aUpSurface.getGraphicsConfiguration(); + if( null != upstreamDevice ) { + final DefaultGraphicsDevice aUpDevice1 = (DefaultGraphicsDevice) aUpCfg.getScreen().getDevice(); + final DefaultGraphicsDevice aUpDevice2 = (DefaultGraphicsDevice)upstreamDevice; + if( !aUpDevice1.getUniqueID().equals( aUpDevice2.getUniqueID() ) ) { + throw new GLException("Incompatible updtream devices: Preserved <"+aUpDevice2.getUniqueID()+">, target <"+aUpDevice1.getUniqueID()+">"); + } + if( DEBUG ) { + System.err.println("GLEventListenerState.moveTo.2a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1); + System.err.println("GLEventListenerState.moveTo.2b: up-pres 0x"+Integer.toHexString(aUpDevice2.hashCode())+", "+aUpDevice2); + System.err.println("GLEventListenerState.moveTo.2c: "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString()); + } + DefaultGraphicsDevice.swapDeviceHandleAndOwnership(aUpDevice1, aUpDevice2); + aUpDevice2.close(); + if( proxyOwnsUpstreamDevice ) { + aProxy.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + if( DEBUG ) { + System.err.println("GLEventListenerState.moveTo.3a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1); + System.err.println("GLEventListenerState.moveTo.3b: up-pres 0x"+Integer.toHexString(aUpDevice2.hashCode())+", "+aUpDevice2); + System.err.println("GLEventListenerState.moveTo.3c: "+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 && null != aUpSurface ) { + a.getDelegatedDrawable().setRealized(true); + } + if( DEBUG ) { + System.err.println("GLEventListenerState.moveTo.X : has aProxy "+(null!=aProxy)); + System.err.println("GLEventListenerState.moveTo.X : has aUpSurface "+(null!=aUpSurface)); } - } - - if( aRealized ) { - a.setRealized(true); - } - final boolean surfaceLocked = false; // NativeSurface.LOCK_SURFACE_NOT_READY < aSurface.lockSurface(); - try { a.setContext( context, false ); } finally { if( surfaceLocked ) { @@ -347,7 +390,14 @@ public class GLEventListenerState { listeners[i] = null; } - if( null != anim && null == a.getAnimator() ) { + if( hasAnimator ) { + // prefer already bound animator + aAnim.add(a); + if( aPaused ) { + aAnim.resume(); + } + } else if ( null != anim ) { + // use previously bound animator anim.add(a); // also handles ECT if(animStarted) { anim.start(); |