diff options
Diffstat (limited to 'src/newt/classes/com/jogamp')
-rw-r--r-- | src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 137 |
1 files changed, 135 insertions, 2 deletions
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(); |