summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--make/scripts/tests.sh5
-rw-r--r--src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java269
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java38
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java40
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java137
-rw-r--r--src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java50
6 files changed, 378 insertions, 161 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 202b7ce38..88d3626cf 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -137,7 +137,7 @@ function jrun() {
#D_ARGS="-Djogl.debug.GLSLCode -Djogl.debug.TraceGL"
#D_ARGS="-Djogl.debug.GLSLCode -Djogl.debug.DebugGL"
#D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.JAWT -Dnewt.debug.Window"
- #D_ARGS="-Dnativewindow.debug.JAWT -Djogl.debug.GLCanvas"
+ D_ARGS="-Dnativewindow.debug.JAWT -Djogl.debug.GLCanvas"
#D_ARGS="-Dnativewindow.debug.JAWT -Djogamp.debug.TaskBase.TraceSource"
#D_ARGS="-Dnativewindow.debug.JAWT"
#D_ARGS="-Djogl.debug.GLContext.TraceSwitch"
@@ -423,6 +423,7 @@ function testawtswt() {
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $*
+testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 $*
#testnoawt com.jogamp.opengl.test.junit.graph.demos.GPUUISceneNewtDemo $*
#testawt com.jogamp.opengl.test.junit.graph.demos.GPUUISceneNewtCanvasAWTDemo $*
@@ -512,7 +513,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLException01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMapBufferRead01NEWT $*
-testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMapBufferRead02NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMapBufferRead02NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
diff --git a/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java
index 11d217535..5f59f7e6d 100644
--- a/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/awt/GLCanvas.java
@@ -173,7 +173,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private final RecursiveLock lock = LockFactory.createRecursiveLock();
private final GLDrawableHelper helper = new GLDrawableHelper();
- private AWTGraphicsConfiguration awtConfig;
private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
private volatile JAWTWindow jawtWindow; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
private volatile GLContextImpl context; // volatile: avoid locking for read-only access
@@ -187,9 +186,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private final GLCapabilitiesImmutable capsReqUser;
private final GLCapabilitiesChooser chooser;
private int additionalCtxCreationFlags = 0;
- private final GraphicsDevice device;
private boolean shallUseOffscreenLayer = false;
+ private volatile GraphicsDevice awtDeviceReq; // one time user req.
+ private volatile AWTGraphicsConfiguration awtConfig;
private volatile boolean isShowing;
private final HierarchyListener hierarchyListener = new HierarchyListener() {
@Override
@@ -270,16 +270,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported
}
- if(null==device) {
- final GraphicsConfiguration gc = super.getGraphicsConfiguration();
- if(null!=gc) {
- this.device = gc.getDevice();
- } else {
- this.device = null;
- }
- } else {
- this.device = device;
- }
+ // One time user AWT GraphicsDevice request
+ awtDeviceReq = device;
// instantiation will be issued in addNotify()
this.chooser = chooser;
@@ -330,124 +322,111 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
/**
- * Overridden to choose a GraphicsConfiguration on a parent container's
- * GraphicsDevice because both devices
+ * {@inheritDoc}
+ * <p>
+ * Overridden to choose a {@link GraphicsConfiguration} from a parent container's
+ * {@link GraphicsDevice}.
+ * </p>
+ * <p>
+ * Method also intercepts {@link GraphicsConfiguration} changes regarding to
+ * its capabilities and its {@link GraphicsDevice}. This may happen in case
+ * the display changes its configuration or the component is moved to another screen.
+ * </p>
*/
@Override
public GraphicsConfiguration getGraphicsConfiguration() {
- /*
- * Workaround for problems with Xinerama and java.awt.Component.checkGD
- * when adding to a container on a different graphics device than the
- * one that this Canvas is associated with.
- *
- * GC will be null unless:
- * - A native peer has assigned it. This means we have a native
- * peer, and are already comitted to a graphics configuration.
- * - This canvas has been added to a component hierarchy and has
- * an ancestor with a non-null GC, but the native peer has not
- * yet been created. This means we can still choose the GC on
- * all platforms since the peer hasn't been created.
- */
- final GraphicsConfiguration gc = super.getGraphicsConfiguration();
-
- if( Beans.isDesignTime() ) {
- return gc;
- }
-
- /*
- * chosen is only non-null on platforms where the GLDrawableFactory
- * returns a non-null GraphicsConfiguration (in the GLCanvas
- * constructor).
- *
- * if gc is from this Canvas' native peer then it should equal chosen,
- * otherwise it is from an ancestor component that this Canvas is being
- * added to, and we go into this block.
- */
- GraphicsConfiguration chosen = null != awtConfig ? awtConfig.getAWTGraphicsConfiguration() : null;
-
- if (gc != null && chosen != null && !chosen.equals(gc)) {
- /*
- * Check for compatibility with gc. If they differ by only the
- * device then return a new GCconfig with the super-class' GDevice
- * (and presumably the same visual ID in Xinerama).
- *
+ /**
+ * parentGC will be null unless:
+ * - A native peer has assigned it. This means we have a native
+ * peer, and are already committed to a graphics configuration.
+ * - This canvas has been added to a component hierarchy and has
+ * an ancestor with a non-null GC, but the native peer has not
+ * yet been created. This means we can still choose the GC on
+ * all platforms since the peer hasn't been created.
*/
- if (!chosen.getDevice().getIDstring().equals(gc.getDevice().getIDstring())) {
- /*
- * Here we select a GraphicsConfiguration on the alternate
- * device that is presumably identical to the chosen
- * configuration, but on the other device.
- *
- * Should really check to ensure that we select a configuration
- * with the same X visual ID for Xinerama screens, otherwise the
- * GLDrawable may have the wrong visual ID (I don't think this
- * ever gets updated). May need to add a method to
- * X11GLDrawableFactory to do this in a platform specific
- * manner.
- *
- * However, on platforms where we can actually get into this
- * block, both devices should have the same visual list, and the
- * same configuration should be selected here.
- */
- final AWTGraphicsConfiguration config = chooseGraphicsConfiguration( (GLCapabilitiesImmutable)awtConfig.getChosenCapabilities(),
- (GLCapabilitiesImmutable)awtConfig.getRequestedCapabilities(),
- chooser, gc.getDevice());
- final GraphicsConfiguration compatible = config.getAWTGraphicsConfiguration();
- final boolean equalCaps = config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities());
- if(DEBUG) {
- System.err.println(getThreadName()+": Info:");
- System.err.println("Created Config (n): HAVE GC "+chosen);
- System.err.println("Created Config (n): THIS GC "+gc);
- System.err.println("Created Config (n): Choosen GC "+compatible);
- System.err.println("Created Config (n): HAVE CF "+awtConfig);
- System.err.println("Created Config (n): Choosen CF "+config);
- System.err.println("Created Config (n): EQUALS CAPS "+equalCaps);
- // Thread.dumpStack();
- }
+ final GraphicsConfiguration parentGC = super.getGraphicsConfiguration();
- if (compatible != null) {
- /*
- * Save the new GC for equals test above, and to return to
- * any outside callers of this method.
- */
- chosen = compatible;
-
- if( !equalCaps && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) {
- // complete destruction!
- destroyImpl( true );
- // recreation!
- awtConfig = config;
- createJAWTDrawableAndContext();
- validateGLDrawable();
- } else {
- awtConfig = config;
+ if( Beans.isDesignTime() ) {
+ return parentGC;
+ }
+ final GraphicsConfiguration oldGC = null != awtConfig ? awtConfig.getAWTGraphicsConfiguration() : null;
+
+ if ( null != parentGC && null != oldGC && !oldGC.equals(parentGC) ) {
+ // Previous oldGC != parentGC of native peer
+
+ if ( !oldGC.getDevice().getIDstring().equals(parentGC.getDevice().getIDstring()) ) {
+ // Previous oldGC's GraphicsDevice != parentGC's GraphicsDevice of native peer
+
+ /**
+ * Here we select a GraphicsConfiguration on the alternate device.
+ * In case the new configuration differs (-> !equalCaps),
+ * we might need a reconfiguration,
+ */
+ final AWTGraphicsConfiguration newConfig = chooseGraphicsConfiguration( (GLCapabilitiesImmutable)awtConfig.getChosenCapabilities(),
+ (GLCapabilitiesImmutable)awtConfig.getRequestedCapabilities(),
+ chooser, parentGC.getDevice());
+ final GraphicsConfiguration newGC = newConfig.getAWTGraphicsConfiguration();
+ final boolean equalCaps = newConfig.getChosenCapabilities().equals(awtConfig.getChosenCapabilities());
+ if(DEBUG) {
+ System.err.println(getThreadName()+": getGraphicsConfiguration() Info: Changed GC and GD");
+ System.err.println("Created Config (n): Old GC "+oldGC);
+ System.err.println("Created Config (n): Old GD "+oldGC.getDevice().getIDstring());
+ System.err.println("Created Config (n): Parent GC "+parentGC);
+ System.err.println("Created Config (n): Parent GD "+parentGC.getDevice().getIDstring());
+ System.err.println("Created Config (n): New GC "+newGC);
+ System.err.println("Created Config (n): New GD "+newGC.getDevice().getIDstring());
+ System.err.println("Created Config (n): Old CF "+awtConfig);
+ System.err.println("Created Config (n): New CF "+newConfig);
+ System.err.println("Created Config (n): EQUALS CAPS "+equalCaps);
+ // Thread.dumpStack();
+ }
+ if ( null != newGC ) {
+ if( !equalCaps && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) {
+ // complete destruction!
+ destroyImpl( true );
+ // recreation!
+ setAWTGraphicsConfiguration(newConfig);
+ createJAWTDrawableAndContext();
+ validateGLDrawable();
+ } else {
+ setAWTGraphicsConfiguration(newConfig);
+ }
+ /**
+ * Return the newGC, which covers the desired capabilities and is compatible
+ * with the available GC's of its devices.
+ */
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: getGraphicsConfiguration - end.01: newGC "+newGC);
+ }
+ return newGC;
+ } else {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: getGraphicsConfiguration - end.00: oldGC "+oldGC);
+ }
+ }
}
- }
+ /**
+ * If a new GC was _not_ found/defined above,
+ * method returns oldGC as selected in the constructor or first addNotify().
+ * This may cause an exception in Component.checkGD when adding to a
+ * container, and is the desired behavior.
+ */
+ return oldGC;
+ } else if (null == parentGC) {
+ /**
+ * The parentGC is null, which means we have no native peer, and are not
+ * part of a (realized) component hierarchy. So we return the
+ * desired visual that was selected in the constructor (possibly
+ * null).
+ */
+ return oldGC;
+ } else {
+ /**
+ * Otherwise we have not explicitly selected a GC in the constructor, so
+ * just return what Canvas would have.
+ */
+ return parentGC;
}
-
- /*
- * If a compatible GC was not found in the block above, this will
- * return the GC that was selected in the constructor (and might
- * cause an exception in Component.checkGD when adding to a
- * container, but in this case that would be the desired behavior).
- *
- */
- return chosen;
- } else if (gc == null) {
- /*
- * The GC is null, which means we have no native peer, and are not
- * part of a (realized) component hierarchy. So we return the
- * desired visual that was selected in the constructor (possibly
- * null).
- */
- return chosen;
- }
-
- /*
- * Otherwise we have not explicitly selected a GC in the constructor, so
- * just return what Canvas would have.
- */
- return gc;
}
@Override
@@ -606,20 +585,35 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
} else {
/**
* 'super.addNotify()' determines the GraphicsConfiguration,
- * while calling this class's overriden 'getGraphicsConfiguration()' method
+ * while calling this class's overridden 'getGraphicsConfiguration()' method
* after which it creates the native peer.
* Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
* is being used in getGraphicsConfiguration().
* This code order also allows recreation, ie re-adding the GLCanvas.
*/
- awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, device);
- if(null==awtConfig) {
- throw new GLException("Error: NULL AWTGraphicsConfiguration");
- }
// before native peer is valid: X11
disableBackgroundErase();
+ final GraphicsDevice awtDevice;
+ if(null==awtDeviceReq) {
+ // Query AWT GraphicsDevice from parent tree, default
+ final GraphicsConfiguration gc = super.getGraphicsConfiguration();
+ if(null==gc) {
+ throw new GLException("Error: NULL AWT GraphicsConfiguration");
+ }
+ awtDevice = gc.getDevice();
+ } else {
+ // Use one time user AWT GraphicsDevice request
+ awtDevice = awtDeviceReq;
+ awtDeviceReq = null;
+ }
+ final AWTGraphicsConfiguration awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, awtDevice);
+ if(null==awtConfig) {
+ throw new GLException("Error: NULL AWTGraphicsConfiguration");
+ }
+ setAWTGraphicsConfiguration(awtConfig);
+
// issues getGraphicsConfiguration() and creates the native peer
super.addNotify();
@@ -775,6 +769,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
return false;
}
+ private void setAWTGraphicsConfiguration(final AWTGraphicsConfiguration config) {
+ // Cache awtConfig
+ awtConfig = config;
+ if( null != jawtWindow ) {
+ // Notify JAWTWindow ..
+ jawtWindow.setAWTGraphicsConfiguration(config);
+ }
+ }
+
/** <p>Overridden to track when this component is removed from a
container. Subclasses which override this method must call
super.removeNotify() in their removeNotify() method in order to
@@ -1394,7 +1397,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
System.err.println(getThreadName()+": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post GraphicsDevice: "+adeviceMsg+", result: "+closed);
}
}
- awtConfig=null;
+ awtConfig = null;
}
};
@@ -1546,10 +1549,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
if( Beans.isDesignTime() ) {
return null;
}
-
- final AbstractGraphicsScreen aScreen = null != device ?
- AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT):
- AWTGraphicsScreen.createDefault();
+ if( null == device ) {
+ throw new GLException("Error: NULL AWT GraphicsDevice");
+ }
+ final AbstractGraphicsScreen aScreen = AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT);
AWTGraphicsConfiguration config = null;
if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) {
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
index 62fd49092..cc70b6b7b 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java
@@ -73,19 +73,42 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple
}
/**
+ * @deprecated Use {@link #create(GraphicsConfiguration, CapabilitiesImmutable, CapabilitiesImmutable)}
+ * Method constructs a new {@link AWTGraphicsConfiguration} primarily based
+ * on the given {@link Component}'s {@link GraphicsConfiguration}.
+ * @param awtComp the {@link Component}, which {@link GraphicsConfiguration} is used for the resulting {@link AWTGraphicsConfiguration}
* @param capsChosen if null, <code>capsRequested</code> is copied and aligned
* with the graphics {@link Capabilities} of the AWT Component to produce the chosen {@link Capabilities}.
* Otherwise the <code>capsChosen</code> is used.
* @param capsRequested if null, default {@link Capabilities} are used, otherwise the given values.
*/
- public static AWTGraphicsConfiguration create(final Component awtComp, CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested) {
- final GraphicsConfiguration awtGfxConfig = awtComp.getGraphicsConfiguration();
- if(null==awtGfxConfig) {
- throw new NativeWindowException("AWTGraphicsConfiguration.create: Null AWT GraphicsConfiguration @ "+awtComp);
+ public static AWTGraphicsConfiguration create(final Component awtComp, final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested) {
+ if(null==awtComp) {
+ throw new IllegalArgumentException("Null AWT Component");
}
- final GraphicsDevice awtGraphicsDevice = awtGfxConfig.getDevice();
+ final GraphicsConfiguration gc = awtComp.getGraphicsConfiguration();
+ if( null == gc ) {
+ throw new NativeWindowException("Null AWT GraphicsConfiguration @ "+awtComp);
+ }
+ return create(gc, capsChosen, capsRequested);
+ }
+
+ /**
+ * Method constructs a new {@link AWTGraphicsConfiguration} primarily based
+ * on the given {@link GraphicsConfiguration}.
+ * @param gc the {@link GraphicsConfiguration} for the resulting {@link AWTGraphicsConfiguration}
+ * @param capsChosen if null, <code>capsRequested</code> is copied and aligned
+ * with the graphics {@link Capabilities} of the AWT Component to produce the chosen {@link Capabilities}.
+ * Otherwise the <code>capsChosen</code> is used.
+ * @param capsRequested if null, default {@link Capabilities} are used, otherwise the given values.
+ */
+ public static AWTGraphicsConfiguration create(final GraphicsConfiguration gc, CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested) {
+ if(null==gc) {
+ throw new IllegalArgumentException("Null AWT GraphicsConfiguration");
+ }
+ final GraphicsDevice awtGraphicsDevice = gc.getDevice();
if(null==awtGraphicsDevice) {
- throw new NativeWindowException("AWTGraphicsConfiguration.create: Null AWT GraphicsDevice @ "+awtGfxConfig);
+ throw new NativeWindowException("Null AWT GraphicsDevice @ "+gc);
}
// Create Device/Screen
@@ -96,7 +119,6 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple
capsRequested = new Capabilities();
}
if(null==capsChosen) {
- final GraphicsConfiguration gc = awtGraphicsDevice.getDefaultConfiguration();
capsChosen = AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capsRequested, gc);
}
final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(awtDevice, capsChosen);
@@ -105,7 +127,7 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple
return (AWTGraphicsConfiguration) config;
}
// System.err.println("Info: AWTGraphicsConfiguration.create: Expected AWTGraphicsConfiguration got: "+config.getClass()+" w/ factory "+factory.getClass()+" - Unable to encapsulate native GraphicsConfiguration.");
- return new AWTGraphicsConfiguration(awtScreen, capsChosen, capsRequested, awtGfxConfig);
+ return new AWTGraphicsConfiguration(awtScreen, capsChosen, capsRequested, gc);
}
// open access to superclass method
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index d315e1876..3a8cbefc6 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -49,7 +49,6 @@ import java.awt.Container;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.GraphicsConfiguration;
-import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.HierarchyEvent;
@@ -91,10 +90,10 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
// lifetime: forever
protected final Component component;
private final AppContextInfo appContextInfo;
- private final AWTGraphicsConfiguration config; // control access due to delegation
private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
private final RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
private final JAWTComponentListener jawtComponentListener;
+ private volatile AWTGraphicsConfiguration awtConfig; // control access through delegation
// lifetime: valid after lock but may change with each 1st lock, purges after invalidate
private boolean isApplet;
@@ -128,9 +127,9 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
appContextInfo = new AppContextInfo("<init>");
this.component = (Component)comp;
- this.config = (AWTGraphicsConfiguration) config;
this.jawtComponentListener = new JAWTComponentListener();
invalidate();
+ this.awtConfig = (AWTGraphicsConfiguration) config;
this.isApplet = false;
this.offscreenSurfaceLayer = 0;
}
@@ -265,6 +264,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
invalidateNative();
jawt = null;
+ awtConfig = null;
isOffscreenLayerSurface = false;
drawable= 0;
drawable_old = 0;
@@ -280,6 +280,34 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
protected abstract void invalidateNative();
+ /**
+ * Set a new {@link AWTGraphicsConfiguration} instance,
+ * as required if {@link #getAWTComponent() upstream component}'s {@link GraphicsConfiguration} has been changed
+ * due to reconfiguration, e.g. moving to a different monitor or changed capabilities.
+ * <p>
+ * {@link #getAWTComponent() Upstream component} shall override {@link Component#getGraphicsConfiguration()},
+ * which shall call this method if detecting a reconfiguration.
+ * See JOGL's GLCanvas and NewtCanvasAWT.
+ * </p>
+ * @param config the new {@link AWTGraphicsConfiguration}
+ * @see #getAWTGraphicsConfiguration()
+ */
+ public final void setAWTGraphicsConfiguration(final AWTGraphicsConfiguration config) {
+ if(DEBUG) {
+ System.err.println(jawtStr()+".setAWTGraphicsConfiguration(): "+this.awtConfig+" -> "+config);
+ // Thread.dumpStack();
+ }
+ this.awtConfig = config;
+ }
+ /**
+ * Return the current {@link AWTGraphicsConfiguration} instance,
+ * which also holds its {@link #getAWTComponent() upstream component}'s {@link GraphicsConfiguration}
+ * @see #setAWTGraphicsConfiguration(AWTGraphicsConfiguration)
+ */
+ public final AWTGraphicsConfiguration getAWTGraphicsConfiguration() {
+ return awtConfig;
+ }
+
@Override
public boolean setSurfaceScale(final float[] pixelScale) {
System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2);
@@ -527,7 +555,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
@Override
public final void setChosenCapabilities(final CapabilitiesImmutable caps) {
((MutableGraphicsConfiguration)getGraphicsConfiguration()).setChosenCapabilities(caps);
- config.setChosenCapabilities(caps);
+ awtConfig.setChosenCapabilities(caps);
}
@Override
@@ -706,7 +734,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
@Override
public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
- return config.getNativeGraphicsConfiguration();
+ return awtConfig.getNativeGraphicsConfiguration();
}
@Override
@@ -877,7 +905,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
"], pixels[scale "+getPixelScaleX()+", "+getPixelScaleY()+" -> "+getSurfaceWidth()+"x"+getSurfaceHeight()+"]"+
", visible "+component.isVisible());
sb.append(", lockedExt "+isSurfaceLockedByOtherThread()+
- ",\n\tconfig "+config+
+ ",\n\tconfig "+awtConfig+
",\n\tawtComponent "+getAWTComponent()+
",\n\tsurfaceLock "+surfaceLock+"]");
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index 5920d6de8..0a27f7f22 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -37,6 +37,7 @@ import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
import java.awt.KeyboardFocusManager;
import java.awt.geom.NoninvertibleTransformException;
import java.beans.Beans;
@@ -47,6 +48,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Set;
+import com.jogamp.nativewindow.CapabilitiesImmutable;
import com.jogamp.nativewindow.NativeWindow;
import com.jogamp.nativewindow.OffscreenLayerOption;
import com.jogamp.nativewindow.WindowClosingProtocol;
@@ -71,6 +73,7 @@ import jogamp.opengl.awt.AWTTilePainter;
import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.nativewindow.awt.JAWTWindow;
@@ -101,7 +104,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
public static final boolean DEBUG = Debug.debug("Window");
private final Object sync = new Object();
- private JAWTWindow jawtWindow = null;
+ private volatile JAWTWindow jawtWindow = null; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
private boolean isApplet = false;
private boolean shallUseOffscreenLayer = false;
private Window newtChild = null;
@@ -112,6 +115,8 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
private final AWTAdapter awtMouseAdapter;
private final AWTAdapter awtKeyAdapter;
+ private volatile AWTGraphicsConfiguration awtConfig;
+
/** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */
private boolean destroyJAWTPending = false;
/** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */
@@ -452,14 +457,142 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
}
}
+ private void setAWTGraphicsConfiguration(final AWTGraphicsConfiguration config) {
+ // Cache awtConfig
+ awtConfig = config;
+ if( null != jawtWindow ) {
+ // Notify JAWTWindow ..
+ jawtWindow.setAWTGraphicsConfiguration(config);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Overridden to choose a {@link GraphicsConfiguration} from a parent container's
+ * {@link GraphicsDevice}.
+ * </p>
+ * <p>
+ * Method also intercepts {@link GraphicsConfiguration} changes regarding to
+ * its capabilities and its {@link GraphicsDevice}. This may happen in case
+ * the display changes its configuration or the component is moved to another screen.
+ * </p>
+ */
+ @Override
+ public GraphicsConfiguration getGraphicsConfiguration() {
+ /**
+ * parentGC will be null unless:
+ * - A native peer has assigned it. This means we have a native
+ * peer, and are already committed to a graphics configuration.
+ * - This canvas has been added to a component hierarchy and has
+ * an ancestor with a non-null GC, but the native peer has not
+ * yet been created. This means we can still choose the GC on
+ * all platforms since the peer hasn't been created.
+ */
+ final GraphicsConfiguration parentGC = super.getGraphicsConfiguration();
+
+ if( Beans.isDesignTime() ) {
+ return parentGC;
+ }
+ final GraphicsConfiguration oldGC = null != awtConfig ? awtConfig.getAWTGraphicsConfiguration() : null;
+
+ if ( null != parentGC && null != oldGC && !oldGC.equals(parentGC) ) {
+ // Previous oldGC != parentGC of native peer
+
+ if ( !oldGC.getDevice().getIDstring().equals(parentGC.getDevice().getIDstring()) ) {
+ // Previous oldGC's GraphicsDevice != parentGC's GraphicsDevice of native peer
+
+ /**
+ * Here we select a GraphicsConfiguration on the alternate device.
+ * In case the new configuration differs (-> !equalCaps),
+ * we might need a reconfiguration,
+ */
+ final AWTGraphicsConfiguration newConfig = AWTGraphicsConfiguration.create(parentGC,
+ awtConfig.getChosenCapabilities(),
+ awtConfig.getRequestedCapabilities());
+ final GraphicsConfiguration newGC = newConfig.getAWTGraphicsConfiguration();
+ final boolean equalCaps = newConfig.getChosenCapabilities().equals(awtConfig.getChosenCapabilities());
+ if(DEBUG) {
+ System.err.println(getThreadName()+": getGraphicsConfiguration() Info: Changed GC and GD");
+ System.err.println("Created Config (n): Old GC "+oldGC);
+ System.err.println("Created Config (n): Old GD "+oldGC.getDevice().getIDstring());
+ System.err.println("Created Config (n): Parent GC "+parentGC);
+ System.err.println("Created Config (n): Parent GD "+parentGC.getDevice().getIDstring());
+ System.err.println("Created Config (n): New GC "+newGC);
+ System.err.println("Created Config (n): Old CF "+awtConfig);
+ System.err.println("Created Config (n): New CF "+newConfig);
+ System.err.println("Created Config (n): EQUALS CAPS "+equalCaps);
+ // Thread.dumpStack();
+ }
+ if ( null != newGC ) {
+ setAWTGraphicsConfiguration(newConfig);
+ /**
+ * Return the newGC, which covers the desired capabilities and is compatible
+ * with the available GC's of its devices.
+ */
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: getGraphicsConfiguration - end.01: newGC "+newGC);
+ }
+ return newGC;
+ } else {
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Info: getGraphicsConfiguration - end.00: oldGC "+oldGC);
+ }
+ }
+ }
+ /**
+ * If a new GC was _not_ found/defined above,
+ * method returns oldGC as selected in the constructor or first addNotify().
+ * This may cause an exception in Component.checkGD when adding to a
+ * container, and is the desired behavior.
+ */
+ return oldGC;
+ } else if (null == parentGC) {
+ /**
+ * The parentGC is null, which means we have no native peer, and are not
+ * part of a (realized) component hierarchy. So we return the
+ * desired visual that was selected in the constructor (possibly
+ * null).
+ */
+ return oldGC;
+ } else {
+ /**
+ * Otherwise we have not explicitly selected a GC in the constructor, so
+ * just return what Canvas would have.
+ */
+ return parentGC;
+ }
+ }
+ private static String getThreadName() { return Thread.currentThread().getName(); }
+
@Override
public void addNotify() {
if( Beans.isDesignTime() ) {
super.addNotify();
} else {
+ /**
+ * 'super.addNotify()' determines the GraphicsConfiguration,
+ * while calling this class's overridden 'getGraphicsConfiguration()' method
+ * after which it creates the native peer.
+ * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
+ * is being used in getGraphicsConfiguration().
+ * This code order also allows recreation, ie re-adding the GLCanvas.
+ */
// before native peer is valid: X11
disableBackgroundErase();
+ // Query AWT GraphicsDevice from parent tree, default
+ final GraphicsConfiguration gc = super.getGraphicsConfiguration();
+ if(null==gc) {
+ throw new GLException("Error: NULL AWT GraphicsConfiguration");
+ }
+ final CapabilitiesImmutable capsReq = null != newtChild ? newtChild.getRequestedCapabilities() : null;
+ final AWTGraphicsConfiguration awtConfig = AWTGraphicsConfiguration.create(gc, null, capsReq);
+ if(null==awtConfig) {
+ throw new GLException("Error: NULL AWTGraphicsConfiguration");
+ }
+ setAWTGraphicsConfiguration(awtConfig);
+
// creates the native peer
super.addNotify();
@@ -472,7 +605,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
System.err.println("NewtCanvasAWT.addNotify.0 - isApplet "+isApplet+", addedOnAWTEDT "+EventQueue.isDispatchThread()+" @ "+currentThreadName());
ExceptionUtils.dumpStack(System.err);
}
- jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, null != newtChild ? newtChild.getRequestedCapabilities() : null);
+ jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, awtConfig);
jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
// enforce initial lock on AWT-EDT, allowing acquisition of pixel-scale
jawtWindow.lockSurface();
diff --git a/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java
index 8eaca7c0e..cc71fb559 100644
--- a/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java
+++ b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java
@@ -28,8 +28,6 @@
package jogamp.newt.awt;
-import java.awt.GraphicsDevice;
-
import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
import com.jogamp.nativewindow.CapabilitiesImmutable;
import com.jogamp.nativewindow.NativeWindow;
@@ -57,6 +55,8 @@ public class NewtFactoryAWT extends NewtFactory {
public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window");
/**
+ * @deprecated Use {@link #getNativeWindow(java.awt.Component, AWTGraphicsConfiguration)}
+ *
* Wraps an AWT component into a {@link com.jogamp.nativewindow.NativeWindow} utilizing the {@link com.jogamp.nativewindow.NativeWindowFactory},<br>
* using a configuration agnostic dummy {@link com.jogamp.nativewindow.DefaultGraphicsConfiguration}.<br>
* <p>
@@ -78,9 +78,37 @@ public class NewtFactoryAWT extends NewtFactory {
return getNativeWindow( (java.awt.Component) awtCompObject, capsRequested );
}
+ /**
+ * @deprecated Use {@link #getNativeWindow(java.awt.Component, AWTGraphicsConfiguration)}
+ * @param awtComp
+ * @param capsRequested
+ * @return
+ */
public static JAWTWindow getNativeWindow(final java.awt.Component awtComp, final CapabilitiesImmutable capsRequested) {
- final AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(awtComp, null, capsRequested);
- final NativeWindow nw = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow
+ final AWTGraphicsConfiguration awtConfig = AWTGraphicsConfiguration.create(awtComp, null, capsRequested);
+ return getNativeWindow(awtComp, awtConfig);
+ }
+
+ /**
+ * Wraps an AWT component into a {@link com.jogamp.nativewindow.NativeWindow} utilizing the {@link com.jogamp.nativewindow.NativeWindowFactory},<br>
+ * using the given {@link AWTGraphicsConfiguration}.
+ * <p>
+ * The actual wrapping implementation is {@link com.jogamp.nativewindow.awt.JAWTWindow}.
+ * </p>
+ * <p>
+ * The required {@link AWTGraphicsConfiguration} may be constructed via
+ * {@link AWTGraphicsConfiguration#create(java.awt.GraphicsConfiguration, CapabilitiesImmutable, CapabilitiesImmutable)}
+ * </p>
+ * <p>
+ * Purpose of this wrapping is to access the AWT window handle,<br>
+ * not to actually render into it.
+ * </p>
+ *
+ * @param awtComp {@link java.awt.Component}
+ * @param awtConfig {@link AWTGraphicsConfiguration} reflecting the used {@link java.awt.GraphicsConfiguration}
+ */
+ public static JAWTWindow getNativeWindow(final java.awt.Component awtComp, final AWTGraphicsConfiguration awtConfig) {
+ final NativeWindow nw = NativeWindowFactory.getNativeWindow(awtComp, awtConfig); // a JAWTWindow
if(! ( nw instanceof JAWTWindow ) ) {
throw new NativeWindowException("Not an AWT NativeWindow: "+nw);
}
@@ -101,13 +129,15 @@ public class NewtFactoryAWT extends NewtFactory {
* @throws IllegalArgumentException if {@code awtComp} is not {@link java.awt.Component#isDisplayable() displayable}
* or has {@code null} {@link java.awt.Component#getGraphicsConfiguration() GraphicsConfiguration}.
*/
- private static void checkComponentValid(final java.awt.Component awtComp) throws IllegalArgumentException {
+ private static java.awt.GraphicsConfiguration checkComponentValid(final java.awt.Component awtComp) throws IllegalArgumentException {
if( !awtComp.isDisplayable() ) {
throw new IllegalArgumentException("Given AWT-Component is not displayable: "+awtComp);
}
- if( null == awtComp.getGraphicsConfiguration() ) {
+ final java.awt.GraphicsConfiguration gc = awtComp.getGraphicsConfiguration();
+ if( null == gc ) {
throw new IllegalArgumentException("Given AWT-Component has no GraphicsConfiguration set: "+awtComp);
}
+ return gc;
}
/**
@@ -120,8 +150,8 @@ public class NewtFactoryAWT extends NewtFactory {
* @see #getAbstractGraphicsScreen(java.awt.Component)
*/
public static Display createDisplay(final java.awt.Component awtComp, final boolean reuse) throws IllegalArgumentException {
- checkComponentValid(awtComp);
- final GraphicsDevice device = awtComp.getGraphicsConfiguration().getDevice();
+ final java.awt.GraphicsConfiguration gc = checkComponentValid(awtComp);
+ final java.awt.GraphicsDevice device = gc.getDevice();
final String displayConnection;
final String nwt = NativeWindowFactory.getNativeWindowType(true);
@@ -174,13 +204,13 @@ public class NewtFactoryAWT extends NewtFactory {
* @see #createScreen(java.awt.Component, boolean)
*/
public static MonitorDevice getMonitorDevice(final Screen screen, final java.awt.Component awtComp) throws IllegalArgumentException {
- checkComponentValid(awtComp);
+ final java.awt.GraphicsConfiguration gc = checkComponentValid(awtComp);
final String nwt = NativeWindowFactory.getNativeWindowType(true);
MonitorDevice res = null;
screen.addReference();
try {
if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
- res = screen.getMonitor( JAWTUtil.getMonitorDisplayID( awtComp.getGraphicsConfiguration().getDevice() ) );
+ res = screen.getMonitor( JAWTUtil.getMonitorDisplayID( gc.getDevice() ) );
}
if( null == res ) {
// Fallback, use AWT component coverage