diff options
author | Sven Gothel <[email protected]> | 2013-04-23 07:53:31 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-04-23 07:53:31 +0200 |
commit | 0f7412855c118cb501d8a001df7a7487354b5029 (patch) | |
tree | 13da9cd0d86bb37aedbad199811700f1de87ef04 | |
parent | 03a3f209aff955410e0f3133e73078529c23d3e1 (diff) |
Fix Bug 722: Make GLEventListenerState 'transaction' safe Animator.pause[ surface.lock[ modify ] ]
GLEventListenerState:
New model for GLEventListenerState's transaction safety:
- Z Decorate-1: Animator.pause [ X ] Animator.resume
- X Decorate-2: Surface.lock [ Y ] Surface.unlock
- Instead of setting AbstractGraphicsDevice, just swap the handle and ownership.
- Issuing setRealized(..) only if required, i.e. having an upstream-surface (EGL..) depending on used device
- Utilizing setRealized(..) on the GLAD's delegated 'real' drawable, avoiding optional GLAD locking.
- Cleanup and above changes shall render impl. easier to read.
GLEventListenerState Unit Tests:
- If swapping/moving from AWT -> NEWT, use a NEWT dedicated Display
avoiding ATI driver XCB crash - read comment.
11 files changed, 485 insertions, 190 deletions
diff --git a/make/build-test.xml b/make/build-test.xml index 3d9c31d83..e00348c38 100644 --- a/make/build-test.xml +++ b/make/build-test.xml @@ -437,6 +437,7 @@ <fileset dir="${classes}"> <include name="${java.dir.junit}/**/newt/**/Test*AWT*"/> <!--include name="${java.dir.junit}/**/newt/**/TestNewtEventModifiers*AWT*"/--> + <!--include name="${java.dir.junit}/**/acore/glels/Test**"/--> <exclude name="**/*$$*"/> </fileset> <formatter usefile="false" type="brief"/> diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 75e5f7fd6..65e070a99 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -115,6 +115,7 @@ function jrun() { #D_ARGS="-Djogl.debug.EGLDisplayUtil -Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLCanvas" #D_ARGS="-Djogl.debug.GLDrawable" + #D_ARGS="-Djogl.debug.GLEventListenerState" #D_ARGS="-Djogl.fbo.force.none" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" #D_ARGS="-Djogl.debug=all" @@ -362,8 +363,9 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch10NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch11NewtAWT $* -#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch12AWT $* -##testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch21Newt2AWT $* +testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch12AWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch21Newt2AWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestBug722GLContextDrawableSwitchNewt2AWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT @@ -379,7 +381,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindowInvisiblePointer01NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT #testnoawt com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle02NEWT -testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode00NEWT $* +#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode00NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode00bNEWT #testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01NEWT #testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode01bNEWT 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(); diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java index 63200b393..fb6d39b2f 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java @@ -120,6 +120,15 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl public void clearHandleOwner() { eglLifecycleCallback = null; } - + @Override + protected Object getHandleOwnership() { + return eglLifecycleCallback; + } + @Override + protected Object setHandleOwnership(Object newOwnership) { + final EGLDisplayLifecycleCallback oldOwnership = eglLifecycleCallback; + eglLifecycleCallback = (EGLDisplayLifecycleCallback) newOwnership; + return oldOwnership; + } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java index da3b31de4..e630e012e 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java @@ -162,4 +162,14 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl public void clearHandleOwner() { handleOwner = false; } + @Override + protected Object getHandleOwnership() { + return Boolean.valueOf(handleOwner); + } + @Override + protected Object setHandleOwnership(Object newOwnership) { + final Boolean oldOwnership = Boolean.valueOf(handleOwner); + handleOwner = ((Boolean) newOwnership).booleanValue(); + return oldOwnership; + } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index b3ae4628c..66b81d7fa 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -185,6 +185,42 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } /** + * Set the native handle of the underlying native device + * and return the previous one. + */ + protected final long setHandle(long newHandle) { + final long oldHandle = handle; + handle = newHandle; + return oldHandle; + } + + protected Object getHandleOwnership() { + return null; + } + protected Object setHandleOwnership(Object newOwnership) { + return null; + } + + public static final void swapDeviceHandleAndOwnership(final DefaultGraphicsDevice aDevice1, final DefaultGraphicsDevice aDevice2) { + aDevice1.lock(); + try { + aDevice2.lock(); + try { + final long aDevice1Handle = aDevice1.getHandle(); + final long aDevice2Handle = aDevice2.setHandle(aDevice1Handle); + aDevice1.setHandle(aDevice2Handle); + final Object aOwnership1 = aDevice1.getHandleOwnership(); + final Object aOwnership2 = aDevice2.setHandleOwnership(aOwnership1); + aDevice1.setHandleOwnership(aOwnership2); + } finally { + aDevice2.unlock(); + } + } finally { + aDevice1.unlock(); + } + } + + /** * Set the internal ToolkitLock, which is used within the * {@link #lock()} and {@link #unlock()} implementation. * @@ -194,8 +230,9 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice * </p> * * @param locker the ToolkitLock, if null, {@link jogamp.nativewindow.NullToolkitLock} is being used + * @return the previous ToolkitLock instance */ - protected void setToolkitLock(ToolkitLock locker) { + protected ToolkitLock setToolkitLock(ToolkitLock locker) { final ToolkitLock _toolkitLock = toolkitLock; _toolkitLock.lock(); try { @@ -203,6 +240,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } finally { _toolkitLock.unlock(); } + return _toolkitLock; } /** 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 300b4ec85..905cbcf25 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 @@ -42,6 +42,7 @@ import javax.media.opengl.awt.GLCanvas; import jogamp.nativewindow.jawt.JAWTUtil; +import com.jogamp.newt.Screen; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.GLEventListenerState; @@ -150,11 +151,12 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { return true; } - protected void testGLADOneLifecycle(GLCapabilities caps, GLADType gladType, int width, int height, - GLEventListenerCounter glelTracker, SnapshotGLEventListener snapshotGLEventListener, - GLEventListenerState glelsIn, GLEventListenerState glelsOut[], GLAnimatorControl animator) + protected void testGLADOneLifecycle(Screen screen, GLCapabilities caps, GLADType gladType, int width, + int height, GLEventListenerCounter glelTracker, + SnapshotGLEventListener snapshotGLEventListener, final GLEventListenerState glelsIn, final GLEventListenerState glelsOut[], GLAnimatorControl animator) throws InterruptedException { + System.err.println("GLAD Lifecycle.0 "+gladType+", restoring "+((null!=glelsIn)?true:false)+", preserving "+((null!=glelsOut)?true:false)); final Frame frame; final GLAutoDrawable glad; if( GLADType.GLCanvasOnscreen == gladType ) { @@ -179,7 +181,11 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { } else if( GLADType.GLWindow == gladType ) { frame = null; - glad = GLWindow.create(caps); + if( null != screen ) { + glad = GLWindow.create(screen, caps); + } else { + glad = GLWindow.create(caps); + } ((GLWindow)glad).setTitle("Newt GLWindow"); ((GLWindow)glad).setSize(width, height); } else if( GLADType.GLOffscreen == gladType ) { @@ -212,7 +218,9 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { if( null != glelsIn ) { Assert.assertEquals(0, glad.getGLEventListenerCount()); - glelsIn.moveTo(glad); + System.err.println(".. restoring.0"); + glelsIn.moveTo(glad); + System.err.println(".. restoring.X"); Assert.assertEquals(1, glelTracker.initCount); Assert.assertTrue(1 <= glelTracker.reshapeCount); @@ -227,6 +235,12 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { Assert.assertEquals(false, glelsIn.isOwner()); } + for (int wait=0; wait<AWTRobotUtil.POLL_DIVIDER && + ( 1 > glelTracker.initCount || 1 > glelTracker.reshapeCount || 1 > glelTracker.displayCount ); + wait++) { + Thread.sleep(AWTRobotUtil.TIME_SLICE); + } + final long t0 = System.currentTimeMillis(); long t1 = t0; @@ -242,17 +256,17 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { if( null != glelsOut ) { final GLContext context1 = glad.getContext(); - final GLEventListenerState _gllsOut = GLEventListenerState.moveFrom(glad); + System.err.println(".. preserving.0"); + glelsOut[0] = GLEventListenerState.moveFrom(glad); + System.err.println(".. preserving.X"); - Assert.assertEquals(context1, _gllsOut.context); + Assert.assertEquals(context1, glelsOut[0].context); Assert.assertNull(context1.getGLReadDrawable()); Assert.assertNull(context1.getGLDrawable()); - Assert.assertEquals(3, _gllsOut.listenerCount()); - Assert.assertEquals(true, _gllsOut.isOwner()); + Assert.assertEquals(3, glelsOut[0].listenerCount()); + Assert.assertEquals(true, glelsOut[0].isOwner()); Assert.assertEquals(null, glad.getContext()); Assert.assertEquals(0, glad.getGLEventListenerCount()); - - glelsOut[0] = _gllsOut; } if( GLADType.GLCanvasOnscreen == gladType || GLADType.GLCanvasOffscreen == gladType ) { destroyFrame(frame); @@ -272,5 +286,6 @@ public abstract class GLContextDrawableSwitchBase extends UITestCase { } else { Assert.assertEquals(1, glelTracker.disposeCount); } + System.err.println("GLAD Lifecycle.X "+gladType); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java new file mode 100644 index 000000000..a11978784 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestBug722GLContextDrawableSwitchNewt2AWT.java @@ -0,0 +1,143 @@ +/** + * 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.test.junit.jogl.acore.glels; + +import java.io.IOException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + + +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.GLRendererQuirks; +import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; +import com.jogamp.opengl.test.junit.util.MiscUtils; + +import org.junit.Test; + +/** + * Tests Bug 722 + * <p> + * See Bug 722 - https://jogamp.org/bugzilla/show_bug.cgi?id=722. + * </p> + */ +public class TestBug722GLContextDrawableSwitchNewt2AWT extends GLContextDrawableSwitchBase { + + static int loops = 10; + static long duration2 = 100; // ms + + /** + * Interesting artifact w/ ATI proprietary driver is that the + * bug causing the quirk {@link GLRendererQuirks#DontCloseX11Display} + * also causes an XCB crash when reusing the X11 display connection + * from AWT -> NEWT. Pre-allocating the X11 Display and keeping it referenced + * to avoid such re-usage worksaround this problem. + */ + public static boolean fixedNewtDisplay = true; + + @Test(timeout=3000000) + public void test11GLWindow2GLCanvasOnScrnGL2ES2() throws InterruptedException { + final GLCapabilities caps = getCaps(GLProfile.GL2ES2); + if(null == caps) return; + + GLADType gladType1 = GLADType.GLWindow; + GLADType gladType2 = GLADType.GLCanvasOnscreen; + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + final Animator animator = new Animator(); + animator.start(); + + final Display dpy; + final Screen screen; + if( fixedNewtDisplay ) { + dpy = NewtFactory.createDisplay(null); + screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + } else { + dpy = null; + screen = null; + } + + duration = duration2; + + for(int i=0; i<loops; i++) { + final GLEventListenerState glels[] = new GLEventListenerState[1]; + final GLEventListenerCounter glelTracker = new GLEventListenerCounter(); + + // - create glad1 w/o context + // - create context using glad1 and assign it to glad1 + { + System.err.println("Test "+i+"/"+loops+".1: GLAD-1 "+gladType1+", preserving."); + testGLADOneLifecycle(screen, caps, gladType1, width, height, + glelTracker, snapshotGLEventListener, + null, + glels, animator); + System.err.println("Test "+i+"/"+loops+".1: done"); + } + + // - create glad2 w/ survived context + { + System.err.println("Test "+i+"/"+loops+".2: GLAD-1 "+gladType2+", restoring."); + testGLADOneLifecycle(screen, caps, gladType2, width+100, height+100, + glelTracker, snapshotGLEventListener, + glels[0], + null, null); + System.err.println("Test "+i+"/"+loops+".2: done."); + } + } + animator.stop(); + + if( fixedNewtDisplay ) { + screen.removeReference(); + } + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration2 = MiscUtils.atol(args[i], duration2); + } else if(args[i].equals("-loops")) { + i++; + loops = MiscUtils.atoi(args[i], loops); + } else if(args[i].equals("-noFixedNewtDisplay")) { + fixedNewtDisplay = false; + } + } + /** + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + System.err.println(stdin.readLine()); */ + org.junit.runner.JUnitCore.main(TestBug722GLContextDrawableSwitchNewt2AWT.class.getName()); + } +} 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 68f74a27a..a3f3ffbee 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 @@ -84,18 +84,18 @@ public class TestGLContextDrawableSwitch11NewtAWT extends GLContextDrawableSwitc // - create glad1 w/o context // - create context using glad1 and assign it to glad1 { - testGLADOneLifecycle(caps, GLADType.GLWindow, width, height, - glelTracker, snapshotGLEventListener, - null, - glels, animator); + testGLADOneLifecycle(null, caps, GLADType.GLWindow, width, + height, glelTracker, + snapshotGLEventListener, + null, glels, animator); } // - create glad2 w/ survived context { - testGLADOneLifecycle(caps, GLADType.GLWindow, width+100, height+100, - glelTracker, snapshotGLEventListener, - glels[0], - null, null); + testGLADOneLifecycle(null, caps, GLADType.GLWindow, width+100, + height+100, glelTracker, + snapshotGLEventListener, + glels[0], null, null); } animator.stop(); } 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 684208909..95e895d44 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 @@ -110,18 +110,18 @@ public class TestGLContextDrawableSwitch12AWT extends GLContextDrawableSwitchBas // - create glad1 w/o context // - create context using glad1 and assign it to glad1 { - testGLADOneLifecycle(caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width, height, - glelTracker, snapshotGLEventListener, - null, - glels, animator); + testGLADOneLifecycle(null, caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width, + height, glelTracker, + snapshotGLEventListener, + null, glels, animator); } // - create glad2 w/ survived context { - testGLADOneLifecycle(caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width+100, height+100, - glelTracker, snapshotGLEventListener, - glels[0], - null, null); + testGLADOneLifecycle(null, caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width+100, + height+100, glelTracker, + snapshotGLEventListener, + glels[0], null, null); } animator.stop(); } 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 87057f5a9..d337570ec 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,7 +34,11 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; import com.jogamp.opengl.GLEventListenerState; +import com.jogamp.opengl.GLRendererQuirks; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.util.GLEventListenerCounter; @@ -58,6 +62,13 @@ import org.junit.Test; * <p> * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665. * </p> + * <p> + * Interesting artifact w/ ATI proprietary driver is that the + * bug causing the quirk {@link GLRendererQuirks#DontCloseX11Display} + * also causes an XCB crash when reusing the X11 display connection + * from AWT -> NEWT. Pre-allocating the X11 Display and keeping it referenced + * to avoid such re-usage worksaround this problem. + * </p> */ public class TestGLContextDrawableSwitch21Newt2AWT extends GLContextDrawableSwitchBase { @@ -65,59 +76,75 @@ public class TestGLContextDrawableSwitch21Newt2AWT extends GLContextDrawableSwit public void test01GLCanvasOnScrn2GLWindowGL2ES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow); + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow); } @Test(timeout=30000) public void test02GLCanvasOnScrn2GLWindowGLES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow); + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow); } @Test(timeout=30000) public void test11GLWindow2GLCanvasOnScrnGL2ES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen); + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen); + screen.removeReference(); } @Test(timeout=30000) public void test12GLWindow2GLCanvasOnScrnGLES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen); + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen); + screen.removeReference(); } @Test(timeout=30000) public void test21GLCanvasOffScrn2GLWindowGL2ES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow); + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow); } @Test(timeout=30000) public void test22GLCanvasOffScrn2GLWindowGLES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow); + testGLCanvas2GLWindowImpl(null, reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow); } @Test(timeout=30000) public void test31GLWindow2GLCanvasOffScrnGL2ES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen); + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen); + screen.removeReference(); } @Test(timeout=30000) public void test32GLWindow2GLCanvasOffScrnGLES2() throws InterruptedException { final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); if(null == reqGLCaps) return; - testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen); + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + testGLCanvas2GLWindowImpl(screen, reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen); + screen.removeReference(); } - private void testGLCanvas2GLWindowImpl(GLCapabilities caps, GLADType gladType1, GLADType gladType2) throws InterruptedException { + private void testGLCanvas2GLWindowImpl(Screen screen, GLCapabilities caps, GLADType gladType1, GLADType gladType2) throws InterruptedException { if( !validateOnOffscreenLayer(gladType1, gladType2) ) { return; } @@ -131,18 +158,18 @@ public class TestGLContextDrawableSwitch21Newt2AWT extends GLContextDrawableSwit // - create glad1 w/o context // - create context using glad1 and assign it to glad1 { - testGLADOneLifecycle(caps, gladType1, width, height, - glelTracker, snapshotGLEventListener, - null, - glels, animator); + testGLADOneLifecycle(screen, caps, gladType1, width, + height, glelTracker, + snapshotGLEventListener, + null, glels, animator); } // - create glad2 w/ survived context { - testGLADOneLifecycle(caps, gladType2, width+100, height+100, - glelTracker, snapshotGLEventListener, - glels[0], - null, null); + testGLADOneLifecycle(screen, caps, gladType2, width+100, + height+100, glelTracker, + snapshotGLEventListener, + glels[0], null, null); } animator.stop(); } |