From b738983638703bb721ee4c9820c8ef43e2252e73 Mon Sep 17 00:00:00 2001
From: Sven Gothel
- * If the old or new context was current on this thread, it is being released before switching the drawable.
+ * The current context will be dis-associated from this auto-drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) setGLDrawable(null, true);} first.
+ *
+ * The new context will be associated with this auto-drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
+ *
+ * If the old or new context was current on this thread, it is being released before switching the association.
* The new context will be made current afterwards, if it was current before.
* However the user shall take extra care that no other thread
* attempts to make this context current.
*
- * Be aware that the old context is still bound to the drawable,
- * and that one context can only be bound to one drawable at one time!
- *
* In case you do not intend to use the old context anymore, i.e.
- * not assigning it to another drawable, it shall be
- * destroyed before setting the new context, i.e.:
+ * not assigning it to another drawable, it shall be
+ * destroyed, i.e.:
* drawable
yet,
+ * may be
might be an inner GLDrawable instance if using a delegation pattern,
- * or this GLAutoDrawable instance.
+ * Associate the new context, null
for lazy initialization
* @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
* @param ownDevice pass true
if {@link AbstractGraphicsDevice#close()} shall be issued,
* otherwise pass false
. Closing the device is required in case
@@ -78,9 +81,6 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAuto
if(null == drawable) {
throw new IllegalArgumentException("null drawable");
}
- if(null == context) {
- throw new IllegalArgumentException("null context");
- }
if(!drawable.isRealized()) {
throw new IllegalArgumentException("drawable not realized");
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
index cc81e4820..c03e4bfa4 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
@@ -27,17 +27,14 @@
*/
package com.jogamp.opengl.util;
-import java.util.ArrayList;
-import java.util.List;
-
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLRunnable;
import jogamp.opengl.Debug;
+import jogamp.opengl.GLEventListenerState;
/**
* Providing utility functions dealing w/ {@link GLDrawable}s, {@link GLAutoDrawable} and their {@link GLEventListener}.
@@ -83,7 +80,7 @@ public class GLDrawableUtil {
dest.addGLEventListener(listener);
if(preserveInitState && initialized) {
dest.setGLEventListenerInitState(listener, true);
- dest.invoke(false, new ReshapeGLEventListener(listener));
+ dest.invoke(false, new GLEventListenerState.ReshapeGLEventListener(listener));
} // else .. !init state is default
}
@@ -121,108 +118,13 @@ public class GLDrawableUtil {
* @param b
*/
public static final void swapGLContextAndAllGLEventListener(GLAutoDrawable a, GLAutoDrawable b) {
- final ListnewtCtx
, to this auto-drawable.
*
- GLContext oldCtx = glad.getContext();
+ GLContext oldCtx = glad.setContext(newCtx);
if(null != oldCtx) {
oldCtx.destroy();
}
- glad.setContext(newCtx);
*
- * This is required, since a context must have a valid drawable at all times
- * and this API shall not restrict the user in any way.
*
null
+ * @param newCtx the new context, maybe null
for dis-association.
+ * @return the previous GLContext, maybe null
*
* @see GLContext#setGLDrawable(GLDrawable, boolean)
* @see GLContext#setGLReadDrawable(GLDrawable)
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 455f2d70d..4817add4d 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -217,15 +217,20 @@ public abstract class GLContext {
/**
* Sets the read/write drawable for framebuffer operations.
* + * If the arguments reflect the current state of this context + * this method is a no-operation and returns the old and current {@link GLDrawable}. + *
+ ** If the context was current on this thread, it is being released before switching the drawable * and made current afterwards. However the user shall take extra care that not other thread * attempts to make this context current. Otherwise a race condition may happen. *
- * @param readWrite the read/write drawable for framebuffer operations. - * @param setWriteOnly iftrue
and if the current read-drawable differs
- * from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}),
- * only change the write-drawable. Otherwise set both drawables.
- * @return the replaced read/write drawable
+ * @param readWrite The read/write drawable for framebuffer operations, maybe null
to remove association.
+ * @param setWriteOnly Only change the write-drawable, if setWriteOnly
is true
and
+ * if the {@link #getGLReadDrawable() read-drawable} differs
+ * from the {@link #getGLDrawable() write-drawable}.
+ * Otherwise set both drawables, read and write.
+ * @return The previous read/write drawable
*
* @throws GLException in case null
is being passed or
* this context is made current on another thread.
@@ -239,6 +244,12 @@ public abstract class GLContext {
/**
* Returns the write-drawable this context uses for framebuffer operations.
+ * + * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)}, + * it equals to the write-drawable (default). + *
+ * @see #setGLDrawable(GLDrawable, boolean) + * @see #setGLReadDrawable(GLDrawable) */ public abstract GLDrawable getGLDrawable(); @@ -259,7 +270,7 @@ public abstract class GLContext { * * @param read the read-drawable for read framebuffer operations. * If null is passed, the default write drawable will be set. - * @return the replaced read-drawable + * @return the previous read-drawable * * @throws GLException in case a read drawable is not supported or * this context is made current on another thread. diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index eadd59559..c20197e72 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -74,8 +74,12 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking /** - * @param drawable upstream {@link GLDrawableImpl} instance, may be null for lazy initialization - * @param context upstream {@link GLContextImpl} instance, may be null for lazy initialization + * @param drawable upstream {@link GLDrawableImpl} instance, + * may benull
for lazy initialization
+ * @param context upstream {@link GLContextImpl} instance,
+ * may not have been made current (created) yet,
+ * may not be associated w/ drawable yet,
+ * may be null
for lazy initialization
* @param ownsDevice pass true
if {@link AbstractGraphicsDevice#close()} shall be issued,
* otherwise pass false
. Closing the device is required in case
* the drawable is created w/ it's own new instance, e.g. offscreen drawables,
@@ -85,6 +89,9 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
this.drawable = drawable;
this.context = context;
this.ownsDevice = ownsDevice;
+ if(null != context && null != drawable) {
+ context.setGLDrawable(drawable, false);
+ }
resetFPSCounter();
}
@@ -326,7 +333,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
final GLContext oldCtx = context;
final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
+ if(newCtxCurrent) { // implies null != newCtx
context.makeCurrent();
}
return oldCtx;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index f2c2cfada..2a2b6a8fd 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -203,8 +203,8 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly) {
- if(null==readWrite) {
- throw new GLException("Null read/write drawable not allowed");
+ if( drawable == readWrite && ( setWriteOnly || drawableRead == readWrite ) ) {
+ return drawable; // no change.
}
final boolean lockHeld = lock.isOwner(Thread.currentThread());
if(lockHeld) {
@@ -212,16 +212,20 @@ public abstract class GLContextImpl extends GLContext {
} else if(lock.isLockedByOtherThread()) { // still could glitch ..
throw new GLException("GLContext current by other thread ("+lock.getOwner()+"), operation not allowed.");
}
- if(!setWriteOnly || drawableRead==drawable) { // if !setWriteOnly || !explicitReadDrawable
+ if( !setWriteOnly || drawableRead == drawable ) { // if !setWriteOnly || !explicitReadDrawable
drawableRead = (GLDrawableImpl) readWrite;
}
final GLDrawableImpl old = drawable;
- old.associateContext(this, false);
- drawableRetargeted = null != drawable;
+ if( null != old ) {
+ old.associateContext(this, false);
+ }
+ drawableRetargeted |= null != drawable && readWrite != drawable;
drawable = (GLDrawableImpl) readWrite ;
- drawable.associateContext(this, true);
- if(lockHeld) {
- makeCurrent();
+ if( null != drawable ) {
+ drawable.associateContext(this, true);
+ if( lockHeld ) {
+ makeCurrent();
+ }
}
return old;
}
@@ -334,7 +338,7 @@ public abstract class GLContextImpl extends GLContext {
", surf "+toHexString(drawable.getHandle())+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
if (contextHandle != 0) {
- int lockRes = drawable.lockSurface();
+ final int lockRes = drawable.lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
// this would be odd ..
throw new GLException("Surface not ready to lock: "+drawable);
@@ -408,7 +412,7 @@ public abstract class GLContextImpl extends GLContext {
throw new GLException("Destination OpenGL context has not been created");
}
- int lockRes = drawable.lockSurface();
+ final int lockRes = drawable.lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
// this would be odd ..
throw new GLException("Surface not ready to lock");
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index f8c58ee34..5d113ff83 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -131,30 +131,36 @@ public class GLDrawableHelper {
}
/**
- * Associate a new context to the drawable and also propagates the context/drawable switch by
- * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
- *
- * If the old or new context was current on this thread, it is being released before switching the drawable.
+ * Switch {@link GLContext} / {@link GLDrawable} association.
+ *
+ * Dis-associate oldCtx
from drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) oldCtx.setGLDrawable(null, true);}.
*
*
- * Be aware that the old context is still bound to the drawable,
- * and that one context can only bound to one drawable at one time!
+ * Re-associate newCtx
with drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
+ *
+ *
+ * If the old or new context was current on this thread, it is being released before switching the drawable.
*
*
* No locking is being performed on the drawable, caller is required to take care of it.
*
*
* @param drawable the drawable which context is changed
- * @param oldCtx the old context
- * @param newCtx the new context
+ * @param oldCtx the old context, maybe null
.
+ * @param newCtx the new context, maybe null
for dis-association.
* @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)}
* @return true if the new context was current, otherwise false
*
* @see GLAutoDrawable#setContext(GLContext)
*/
public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) {
- if( null != oldCtx && oldCtx.isCurrent() ) {
- oldCtx.release();
+ if( null != oldCtx ) {
+ if( oldCtx.isCurrent() ) {
+ oldCtx.release();
+ }
+ oldCtx.setGLDrawable(null, true); // dis-associate old pair
}
final boolean newCtxCurrent;
if(null!=newCtx) {
@@ -163,8 +169,8 @@ public class GLDrawableHelper {
newCtx.release();
}
newCtx.setContextCreationFlags(newCtxCreationFlags);
- newCtx.setGLDrawable(drawable, true); // propagate context/drawable switch
- } else {
+ newCtx.setGLDrawable(drawable, true); // re-associate new pair
+ } else {
newCtxCurrent = false;
}
return newCtxCurrent;
@@ -203,6 +209,7 @@ public class GLDrawableHelper {
}
context.getGL().glFinish();
context.release();
+ context.setGLDrawable(null, true); // dis-associate
}
if(null != proxySurface) {
diff --git a/src/jogl/classes/jogamp/opengl/GLEventListenerState.java b/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
new file mode 100644
index 000000000..dea2bc85b
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
@@ -0,0 +1,267 @@
+/**
+ * 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 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.NativeWindowFactory;
+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 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 AbstractGraphicsScreen}
+ * - {@link GLCapabilitiesImmutable}
+ * - {@link GLContext} operating all {@link GLEventListener}
+ * - All {@link GLEventListener}
+ * - All {@link GLEventListener}'s init state
+ * - {@link GLAnimatorControl}
+ *
+ *
+ * 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 GLEventListenerState(AbstractGraphicsScreen screen, GLCapabilitiesImmutable caps, GLContext context, int count, GLAnimatorControl anim) {
+ 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 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 AbstractGraphicsConfiguration aCfg1 = a.getNativeSurface().getGraphicsConfiguration();
+ final GLCapabilitiesImmutable caps1 = (GLCapabilitiesImmutable) aCfg1.getChosenCapabilities();
+ final AbstractGraphicsScreen aScreen1 = aCfg1.getScreen();
+ final AbstractGraphicsDevice aDevice1 = aScreen1.getDevice();
+ final AbstractGraphicsDevice aDevice2 = (AbstractGraphicsDevice) aDevice1.clone();
+ final AbstractGraphicsScreen aScreen2 = NativeWindowFactory.createScreen( NativeWindowFactory.getNativeWindowType(false), aDevice2, aScreen1.getIndex() );
+
+ final GLAnimatorControl aAnim = a.getAnimator();
+ if( null != aAnim ) {
+ aAnim.remove(a); // also handles ECT
+ }
+
+ final GLEventListenerState glls = new GLEventListenerState(aScreen2, caps1, 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 MutableGraphicsConfiguration aCfg = (MutableGraphicsConfiguration) a.getNativeSurface().getGraphicsConfiguration();
+ final GLCapabilitiesImmutable aCaps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities();
+ if( caps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) != aCaps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) ) {
+ throw new GLException("XXX: Incompatible - Prev Holder: "+caps+", New Holder "+caps);
+ }
+ final GLContext prevContext = a.getContext();
+ if( null != prevContext) {
+ prevContext.destroy();
+ }
+ final AbstractGraphicsScreen preScreen = aCfg.getScreen();
+ aCfg.setScreen( screen );
+ preScreen.getDevice().close();
+ a.setContext( context );
+ owner = false;
+
+ //
+ // Trigger GL-Viewport reset and reshape of all initialized GLEventListeners
+ //
+ aGLCmds.add(setViewport);
+ for(int i=0; i= 0 is specific screen
* @return
- * @throws UnsupportedOperationException
*/
- public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) throws UnsupportedOperationException {
- if( isX11 ) {
- X11GraphicsDevice x11Device = (X11GraphicsDevice)device;
- if(0 > screen) {
- screen = x11Device.getDefaultScreen();
- }
- return new X11GraphicsScreen(x11Device, screen);
- }
- if(0 > screen) {
- screen = 0; // FIXME: Needs native API utilization
- }
- if( isWindows || isOSX ) {
- return new DefaultGraphicsScreen(device, screen);
- }
- throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
+ public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) {
+ return NativeWindowFactory.createScreen(nwt, device, screen);
}
public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) {
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
index 0f28ca67c..da3b31de4 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
@@ -45,7 +45,7 @@ import javax.media.nativewindow.ToolkitLock;
*/
public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
- final boolean handleOwner;
+ /* final */ boolean handleOwner;
final boolean isXineramaEnabled;
/** Constructs a new X11GraphicsDevice corresponding to the given connection and default
@@ -153,5 +153,13 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
}
return super.close();
}
+
+ @Override
+ public boolean isHandleOwner() {
+ return handleOwner;
+ }
+ @Override
+ public void clearHandleOwner() {
+ handleOwner = false;
+ }
}
-
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
index ebdaf2fbb..4e45113d4 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
@@ -42,8 +42,9 @@ package javax.media.nativewindow;
/** A marker interface describing a graphics configuration, visual, or
pixel format in a toolkit-independent manner. */
-
public interface AbstractGraphicsConfiguration extends VisualIDHolder, Cloneable {
+ public Object clone();
+
/**
* Return the screen this graphics configuration is valid for
*/
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
index 8ecd5242d..585cd1f09 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
@@ -45,7 +45,6 @@ import jogamp.nativewindow.Debug;
/** A interface describing a graphics device in a
toolkit-independent manner.
*/
-
public interface AbstractGraphicsDevice extends Cloneable {
public static final boolean DEBUG = Debug.debug("GraphicsDevice");
@@ -58,6 +57,8 @@ public interface AbstractGraphicsDevice extends Cloneable {
/** Default unit id for the 1st device: 0 */
public static int DEFAULT_UNIT = 0;
+ public Object clone();
+
/**
* Returns the type of the underlying subsystem, ie
* NativeWindowFactory.TYPE_KD, NativeWindowFactory.TYPE_X11, ..
@@ -143,10 +144,17 @@ public interface AbstractGraphicsDevice extends Cloneable {
*
* Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
* or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
- * issue the native close operation or skip it depending on the handles's ownership.
+ * issue the native close operation or skip it depending on the {@link #isHandleOwner() handles's ownership}.
*
*
* @return true if the handle was not null
and closing was successful, otherwise false.
*/
public boolean close();
+
+ /**
+ * @return true
if instance owns the handle to issue {@link #close()}, otherwise false
.
+ */
+ public boolean isHandleOwner();
+
+ public void clearHandleOwner();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
index eb2cc9120..acb98073b 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
@@ -44,6 +44,8 @@ package javax.media.nativewindow;
*/
public interface AbstractGraphicsScreen extends Cloneable {
+ public Object clone();
+
/**
* Return the device this graphics configuration is valid for
*/
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
index a33c3792a..6b23172e1 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
@@ -93,25 +93,26 @@ public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphics
/**
* Set the capabilities to a new value.
*
+ *
* The use case for setting the Capabilities at a later time is
- * a change of the graphics device in a multi-screen environment.
- *
+ * a change or re-validation of capabilities.
+ *
* @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
*/
protected void setChosenCapabilities(CapabilitiesImmutable capsChosen) {
- capabilitiesChosen = capsChosen;
+ this.capabilitiesChosen = capsChosen;
}
/**
* Set a new screen.
*
+ *
* the use case for setting a new screen at a later time is
- * a change of the graphics device in a multi-screen environment.
- *
- * A copy of the passed object is being used.
+ * a change of the graphics device in a multi-screen environment.
+ *
*/
- final protected void setScreen(DefaultGraphicsScreen screen) {
- this.screen = (AbstractGraphicsScreen) screen.clone();
+ protected void setScreen(AbstractGraphicsScreen screen) {
+ this.screen = screen;
}
@Override
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 9288652d9..b3ae4628c 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -37,10 +37,10 @@ import jogamp.nativewindow.NativeWindowFactoryImpl;
public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice {
private static final String separator = "_";
- private String type;
- protected String connection;
- protected int unitID;
- protected String uniqueID;
+ private final String type;
+ protected final String connection;
+ protected final int unitID;
+ protected final String uniqueID;
protected long handle;
protected ToolkitLock toolkitLock;
@@ -170,9 +170,18 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
return false;
}
+ @Override
+ public boolean isHandleOwner() {
+ return false;
+ }
+
+ @Override
+ public void clearHandleOwner() {
+ }
+
@Override
public String toString() {
- return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", "+toolkitLock+"]";
+ return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", owner "+isHandleOwner()+", "+toolkitLock+"]";
}
/**
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
index f50bd0e14..9fa58c7a3 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
@@ -33,8 +33,8 @@
package javax.media.nativewindow;
public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen {
- AbstractGraphicsDevice device;
- private int idx;
+ private final AbstractGraphicsDevice device;
+ private final int idx;
public DefaultGraphicsScreen(AbstractGraphicsDevice device, int idx) {
this.device = device;
@@ -57,7 +57,7 @@ public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen
public AbstractGraphicsDevice getDevice() {
return device;
}
-
+
public int getIndex() {
return idx;
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index d7f28a986..07702c762 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -48,6 +48,10 @@ import jogamp.nativewindow.ResourceToolkitLock;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
+import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
/** Provides a pluggable mechanism for arbitrary window toolkits to
adapt their components to the {@link NativeWindow} interface,
@@ -428,6 +432,29 @@ public abstract class NativeWindowFactory {
return NativeWindowFactoryImpl.getNullToolkitLock();
}
+ /**
+ * @param device
+ * @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen
+ * @return newly created AbstractGraphicsScreen of given native type
+ */
+ public static AbstractGraphicsScreen createScreen(String type, AbstractGraphicsDevice device, int screen) {
+ if( TYPE_X11 == type ) {
+ final X11GraphicsDevice x11Device = (X11GraphicsDevice)device;
+ if(0 > screen) {
+ screen = x11Device.getDefaultScreen();
+ }
+ return new X11GraphicsScreen(x11Device, screen);
+ }
+ if(0 > screen) {
+ screen = 0; // FIXME: Needs native API utilization
+ }
+ if( TYPE_AWT == type ) {
+ final AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) device;
+ return new AWTGraphicsScreen(awtDevice);
+ }
+ return new DefaultGraphicsScreen(device, screen);
+ }
+
/** Returns the appropriate NativeWindowFactory to handle window
objects of the given type. The windowClass might be {@link
NativeWindow NativeWindow}, in which case the client has
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index a8d45f288..017c52df2 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -180,7 +180,7 @@ static int errorHandlerThrowException = 0;
static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
{
- if(!errorHandlerQuiet) {
+ if( !errorHandlerQuiet || errorHandlerDebug ) {
const char * errnoStr = strerror(errno);
char errCodeStr[80];
char reqCodeStr[80];
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index 96d0f6e3b..7fccb6622 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -458,24 +458,22 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
} else {
t0 = 0;
}
-
- /* if (nativeWindowCreated && null != context) {
- throw new GLException("InternalError: Native Windows has been just created, but context wasn't destroyed (is not null)");
- } */
- if (null == context && visible && 0 != window.getWindowHandle() && 0 ctx1/draw2, ctx2/draw1.
+ */
+public class TestGLContextDrawableSwitch01NEWT extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ glp = GLProfile.getGL2ES2();
+ caps = new GLCapabilities(glp);
+ width = 256;
+ height = 256;
+ }
+
+ private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
+ final Window window = NewtFactory.createWindow(caps);
+ Assert.assertNotNull(window);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable drawable = factory.createGLDrawable(window);
+ Assert.assertNotNull(drawable);
+
+ drawable.setRealized(true);
+ Assert.assertTrue(drawable.isRealized());
+
+ final GLContext context = drawable.createContext(null);
+ Assert.assertNotNull(context);
+
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock();
+ window.destroy(); // destroys the actual window
+ }
+ };
+
+ // add basic window interaction
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) {
+ glad.windowRepaintOp();
+ }
+ @Override
+ public void windowResized(WindowEvent e) {
+ glad.windowResizedOp(window.getWidth(), window.getHeight());
+ }
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ glad.windowDestroyNotifyOp();
+ }
+ });
+ window.addWindowListener(wl);
+
+ return glad;
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2WindowSingleContext() throws InterruptedException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
+ GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+
+ // create single context using glad1 and assign it to glad1,
+ // destroy the prev. context afterwards.
+ {
+ final GLContext newCtx = glad1.createContext(null);
+ Assert.assertNotNull(newCtx);
+ final GLContext oldCtx = glad1.setContext(newCtx);
+ Assert.assertNotNull(oldCtx);
+ oldCtx.destroy();
+ final int res = newCtx.makeCurrent();
+ Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
+ newCtx.release();
+ }
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ GearsES2 gears = new GearsES2(1);
+ glad1.addGLEventListener(gears);
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Animator animator = new Animator();
+ animator.add(glad1);
+ animator.add(glad2);
+ animator.start();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+
+ // switch context _and_ the demo synchronously
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2);
+
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ glad1.destroy();
+ glad2.destroy();
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowOneDemo() throws InterruptedException {
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GearsES2 gears = new GearsES2(1);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ GLWindow glWindow1 = GLWindow.create(caps);
+ glWindow1.setTitle("win1");
+ glWindow1.setSize(width, height);
+ glWindow1.setPosition(64, 64);
+ glWindow1.addGLEventListener(0, gears);
+ glWindow1.addGLEventListener(snapshotGLEventListener);
+ glWindow1.addWindowListener(quitAdapter);
+
+ GLWindow glWindow2 = GLWindow.create(caps);
+ glWindow2.setTitle("win2");
+ glWindow2.setSize(width+100, height+100);
+ glWindow2.setPosition(2*64+width, 64);
+ glWindow2.addWindowListener(quitAdapter);
+
+ Animator animator = new Animator();
+ animator.add(glWindow1);
+ animator.add(glWindow2);
+ animator.start();
+
+ glWindow1.setVisible(true);
+ glWindow2.setVisible(true);
+
+ snapshotGLEventListener.setMakeSnapshot();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+ System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+
+ // switch context _and_ the demo synchronously
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
+
+ System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+
+ snapshotGLEventListener.setMakeSnapshot();
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ glWindow1.destroy();
+ glWindow2.destroy();
+
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowEachWithOwnDemo() throws InterruptedException {
+ final GearsES2 gears = new GearsES2(1);
+ final RedSquareES2 rsquare = new RedSquareES2(1);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ final SnapshotGLEventListener snapshotGLEventListener1 = new SnapshotGLEventListener();
+ final SnapshotGLEventListener snapshotGLEventListener2 = new SnapshotGLEventListener();
+
+ GLWindow glWindow1 = GLWindow.create(caps);
+ glWindow1.setTitle("win1");
+ glWindow1.setSize(width, height);
+ glWindow1.setPosition(64, 64);
+ glWindow1.addGLEventListener(0, gears);
+ glWindow1.addGLEventListener(snapshotGLEventListener1);
+ glWindow1.addWindowListener(quitAdapter);
+
+ GLWindow glWindow2 = GLWindow.create(caps);
+ glWindow2.setTitle("win2");
+ glWindow2.setSize(width+100, height+100);
+ glWindow2.setPosition(2*64+width, 64);
+ glWindow2.addGLEventListener(0, rsquare);
+ glWindow2.addGLEventListener(snapshotGLEventListener2);
+ glWindow2.addWindowListener(quitAdapter);
+
+ Animator animator = new Animator();
+ animator.add(glWindow1);
+ animator.add(glWindow2);
+ animator.start();
+
+ glWindow1.setVisible(true);
+ glWindow2.setVisible(true);
+
+ snapshotGLEventListener1.setMakeSnapshot();
+ snapshotGLEventListener2.setMakeSnapshot();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+ System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
+ System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+ snapshotGLEventListener1.setMakeSnapshot();
+ snapshotGLEventListener2.setMakeSnapshot();
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ // System.err.println("pre -del-w1: w1: "+glWindow1);
+ // System.err.println("pre -del-w1: w2: "+glWindow2);
+ glWindow1.destroy();
+ // System.err.println("post-del-w1: w1: "+glWindow1);
+ // System.err.println("post-del-w1: w2: "+glWindow2);
+ glWindow2.destroy();
+
+ }
+
+ // default timing for 2 switches
+ static long duration = 2200; // ms
+ static long period = 1000; // ms
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ *
+ */
+public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ glp = GLProfile.getGL2ES2();
+ caps = new GLCapabilities(glp);
+ width = 256;
+ height = 256;
+ }
+
+ private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
+ final Window window = NewtFactory.createWindow(caps);
+ Assert.assertNotNull(window);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable drawable = factory.createGLDrawable(window);
+ Assert.assertNotNull(drawable);
+
+ drawable.setRealized(true);
+ Assert.assertTrue(drawable.isRealized());
+
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock();
+ window.destroy(); // destroys the actual window
+ }
+ };
+
+ // add basic window interaction
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) {
+ glad.windowRepaintOp();
+ }
+ @Override
+ public void windowResized(WindowEvent e) {
+ glad.windowResizedOp(window.getWidth(), window.getHeight());
+ }
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ glad.windowDestroyNotifyOp();
+ }
+ });
+ window.addWindowListener(wl);
+
+ return glad;
+ }
+
+ @Test(timeout=30000)
+ public void test01() throws InterruptedException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ final GLEventListenerCounter glelCounter = new GLEventListenerCounter();
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final long t0 = System.currentTimeMillis();
+ final GLEventListenerState glls1;
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ final GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
+ final GLContext context1 = glad1.createContext(null);
+ glad1.setContext(context1);
+ animator.add(glad1);
+
+ glad1.addGLEventListener(glelCounter);
+ glad1.addGLEventListener(new GearsES2(1));
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/2 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ // - dis-associate context from glad1
+ // - destroy glad1
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(context1, glad1.getContext());
+ Assert.assertEquals(3, glad1.getGLEventListenerCount());
+ Assert.assertEquals(context1.getGLReadDrawable(), glad1.getDelegatedDrawable());
+ Assert.assertEquals(context1.getGLDrawable(), glad1.getDelegatedDrawable());
+
+ glls1 = GLEventListenerState.moveFrom(glad1);
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(context1, glls1.context);
+ Assert.assertNull(context1.getGLReadDrawable());
+ Assert.assertNull(context1.getGLDrawable());
+ Assert.assertEquals(3, glls1.listenerCount());
+ Assert.assertEquals(true, glls1.isOwner());
+ Assert.assertEquals(null, glad1.getContext());
+ Assert.assertEquals(0, glad1.getGLEventListenerCount());
+
+ glad1.destroy();
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ final GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Assert.assertEquals(null, glad2.getContext());
+ Assert.assertEquals(0, glad2.getGLEventListenerCount());
+
+ glls1.moveTo(glad2);
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(glls1.context, glad2.getContext());
+ Assert.assertEquals(3, glad2.getGLEventListenerCount());
+ Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(false, glls1.isOwner());
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/1 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ glad2.destroy();
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(1, glelCounter.disposeCount);
+ }
+ animator.stop();
+ }
+
+ @Test(timeout=30000)
+ public void test02() throws InterruptedException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final long t0 = System.currentTimeMillis();
+ final GLEventListenerState glls1;
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ final GLWindow glad1 = GLWindow.create(caps);
+ glad1.setSize(width, height);
+ glad1.setPosition(64, 64);
+ glad1.addWindowListener(quitAdapter);
+ glad1.setVisible(true);
+ animator.add(glad1);
+
+ glad1.addGLEventListener(glelTracker);
+ glad1.addGLEventListener(new GearsES2(1));
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/2 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ // - dis-associate context from glad1
+ // - destroy glad1
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(3, glad1.getGLEventListenerCount());
+ Assert.assertEquals(glad1.getContext().getGLReadDrawable(), glad1.getDelegatedDrawable());
+ Assert.assertEquals(glad1.getContext().getGLDrawable(), glad1.getDelegatedDrawable());
+
+ final GLContext context1 = glad1.getContext();
+ glls1 = GLEventListenerState.moveFrom(glad1);
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(context1, glls1.context);
+ Assert.assertNull(context1.getGLReadDrawable());
+ Assert.assertNull(context1.getGLDrawable());
+ Assert.assertEquals(3, glls1.listenerCount());
+ Assert.assertEquals(true, glls1.isOwner());
+ Assert.assertEquals(null, glad1.getContext());
+ Assert.assertEquals(0, glad1.getGLEventListenerCount());
+
+ glad1.destroy();
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ final GLWindow glad2 = GLWindow.create(caps);
+ glad2.setSize(width+100, height+100);
+ glad2.setPosition(2*64+width, 64);
+ glad2.addWindowListener(quitAdapter);
+ glad2.setVisible(true);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Assert.assertNotNull(glad2.getContext());
+ Assert.assertEquals(0, glad2.getGLEventListenerCount());
+
+ glls1.moveTo(glad2);
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(glls1.context, glad2.getContext());
+ Assert.assertEquals(3, glad2.getGLEventListenerCount());
+ Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(false, glls1.isOwner());
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/1 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ glad2.destroy();
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(1, glelTracker.disposeCount);
+ }
+ animator.stop();
+ }
+
+ // default timing for 2 switches
+ static long duration = 2200; // ms
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
-
- // switch context _and_ the demo synchronously
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2);
-
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- glad1.destroy();
- glad2.destroy();
- }
-
- @Test(timeout=30000)
- public void testSwitch2GLWindowOneDemo() throws InterruptedException {
- GearsES2 gears = new GearsES2(1);
- final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLWindow glWindow1 = GLWindow.create(caps);
- glWindow1.setTitle("win1");
- glWindow1.setSize(width, height);
- glWindow1.setPosition(64, 64);
- glWindow1.addGLEventListener(0, gears);
- glWindow1.addWindowListener(quitAdapter);
-
- GLWindow glWindow2 = GLWindow.create(caps);
- glWindow2.setTitle("win2");
- glWindow2.setSize(width+100, height+100);
- glWindow2.setPosition(2*64+width, 64);
- glWindow2.addWindowListener(quitAdapter);
-
- Animator animator = new Animator();
- animator.add(glWindow1);
- animator.add(glWindow2);
- animator.start();
-
- glWindow1.setVisible(true);
- glWindow2.setVisible(true);
-
- int s = 0;
- long t0 = System.currentTimeMillis();
- long t1 = t0;
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
- if( ( t1 - t0 ) / period > s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
-
- // switch context _and_ the demo synchronously
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
-
- System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- glWindow1.destroy();
- glWindow2.destroy();
-
- }
-
- @Test(timeout=30000)
- public void testSwitch2GLWindowEachWithOwnDemo() throws InterruptedException {
- GearsES2 gears = new GearsES2(1);
- RedSquareES2 rsquare = new RedSquareES2(1);
- final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLWindow glWindow1 = GLWindow.create(caps);
- glWindow1.setTitle("win1");
- glWindow1.setSize(width, height);
- glWindow1.setPosition(64, 64);
- glWindow1.addGLEventListener(0, gears);
- glWindow1.addWindowListener(quitAdapter);
-
- GLWindow glWindow2 = GLWindow.create(caps);
- glWindow2.setTitle("win2");
- glWindow2.setSize(width+100, height+100);
- glWindow2.setPosition(2*64+width, 64);
- glWindow2.addGLEventListener(0, rsquare);
- glWindow2.addWindowListener(quitAdapter);
-
- Animator animator = new Animator();
- animator.add(glWindow1);
- animator.add(glWindow2);
- animator.start();
-
- glWindow1.setVisible(true);
- glWindow2.setVisible(true);
-
- int s = 0;
- long t0 = System.currentTimeMillis();
- long t1 = t0;
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
- if( ( t1 - t0 ) / period > s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
- System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- // System.err.println("pre -del-w1: w1: "+glWindow1);
- // System.err.println("pre -del-w1: w2: "+glWindow2);
- glWindow1.destroy();
- // System.err.println("post-del-w1: w1: "+glWindow1);
- // System.err.println("post-del-w1: w2: "+glWindow2);
- glWindow2.destroy();
-
- }
-
- // default timing for 2 switches
- static long duration = 2200; // ms
- static long period = 1000; // ms
-
- public static void main(String args[]) throws IOException {
- for(int i=0; i