aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2010-09-25 15:06:26 +0200
committerSven Gothel <[email protected]>2010-09-25 15:06:26 +0200
commitbcad73dccb1cd0c32e3a77b3406ddc74e8f2e4ac (patch)
treeaac1f157781e4243acba7d11622344b6b84dafcf /src
parent1c02f0eeb539ff5de7259b822893ab63a9cc3ab0 (diff)
Unit test for Bug 411 (Pre AWT/Swing Usage, Mixed usage with JOGL) - GLCanvas NPE fix - NewtCanvasAWT added destroy(..)
Unit test for Bug 411 (Pre AWT/Swing Usage, Mixed usage with JOGL): Added exhausting Pre AWT/Swing usage test utilizing a later JOGL init with GLCanvas and NEWTCanvasAWT. This works for NV+X11+Ubuntu+64bit, have to do more testing. GLCanvas NPE fix at destroy/dispose, check if already destroyed, ie context==null NewtCanvasAWT: Add destroy() and destroy(boolean unrecoverable)
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java39
-rw-r--r--src/junit/com/jogamp/test/junit/jogl/awt/TestSwingAWTUsageBeforeJOGLInitBug411.java310
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java42
3 files changed, 370 insertions, 21 deletions
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 705b12783..4e63a8048 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -316,26 +316,29 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable {
Exception ex1 = new Exception("dispose("+regenerate+") - start");
ex1.printStackTrace();
}
- disposeRegenerate=regenerate;
- if (Threading.isSingleThreaded() &&
- !Threading.isOpenGLThread()) {
- // Workaround for termination issues with applets --
- // sun.applet.AppletPanel should probably be performing the
- // remove() call on the EDT rather than on its own thread
- if (ThreadingImpl.isAWTMode() &&
- Thread.holdsLock(getTreeLock())) {
- // The user really should not be invoking remove() from this
- // thread -- but since he/she is, we can not go over to the
- // EDT at this point. Try to destroy the context from here.
- if(context.isCreated()) {
- drawableHelper.invokeGL(drawable, context, disposeAction, null);
+ if(null!=context) {
+ disposeRegenerate=regenerate;
+
+ if (Threading.isSingleThreaded() &&
+ !Threading.isOpenGLThread()) {
+ // Workaround for termination issues with applets --
+ // sun.applet.AppletPanel should probably be performing the
+ // remove() call on the EDT rather than on its own thread
+ if (ThreadingImpl.isAWTMode() &&
+ Thread.holdsLock(getTreeLock())) {
+ // The user really should not be invoking remove() from this
+ // thread -- but since he/she is, we can not go over to the
+ // EDT at this point. Try to destroy the context from here.
+ if(context.isCreated()) {
+ drawableHelper.invokeGL(drawable, context, disposeAction, null);
+ }
+ } else if(context.isCreated()) {
+ Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction);
+ }
+ } else if(context.isCreated()) {
+ drawableHelper.invokeGL(drawable, context, disposeAction, null);
}
- } else if(context.isCreated()) {
- Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction);
- }
- } else if(context.isCreated()) {
- drawableHelper.invokeGL(drawable, context, disposeAction, null);
}
if(DEBUG) {
diff --git a/src/junit/com/jogamp/test/junit/jogl/awt/TestSwingAWTUsageBeforeJOGLInitBug411.java b/src/junit/com/jogamp/test/junit/jogl/awt/TestSwingAWTUsageBeforeJOGLInitBug411.java
new file mode 100644
index 000000000..8f0216fe7
--- /dev/null
+++ b/src/junit/com/jogamp/test/junit/jogl/awt/TestSwingAWTUsageBeforeJOGLInitBug411.java
@@ -0,0 +1,310 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.test.junit.jogl.awt;
+
+import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears;
+
+import java.lang.reflect.InvocationTargetException;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.awt.GLCanvas;
+import com.jogamp.opengl.util.Animator;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+
+import java.awt.BorderLayout;
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.AWTException;
+import java.awt.Container;
+import java.awt.LayoutManager;
+import java.awt.Robot;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import javax.media.opengl.GLEventListener;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.BorderFactory;
+import javax.swing.border.Border;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+public class TestSwingAWTUsageBeforeJOGLInitBug411 {
+ static long durationPerTest = 500; // ms
+ static Robot robot;
+ static boolean keyTyped;
+ static boolean buttonClicked;
+ static Border border;
+ static JFrame frame;
+ static JButton button;
+ static JPanel panel;
+ static JPanel colorPanel;
+ static boolean windowClosing;
+
+ boolean modLightBrighter = true;
+
+ Color modLight(Color c) {
+ Color c2;
+ if(modLightBrighter) {
+ c2 = c.brighter();
+ } else {
+ c2 = c.darker();
+ }
+ if(c2.equals(c)) {
+ modLightBrighter = !modLightBrighter;
+ }
+ return c2;
+ }
+
+ class SwingGLAction implements GLEventListener {
+ public void init(GLAutoDrawable glad) {
+ }
+
+ public void dispose(GLAutoDrawable glad) {
+ }
+
+ public void display(GLAutoDrawable glad) {
+ colorPanel.setBackground(modLight(colorPanel.getBackground()));
+ colorPanel.repaint();
+ }
+
+ public void reshape(GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ }
+ }
+
+ @BeforeClass
+ public static void setup() throws InterruptedException, InvocationTargetException, AWTException {
+ int count;
+
+ // simulate AWT usage before JOGL's initialization of X11 threading
+ keyTyped = false;
+ buttonClicked = false;
+ windowClosing=false;
+ border = BorderFactory.createLineBorder (Color.yellow, 2);
+
+ panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+
+ button = new JButton("Click me");
+ button.addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ System.err.println("Test: "+e);
+ buttonClicked = true;
+ }
+ });
+ panel.add(button, BorderLayout.NORTH);
+
+ colorPanel = new JPanel();
+ Dimension size = new Dimension(400,100);
+ colorPanel.setPreferredSize(size);
+ colorPanel.setBorder(border);
+ panel.add(colorPanel, BorderLayout.SOUTH);
+
+ frame = new JFrame("PRE JOGL");
+ frame.addWindowListener( new WindowAdapter() {
+ public void windowClosing(WindowEvent ev) {
+ windowClosing=true;
+ }
+ });
+ frame.addKeyListener(new KeyAdapter() {
+ public void keyTyped(KeyEvent e) {
+ System.err.println("Test: "+e);
+ keyTyped = true;
+ }
+ });
+ frame.setContentPane(panel);
+ frame.setSize(512, 512);
+ frame.pack();
+ frame.setVisible(true);
+
+ // AWT/Swing: From here on (post setVisible(true)
+ // you need to use AWT/Swing's invokeAndWait()
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ colorPanel.setBackground(Color.white);
+ colorPanel.repaint();
+ }});
+
+ robot = new Robot();
+ robot.setAutoWaitForIdle(true);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.requestFocus();
+ }});
+
+ Thread.sleep(200);
+
+ robot.delay(100);
+
+ for (count=0; !keyTyped && count<99; count++) {
+ robot.keyPress(KeyEvent.VK_Q);
+ robot.delay(50);
+ robot.keyRelease(KeyEvent.VK_Q);
+ robot.delay(100);
+ Thread.sleep(100);
+ }
+ Point p0 = button.getLocationOnScreen();
+ Rectangle r0 = button.getBounds();
+ robot.mouseMove( (int) ( p0.getX() + r0.getWidth() /2.0 + .5 ) ,
+ (int) ( p0.getY() + r0.getHeight()/2.0 + .5 ) );
+
+ for (count=0; !buttonClicked && count<99; count++) {
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.delay(50);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ robot.delay(100);
+ Thread.sleep(100);
+ }
+ System.err.println("Clean End of Pre-JOGL-Swing");
+
+ GLProfile.initSingleton();
+ }
+
+ @AfterClass
+ public static void release() {
+ robot = null;
+ Assert.assertNotNull(frame);
+ frame.dispose();
+ frame=null;
+ }
+
+ protected void runTestGL(final Canvas canvas, GLAutoDrawable drawable) throws InterruptedException, InvocationTargetException {
+ Dimension size = new Dimension(400,400);
+ canvas.setPreferredSize(size);
+
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ panel.add(canvas, BorderLayout.CENTER);
+ frame.pack();
+ }
+ });
+
+ drawable.addGLEventListener(new Gears());
+
+ for(int i=0; i<100; i++) {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ colorPanel.setBackground(modLight(colorPanel.getBackground()));
+ colorPanel.repaint();
+ }
+ });
+ drawable.display(); // one in process display
+ Thread.sleep(10);
+ }
+
+ colorPanel.setBackground(Color.blue);
+ drawable.addGLEventListener(new SwingGLAction());
+
+ Animator animator = new Animator(drawable);
+ animator.start();
+
+ Point p0 = canvas.getLocationOnScreen();
+ Rectangle r0 = canvas.getBounds();
+ robot.mouseMove( (int) ( p0.getX() + .5 ) ,
+ (int) ( p0.getY() + .5 ) );
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ for(int i=0; !windowClosing && i<durationPerTest/10; i++) {
+ p0.translate(1,1);
+ robot.mouseMove( (int) ( p0.getX() + .5 ) ,
+ (int) ( p0.getY() + .5 ) );
+ Thread.sleep(10);
+ }
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+
+ for(int i=0; !windowClosing && i<durationPerTest/10; i++) {
+ Thread.sleep(10);
+ }
+
+ animator.stop();
+
+ Assert.assertNotNull(canvas);
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ panel.remove(canvas);
+ frame.pack();
+ }
+ });
+ }
+
+ @Test
+ public void test01GLCanvas() throws InterruptedException, InvocationTargetException {
+ GLProfile glp = GLProfile.getDefault();
+ GLCapabilities caps = new GLCapabilities(glp);
+
+ GLCanvas glCanvas = new GLCanvas(caps);
+
+ runTestGL(glCanvas, glCanvas);
+ }
+
+ @Test
+ public void test02NewtCanvasAWT() throws InterruptedException, InvocationTargetException {
+ GLProfile glp = GLProfile.getDefault();
+ GLCapabilities caps = new GLCapabilities(glp);
+
+ NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(GLWindow.create(caps));
+
+ runTestGL(newtCanvasAWT, (GLAutoDrawable)newtCanvasAWT.getNEWTChild());
+ newtCanvasAWT.destroy(true);
+ }
+
+ static int atoi(String a) {
+ int i=0;
+ try {
+ i = Integer.parseInt(a);
+ } catch (Exception ex) { ex.printStackTrace(); }
+ return i;
+ }
+
+ public static void main(String args[]) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ durationPerTest = atoi(args[++i]);
+ }
+ }
+ System.out.println("durationPerTest: "+durationPerTest);
+ org.junit.runner.JUnitCore.main(TestSwingAWTUsageBeforeJOGLInitBug411.class.getName());
+ }
+}
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index fdb434889..de4ea2a30 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -165,9 +165,7 @@ public class NewtCanvasAWT extends java.awt.Canvas {
}
if(add) {
- if(null!=newtChild) {
- parent = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities());
- }
+ parent = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities());
if(null!=parent) {
if(DEBUG) {
System.err.println("NewtCanvasAWT.reparentWindow: "+newtChild);
@@ -188,6 +186,44 @@ public class NewtCanvasAWT extends java.awt.Canvas {
}
}
+ /**
+ * @see #destroy(boolean)
+ */
+ public final void destroy() {
+ destroy(false);
+ }
+
+ /**
+ * Destroys this resource:
+ * <ul>
+ * <li> Make the NEWT Child invisible </li>
+ * <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
+ * <li> Issues <code>destroy(unrecoverable)</code> on the NEWT Child</li>
+ * <li> Remove reference to the NEWT Child, if unrecoverable</li>
+ * <li> Remove this Canvas from it's parent.</li>
+ * </ul>
+ * @see Window#destroy()
+ * @see Window#destroy(boolean)
+ */
+ public final void destroy(boolean unrecoverable) {
+ if(null!=newtChild) {
+ java.awt.Container cont = getContainer(this);
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.destroy("+unrecoverable+"): "+newtChild+", from "+cont);
+ }
+ parent = null;
+ newtChild.setVisible(false);
+ newtChild.reparentWindow(null);
+ newtChild.destroy(unrecoverable);
+ if(unrecoverable) {
+ newtChild = null;
+ }
+ if(null!=cont) {
+ cont.remove(this);
+ }
+ }
+ }
+
public void paint(Graphics g) {
if(null!=newtChild) {
newtChild.windowRepaint(0, 0, getWidth(), getHeight());