From 0d24458c68ac1bb92da21a1701633f8f32a267bb Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 16 Jun 2010 06:57:15 +0200 Subject: JOGL.GLAutoDrawable: - Add: 'public void addGLEventListener(int index, GLEventListener listener)' Fixes previous GLWindow addition, ie public in interface and common impl. behavior. - Add: 'public void invoke(boolean wait, GLRunnable glRunnable)' - Change: 'public void display()' semantics, in regards to the GLRunnable queue New: GLRunnable, invoke() at GLAutoDrawable Allows injection of GL commands from other threads, executed after the GLEventListener's display() notifyier by the GLAutoDrawable. NEWT: - Fix EDTUTil.invokeAndWait() and Display.enqueueAndWait() impl., where we only wait for the single action/event to be processed now. JUnit: NEWT Parenting - Added test cases for Swing (JFrame, JPanel and COntainer) with NewtCanvasAWT - Added thread calling 'invoke(true, GLRunnable)' - start Animator ASAP --- src/newt/classes/com/jogamp/newt/Display.java | 80 ++++++++-------------- src/newt/classes/com/jogamp/newt/Window.java | 12 ++-- .../com/jogamp/newt/impl/event/NEWTEventTask.java | 54 +++++++++++++++ .../classes/com/jogamp/newt/opengl/GLWindow.java | 4 ++ src/newt/classes/com/jogamp/newt/util/EDTUtil.java | 34 +++++---- 5 files changed, 118 insertions(+), 66 deletions(-) create mode 100644 src/newt/classes/com/jogamp/newt/impl/event/NEWTEventTask.java (limited to 'src/newt') diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index c804b3d2d..193bb26dc 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -36,6 +36,7 @@ package com.jogamp.newt; import javax.media.nativewindow.*; import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import com.jogamp.newt.event.*; +import com.jogamp.newt.impl.event.*; import com.jogamp.newt.impl.Debug; import com.jogamp.newt.util.EDTUtil; import java.util.*; @@ -315,46 +316,31 @@ public abstract class Display { private Object eventsLock = new Object(); private LinkedList/**/ events = new LinkedList(); - private boolean events2Wait = false; protected void dispatchMessages() { if(0==refCount) return; // we should not exist .. if(!events.isEmpty()) { - if(events2Wait) { - synchronized(eventsLock) { - while (!events.isEmpty()) { - NEWTEvent e = (NEWTEvent) events.removeFirst(); - Object source = e.getSource(); - if(source instanceof Window) { - ((Window)source).sendEvent(e); - } else { - throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); - } - } - events2Wait = false; // clear - eventsLock.notifyAll(); - } - } else { - // swap events list to free ASAP - LinkedList/**/ _events = null; - synchronized(eventsLock) { - if(!events.isEmpty()) { - _events = events; - events = new LinkedList(); - } - eventsLock.notifyAll(); + // swap events list to free ASAP + LinkedList/**/ _events = null; + synchronized(eventsLock) { + if(!events.isEmpty()) { + _events = events; + events = new LinkedList(); } - if( null != _events ) { - while (!_events.isEmpty()) { - NEWTEvent e = (NEWTEvent) _events.removeFirst(); - Object source = e.getSource(); - if(source instanceof Window) { - ((Window)source).sendEvent(e); - } else { - throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); - } + eventsLock.notifyAll(); + } + if( null != _events ) { + for (Iterator iter = _events.iterator(); iter.hasNext(); ) { + NEWTEventTask eventTask = (NEWTEventTask) iter.next(); + NEWTEvent event = eventTask.get(); + Object source = event.getSource(); + if(source instanceof Window) { + ((Window)source).sendEvent(event); + } else { + throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); } + eventTask.notifyIssuer(); } } } @@ -372,27 +358,21 @@ public abstract class Display { } public void enqueueEvent(boolean wait, NEWTEvent e) { - synchronized(eventsLock) { - if(DEBUG) { - System.out.println("Display.enqueueEvent: START - wait "+wait+", "+e); - } - events2Wait = wait; - events.addLast(e); - } - if(wait && !events.isEmpty()) { + Object lock = new Object(); + NEWTEventTask eTask = new NEWTEventTask(e, wait?lock:null); + synchronized(lock) { synchronized(eventsLock) { - while(!events.isEmpty()) { - try { - eventsLock.wait(); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } + events.addLast(eTask); + eventsLock.notifyAll(); + } + if( wait ) { + try { + lock.wait(); + } catch (InterruptedException ie) { + throw new RuntimeException(ie); } } } - if(DEBUG) { - System.out.println("Display.enqueueEvent: END - wait "+wait+", "+e); - } } public void lock() { diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 045a5eb72..e9289f5dc 100755 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -707,9 +707,9 @@ public abstract class Window implements NativeWindow public void reparentWindow(NativeWindow newParent, Screen newScreen) { if(!isDestroyed()) { runOnEDTIfAvail(true, new ReparentAction(newParent, newScreen)); - if( isVisible() ) { - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener - } + // if( isVisible() ) { + enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener + // } } } @@ -1321,8 +1321,12 @@ public abstract class Window implements NativeWindow // WindowListener/Event Support // protected void enqueueWindowEvent(int eventType) { + enqueueWindowEvent(false, eventType); + } + + protected void enqueueWindowEvent(boolean wait, int eventType) { WindowEvent event = new WindowEvent(eventType, this, System.currentTimeMillis()); - screen.getDisplay().enqueueEvent( event ); + screen.getDisplay().enqueueEvent( wait, event ); // sendWindowEvent ( event ); // FIXME: Think about performance/lag .. ? } diff --git a/src/newt/classes/com/jogamp/newt/impl/event/NEWTEventTask.java b/src/newt/classes/com/jogamp/newt/impl/event/NEWTEventTask.java new file mode 100644 index 000000000..479c493b0 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/impl/event/NEWTEventTask.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010, Sven Gothel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Sven Gothel nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 Sven Gothel 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. + */ +package com.jogamp.newt.impl.event; + +import com.jogamp.newt.event.NEWTEvent; + +/** + * Helper class to provide a NEWTEvent queue implementation with a NEWTEvent wrapper + * which notifies after sending the event for the invokeAndWait() semantics. + */ +public class NEWTEventTask { + NEWTEvent event; + Object notifyObject; + + public NEWTEventTask(NEWTEvent event, Object notifyObject) { + this.event = event ; + this.notifyObject = notifyObject ; + } + + public NEWTEvent get() { return event; } + + public void notifyIssuer() { + if(null != notifyObject) { + synchronized (notifyObject) { + notifyObject.notifyAll(); + } + } + } +} + diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 1807201a4..0e93fc0bd 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -487,6 +487,10 @@ public class GLWindow extends Window implements GLAutoDrawable { helper.removeGLEventListener(listener); } + public void invoke(boolean wait, GLRunnable glRunnable) { + helper.invoke(wait, glRunnable); + } + public void display() { display(false); } diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java index 235132460..2e339fd45 100644 --- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -36,6 +36,7 @@ package com.jogamp.newt.util; +import com.jogamp.common.util.RunnableTask; import com.jogamp.newt.Display; import com.jogamp.newt.impl.Debug; import java.util.*; @@ -107,10 +108,7 @@ public class EDTUtil { return null!=edt && edt.isRunning() ; } - public void invokeLater(Runnable task) { - if(task == null) { - return; - } + private void invokeLater(Runnable task) { synchronized(edtLock) { if(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) { tasks.add(task); @@ -122,21 +120,33 @@ public class EDTUtil { } } - public void invokeAndWait(Runnable task) { - invoke(true, task); - } - public void invoke(boolean wait, Runnable task) { if(task == null) { return; } - invokeLater(task); - if(wait) { - waitOnWorker(); + boolean doWait = wait && null!=edt && edt.isRunning() && edt != Thread.currentThread(); + Object lock = new Object(); + RunnableTask rTask = new RunnableTask(task, doWait?lock:null, true); + Throwable throwable = null; + synchronized(lock) { + invokeLater(rTask); + if( doWait ) { + try { + lock.wait(); + } catch (InterruptedException ie) { + throwable = ie; + } + } + } + if(null==throwable) { + throwable = rTask.getThrowable(); + } + if(null!=throwable) { + throw new RuntimeException(throwable); } } - public void waitOnWorker() { + public void waitUntilIdle() { synchronized(edtLock) { if(null!=edt && edt.isRunning() && tasks.size()>0 && edt != Thread.currentThread() ) { try { -- cgit v1.2.3