diff options
author | Sven Gothel <[email protected]> | 2010-09-10 05:33:17 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-09-10 05:33:17 +0200 |
commit | 63be4a40aa6ecfe9fbc6585acccbc6f6f6689377 (patch) | |
tree | 41bcd52797e1602ffa409079b7d1744a399f77b8 /src/newt/classes | |
parent | 340b1ceb07907be113e33c54d084e53ddc93e368 (diff) |
NEWT: Changed Lifecycle of Display/Screen
Display/Screen:
- Removed Display reusage by unique TLS key: type + name,
instead use user-responsibility or Destroy-When-Unused (usage reference count).
- Removed X11 Display TLS pool usage
- Display creation means i, incl the later native one (X11).
- Added reference counting as follows:
- Display's refCount: number it is referenced by Screen:
display.addReference()/display.removeReference()
- Screen's refCount: number it is referenced by Window:
screen.addReference()/screen.removeReference()
- Lazy creation using refcount 0 -> 1
All resources are created when they are needed.
This also removes redundant native Display/Screen objects,
ie in case of [AWT] reparenting.
- Default lifecycle is user-responsibility, ie no Destroy-When-Unused, where
Window may be destroyed unrecoverable, which removes the Screen reference only.
- If using optional Destroy-When-Unused a
Window may be destroyed unrecoverable, which removes the Screen reference:
Screen.removeReference();
IF Screen.refCount == 0 THEN
Screen.destroy();
Display.removeReference();
IF Display.refCount == 0 THEN
Display.destroy();
- Use Destroy-When-Unused lifecycle for all automatic created Display/Screen
instances (GLWindow, NewtCanvasAWT,..)
- Display/Screen destroy/create cycles valid,
ie you can reuse destroyed Display/Screen's
- EDTUtil:
- Created right away.
- Started always via invoke, if not running.
- DefaultEDTUtil:
- Simplified locking a bit locking on:
- edtLock for start/stop
- edtTasks for tasks queue
- invoke-wait doubles check shouldStop
- invoke-wait 'waiting' outside of edtLock
+++
NEWT: Cleanup
- Window.destroy/invalidate: deep -> unrecoverable
- Window.isNativeWindowValid() -> Window.isNativeValid()
to unify with Display/Screen
- Window.isDestroyed() -> Window.isValid()
to unify and simplify logic.
Returns false if destroy(true) has been called.
- NewtFactory.wrapDisplay(.. handle) -> NewtFactory.createDisplay(.. handle),
since it actually creates a compatible display.
+++
NativeWindow X11Util: Added non TLS createDisplay()/closeDisplay()
+++
TODO:
- Stabilize (many tests fail)
- OSX
Diffstat (limited to 'src/newt/classes')
34 files changed, 555 insertions, 422 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index b9ef93572..1c1fdd7ec 100644 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -69,111 +69,54 @@ public abstract class Display { return displayClass; } - // Unique Display for each thread - private static ThreadLocal currentDisplayMap = new ThreadLocal(); - - /** Returns the thread local display map */ - public static Map getCurrentDisplayMap() { - Map displayMap = (Map) currentDisplayMap.get(); - if(null==displayMap) { - displayMap = new HashMap(); - currentDisplayMap.set( displayMap ); + // Global Displays + private static ArrayList displayList = new ArrayList(); + private static int displaysActive = 0; + private static int serialno = 1; + + public static void dumpDisplayList(String prefix) { + synchronized(displayList) { + Iterator i = displayList.iterator(); + System.err.println(prefix+" DisplayList[] entries: "+displayList.size()+" - "+getThreadName()); + for(int j=0; i.hasNext(); j++) { + Display d = (Display) i.next(); + System.err.println(" ["+j+"] : "+d); + } } - return displayMap; } - /** maps the given display to the thread local display map - * and notifies all threads synchronized to this display map. */ - protected static Display setCurrentDisplay(Display display) { - Map displayMap = getCurrentDisplayMap(); - Display oldDisplay = null; - synchronized(displayMap) { - oldDisplay = (Display) displayMap.put(display.getFQName(), display); - displayMap.notifyAll(); + /** Returns the global display collection */ + public static Collection getAllDisplays() { + ArrayList list; + synchronized(displayList) { + list = (ArrayList) displayList.clone(); } - return oldDisplay; + return list; } - /** removes the mapping of the given name from the thread local display map - * and notifies all threads synchronized to this display map. */ - protected static Display removeCurrentDisplay(String type, String name) { - Map displayMap = getCurrentDisplayMap(); - Display oldDisplay = null; - synchronized(displayMap) { - oldDisplay = (Display) displayMap.remove(getFQName(type,name)); - displayMap.notifyAll(); + public static int getActiveDisplayNumber() { + synchronized(displayList) { + return displaysActive; } - return oldDisplay; - } - - /** Returns the thread local display mapped to the given name */ - public static Display getCurrentDisplay(String type, String name) { - Map displayMap = getCurrentDisplayMap(); - Display display = (Display) displayMap.get(getFQName(type,name)); - return display; - } - - public static void dumpDisplayMap(String prefix) { - Map displayMap = getCurrentDisplayMap(); - Set entrySet = displayMap.entrySet(); - Iterator i = entrySet.iterator(); - System.err.println(prefix+" DisplayMap[] entries: "+entrySet.size()+" - "+getThreadName()); - for(int j=0; i.hasNext(); j++) { - Map.Entry entry = (Map.Entry) i.next(); - System.err.println(" ["+j+"] "+entry.getKey()+" -> "+entry.getValue()); - } - } - - /** Returns the thread local display collection */ - public static Collection getCurrentDisplays() { - return getCurrentDisplayMap().values(); } /** Make sure to reuse a Display with the same name */ - protected static synchronized Display create(String type, String name, final long handle) { + protected static Display create(String type, String name, final long handle) { try { Class displayClass = getDisplayClass(type); - Display tmpDisplay = (Display) displayClass.newInstance(); - name = tmpDisplay.validateDisplayName(name, handle); - - if(DEBUG) { - dumpDisplayMap("Display.create("+getFQName(type, name)+") BEGIN"); - } - Display display = getCurrentDisplay(type, name); - if(null==display) { - display = tmpDisplay; - tmpDisplay = null; - display.name = name; - display.type=type; - display.refCount=0; - if(DEBUG) { - System.err.println("Display.create("+getFQName(type, name)+") NEW: refCount "+display.refCount+", "+display+" "+getThreadName()); - } - } else { - tmpDisplay = null; - if(DEBUG) { - System.err.println("Display.create("+getFQName(type, name)+") REUSE: refCount "+display.refCount+", "+display+" "+getThreadName()); - } - } - synchronized(display) { - display.refCount++; - if(null==display.aDevice) { - final Display f_dpy = display; - display.runOnEDTIfAvail(true, new Runnable() { - public void run() { - f_dpy.createNative(); - }}); - if(null==display.aDevice) { - throw new RuntimeException("Display.createNative() failed to instanciate an AbstractGraphicsDevice"); - } - setCurrentDisplay(display); - if(DEBUG) { - System.err.println("Display.create("+getFQName(type, name)+") CreateNative: "+display+" "+getThreadName()); - } - } + Display display = (Display) displayClass.newInstance(); + name = display.validateDisplayName(name, handle); + display.name = name; + display.type=type; + display.destroyWhenUnused=false; + synchronized(displayList) { + display.id = serialno++; + display.fqname = getFQName(display.id, display.type, display.name); + displayList.add(display); } + display.createEDTUtil(); if(DEBUG) { - dumpDisplayMap("Display.create("+getFQName(type, name)+") END"); + System.err.println("Display.create() NEW: "+display+" "+getThreadName()); } return display; } catch (Exception e) { @@ -181,98 +124,138 @@ public abstract class Display { } } + protected synchronized final void createNative() { + if(null==aDevice) { + if(DEBUG) { + System.out.println("Display.createNative() START ("+getThreadName()+", "+this+")"); + } + final Display f_dpy = this; + runOnEDTIfAvail(true, new Runnable() { + public void run() { + f_dpy.createNativeImpl(); + }}); + if(null==aDevice) { + throw new RuntimeException("Display.createNative() failed to instanciate an AbstractGraphicsDevice"); + } + if(DEBUG) { + System.out.println("Display.createNative() END ("+getThreadName()+", "+this+")"); + } + synchronized(displayList) { + displaysActive++; + } + } + } + protected boolean getShallRunOnEDT() { return true; } - public EDTUtil getEDTUtil() { - if( null == edtUtil ) { - synchronized (this) { - if( null == edtUtil ) { - if(NewtFactory.useEDT()) { - final Display f_dpy = this; - if ( ! DEBUG_TEST_EDT_MAINTHREAD ) { - Thread current = Thread.currentThread(); - edtUtil = new DefaultEDTUtil(current.getThreadGroup(), - "Display_"+getFQName(), - new Runnable() { - public void run() { - if(null!=f_dpy.getGraphicsDevice()) { - f_dpy.dispatchMessages(); - } } } ); - } else { - // Begin JAU EDT Test .. - MainThread.addPumpMessage(this, - new Runnable() { - public void run() { - if(null!=f_dpy.getGraphicsDevice()) { - f_dpy.dispatchMessages(); - } } } ); - edtUtil = MainThread.getSingleton(); - System.err.println("Display.getEDTUtil("+getFQName()+") Test EDT MainThread: "+edtUtil.getClass().getName()); - // End JAU EDT Test .. - } - edtUtil.start(); - } - } + protected void createEDTUtil() { + if(NewtFactory.useEDT()) { + if ( ! DEBUG_TEST_EDT_MAINTHREAD ) { + Thread current = Thread.currentThread(); + edtUtil = new DefaultEDTUtil(current.getThreadGroup(), "Display_"+getFQName(), dispatchMessagesRunnable); + } else { + // Begin JAU EDT Test .. + MainThread.addPumpMessage(this, dispatchMessagesRunnable); + edtUtil = MainThread.getSingleton(); + // End JAU EDT Test .. + } + if(DEBUG) { + System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName()); } } - return edtUtil; } - protected void releaseEDTUtil() { - if(null!=edtUtil) { - if ( DEBUG_TEST_EDT_MAINTHREAD ) { - MainThread.removePumpMessage(this); // JAU EDT Test .. - } - edtUtil.waitUntilStopped(); - edtUtil=null; - } + public final EDTUtil getEDTUtil() { + return edtUtil; } public void runOnEDTIfAvail(boolean wait, final Runnable task) { - EDTUtil _edtUtil = getEDTUtil(); - if(getShallRunOnEDT() && null!=_edtUtil) { - _edtUtil.invoke(wait, task); + if( getShallRunOnEDT() && null!=edtUtil ) { + edtUtil.invoke(wait, task); } else { task.run(); } } - public synchronized void destroy() { - if(DEBUG) { - dumpDisplayMap("Display.destroy("+getFQName()+") BEGIN"); - } - refCount--; - if(0==refCount) { - removeCurrentDisplay(type, name); + public synchronized final void destroy() { + if ( null != aDevice ) { + if(DEBUG) { + dumpDisplayList("Display.destroy("+getFQName()+") BEGIN"); + } + synchronized(displayList) { + displayList.remove(this); + displaysActive--; + } if(DEBUG) { - System.err.println("Display.destroy("+getFQName()+") REMOVE: "+this+" "+getThreadName()); + System.err.println("Display.destroy(): "+this+" "+getThreadName()); } final Display f_dpy = this; final EDTUtil f_edtUtil = edtUtil; runOnEDTIfAvail(true, new Runnable() { public void run() { - f_dpy.closeNative(); + f_dpy.closeNativeImpl(); if(null!=f_edtUtil) { f_edtUtil.stop(); } } } ); - releaseEDTUtil(); + if(null!=edtUtil) { + if ( DEBUG_TEST_EDT_MAINTHREAD ) { + MainThread.removePumpMessage(this); // JAU EDT Test .. + } + edtUtil.waitUntilStopped(); + edtUtil.reset(); + } aDevice = null; - } else { if(DEBUG) { - System.err.println("Display.destroy("+getFQName()+") KEEP: refCount "+refCount+", "+this+" "+getThreadName()); + dumpDisplayList("Display.destroy("+getFQName()+") END"); } } + } + + protected synchronized final int addReference() { if(DEBUG) { - dumpDisplayMap("Display.destroy("+getFQName()+") END"); + System.out.println("Display.addReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount+1)); + } + if ( 0 == refCount ) { + createNative(); + } + if(null == aDevice) { + throw new RuntimeException("Display.addReference() (refCount "+refCount+") null AbstractGraphicsDevice"); } + return ++refCount; } - protected abstract void createNative(); - protected abstract void closeNative(); + + protected synchronized final int removeReference() { + if(DEBUG) { + System.out.println("Display.removeReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount-1)); + } + refCount--; + if(0==refCount && destroyWhenUnused) { + destroy(); + } + return refCount; + } + + /** + * @return number of references by Screen + */ + public synchronized final int getReferenceCount() { + return refCount; + } + + public final boolean getDestroyWhenUnused() { return destroyWhenUnused; } + public final void setDestroyWhenUnused(boolean v) { destroyWhenUnused=v; } + + protected abstract void createNativeImpl(); + protected abstract void closeNativeImpl(); + + public final int getId() { + return id; + } public final String getType() { return type; @@ -283,35 +266,45 @@ public abstract class Display { } public final String getFQName() { - return getFQName(type, name); + return fqname; } - static final String nilString = "nil" ; + public static final String nilString = "nil" ; - protected String validateDisplayName(String name, long handle) { + public String validateDisplayName(String name, long handle) { if(null==name && 0!=handle) { name="wrapping-"+toHexString(handle); } return ( null == name ) ? nilString : name ; } - public static final String getFQName(String type, String name) { + public static final String getFQName(int id, String type, String name) { if(null==type) type=nilString; if(null==name) name=nilString; - return type+"_"+name; + StringBuffer sb = new StringBuffer(); + sb.append(type); + sb.append("_"); + sb.append(name); + sb.append("_"); + sb.append(id); + return sb.toString(); } - public long getHandle() { + public final long getHandle() { if(null!=aDevice) { return aDevice.getHandle(); } return 0; } - public AbstractGraphicsDevice getGraphicsDevice() { + public final AbstractGraphicsDevice getGraphicsDevice() { return aDevice; } + public final boolean isNativeValid() { + return null != aDevice; + } + public synchronized void pumpMessages() { dispatchMessages(); } @@ -338,8 +331,16 @@ public abstract class Display { private Object eventsLock = new Object(); private LinkedList/*<NEWTEvent>*/ events = new LinkedList(); + class DispatchMessagesRunnable implements Runnable { + public void run() { + Display.this.dispatchMessages(); + } + } + DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable(); + public void dispatchMessages() { - if(0==refCount) return; // in destruction .. + if(0==refCount) return; // no screens + if(null==getGraphicsDevice()) return; // no native device LinkedList/*<NEWTEvent>*/ _events = null; @@ -405,9 +406,12 @@ public abstract class Display { } protected EDTUtil edtUtil = null; + protected int id; protected String name; protected String type; - protected int refCount; + protected String fqname; + protected int refCount; // number of Display references by Screen + protected boolean destroyWhenUnused; protected AbstractGraphicsDevice aDevice; } diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java index 3959c6a8d..12dadc310 100644 --- a/src/newt/classes/com/jogamp/newt/NewtFactory.java +++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java @@ -145,12 +145,13 @@ public abstract class NewtFactory { if(null!=nParentConfig) { AbstractGraphicsScreen nParentScreen = nParentConfig.getScreen(); AbstractGraphicsDevice nParentDevice = nParentScreen.getDevice(); - Display display = NewtFactory.wrapDisplay(type, nParentDevice.getHandle()); + Display display = NewtFactory.createDisplay(type, nParentDevice.getHandle()); screen = NewtFactory.createScreen(type, display, nParentScreen.getIndex()); } else { Display display = NewtFactory.createDisplay(type, null); // local display screen = NewtFactory.createScreen(type, display, 0); // screen 0 } + screen.setDestroyWhenUnused(true); final Window win = createWindowImpl(type, nParentWindow, screen, caps, undecorated); win.setSize(nParentWindow.getWidth(), nParentWindow.getHeight()); @@ -177,6 +178,7 @@ public abstract class NewtFactory { protected static Window createWindowImpl(String type, Capabilities caps, boolean undecorated) { Display display = NewtFactory.createDisplay(type, null); // local display Screen screen = NewtFactory.createScreen(type, display, 0); // screen 0 + screen.setDestroyWhenUnused(true); return Window.create(type, null, 0, screen, caps, undecorated); } @@ -217,7 +219,7 @@ public abstract class NewtFactory { /** * Instantiate a Display entity using the native handle. */ - public static Display wrapDisplay(String type, long handle) { + public static Display createDisplay(String type, long handle) { return Display.create(type, null, handle); } diff --git a/src/newt/classes/com/jogamp/newt/OffscreenWindow.java b/src/newt/classes/com/jogamp/newt/OffscreenWindow.java index e85714d4f..d17f8df07 100644 --- a/src/newt/classes/com/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/com/jogamp/newt/OffscreenWindow.java @@ -62,7 +62,7 @@ public class OffscreenWindow extends Window implements SurfaceChangeable { } } - protected void closeNative() { + protected void closeNativeImpl() { // nop } diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java index 26342519e..e9697647d 100644 --- a/src/newt/classes/com/jogamp/newt/Screen.java +++ b/src/newt/classes/com/jogamp/newt/Screen.java @@ -40,6 +40,8 @@ import java.security.*; public abstract class Screen { + public static final boolean DEBUG = Debug.debug("Display"); + private static Class getScreenClass(String type) throws ClassNotFoundException { @@ -62,7 +64,7 @@ public abstract class Screen { return screenClass; } - protected static Screen create(String type, Display display, int idx) { + protected static Screen create(String type, Display display, final int idx) { try { if(usrWidth<0 || usrHeight<0) { usrWidth = Debug.getIntProperty("newt.ws.swidth", true, localACC); @@ -74,48 +76,105 @@ public abstract class Screen { Class screenClass = getScreenClass(type); Screen screen = (Screen) screenClass.newInstance(); screen.display = display; - screen.createNative(idx); - if(null==screen.aScreen) { - throw new RuntimeException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen"); - } + screen.idx = idx; return screen; } catch (Exception e) { throw new RuntimeException(e); } } - public synchronized void destroy() { - closeNative(); - display = null; - aScreen = null; + protected synchronized final void createNative() { + if(null == aScreen) { + if(DEBUG) { + System.out.println("Screen.createNative() START ("+Display.getThreadName()+", "+this+")"); + } + display.addReference(); + createNativeImpl(); + if(null == aScreen) { + throw new RuntimeException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen"); + } + if(DEBUG) { + System.out.println("Screen.createNative() END ("+Display.getThreadName()+", "+this+")"); + } + } + } + + public synchronized final void destroy() { + if ( null != aScreen ) { + closeNativeImpl(); + display.removeReference(); + aScreen = null; + } + } + + protected synchronized final int addReference() { + if(DEBUG) { + System.out.println("Screen.addReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount+1)); + } + if ( 0 == refCount ) { + createNative(); + } + if(null == aScreen) { + throw new RuntimeException("Screen.addReference() (refCount "+refCount+") null AbstractGraphicsScreen"); + } + return ++refCount; + } + + protected synchronized final int removeReference() { + if(DEBUG) { + System.out.println("Screen.removeReference() ("+Display.getThreadName()+"): "+refCount+" -> "+(refCount-1)); + } + refCount--; + if(0==refCount && getDestroyWhenUnused()) { + destroy(); + } + return refCount; + } + + /** + * @return number of references by Window + */ + public synchronized final int getReferenceCount() { + return refCount; } - protected abstract void createNative(int index); - protected abstract void closeNative(); + public final boolean getDestroyWhenUnused() { + return display.getDestroyWhenUnused(); + } + public final void setDestroyWhenUnused(boolean v) { + display.setDestroyWhenUnused(v); + } + + protected abstract void createNativeImpl(); + protected abstract void closeNativeImpl(); protected void setScreenSize(int w, int h) { System.out.println("Detected screen size "+w+"x"+h); width=w; height=h; } - public Display getDisplay() { + public final Display getDisplay() { return display; } - public int getIndex() { - return aScreen.getIndex(); + public final int getIndex() { + return idx; } - public AbstractGraphicsScreen getGraphicsScreen() { + public final AbstractGraphicsScreen getGraphicsScreen() { return aScreen; } + public final boolean isNativeValid() { + return null != aScreen; + } + /** * The actual implementation shall return the detected display value, * if not we return 800. * This can be overwritten with the user property 'newt.ws.swidth', */ - public int getWidth() { + public final int getWidth() { return (usrWidth>0) ? usrWidth : (width>0) ? width : 480; } @@ -124,12 +183,14 @@ public abstract class Screen { * if not we return 480. * This can be overwritten with the user property 'newt.ws.sheight', */ - public int getHeight() { + public final int getHeight() { return (usrHeight>0) ? usrHeight : (height>0) ? height : 480; } protected Display display; + protected int idx; protected AbstractGraphicsScreen aScreen; + protected int refCount; // number of Screen references by Window protected int width=-1, height=-1; // detected values: set using setScreenSize protected static int usrWidth=-1, usrHeight=-1; // property values: newt.ws.swidth and newt.ws.sheight private static AccessControlContext localACC = AccessController.getContext(); diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index d002791ca..3f07e63de 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -150,8 +150,9 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer protected String title = "Newt Window"; protected boolean undecorated = false; + protected boolean screenRefAdded = false; - private boolean createNative() { + private final boolean createNative() { if( null==screen || 0!=windowHandle || !visible ) { return 0 != windowHandle ; } @@ -159,7 +160,11 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer System.out.println("Window.createNative() START ("+getThreadName()+", "+this+")"); } if(validateParentWindowHandle()) { - Display dpy = getScreen().getDisplay(); + if(!screenRefAdded) { + // only once .. at 1st creation + screenRefAdded = true; + getScreen().addReference(); + } createNativeImpl(); setVisibleImpl(true); } @@ -219,7 +224,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer */ protected abstract void createNativeImpl(); - protected abstract void closeNative(); + protected abstract void closeNativeImpl(); public Capabilities getRequestedCapabilities() { return (Capabilities)caps.clone(); @@ -348,7 +353,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer windowLock.lock(); // if(windowLock.getRecursionCount() == 0) { // allow recursion to lock again, always - if(isDestroyed() || !isNativeWindowValid()) { + if(!isNativeValid()) { windowLock.unlock(); return LOCK_SURFACE_NOT_READY; } @@ -381,7 +386,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer * windowing related resources.<br></p> * <p> * all other resources and states are kept intact, - * ie listeners, parent handles and size, position etc.<br></p> + * ie listeners, parent handles, size, position and Screen reference.<br></p> * * @see #destroy(boolean) * @see #invalidate() @@ -391,49 +396,51 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer } /** - * @param deep If true, all resources, ie listeners, parent handles, size, position - * and the referenced NEWT screen and display, will be destroyed as well. Be aware that if you call - * this method with deep = true, you will not be able to regenerate the Window. + * Destroys the Window and it's children. + * @param unrecoverable If true, all resources, ie listeners, parent handles, + * size, position and reference to it's Screen will be destroyed as well. + * Otherwise you can recreate the window, via <code>setVisible(true)</code>. * @see #destroy() * @see #invalidate(boolean) + * @see #setVisible(boolean) */ - public void destroy(boolean deep) { - if(!isDestroyed()) { - runOnEDTIfAvail(true, new DestroyAction(deep)); + public void destroy(boolean unrecoverable) { + if(isValid()) { + runOnEDTIfAvail(true, new DestroyAction(unrecoverable)); } } class DestroyAction implements Runnable { - boolean deep; - public DestroyAction(boolean deep) { - this.deep = deep; + boolean unrecoverable; + public DestroyAction(boolean unrecoverable) { + this.unrecoverable = unrecoverable; } public void run() { windowLock(); try { if(DEBUG_IMPLEMENTATION) { - System.out.println("Window.destroy(deep: "+deep+") START "+getThreadName()+", "+Window.this); + System.out.println("Window.destroy(unrecoverable: "+unrecoverable+") START "+getThreadName()+", "+Window.this); } // Childs first .. synchronized(childWindowsLock) { for(Iterator i = childWindows.iterator(); i.hasNext(); ) { NativeWindow nw = (NativeWindow) i.next(); - System.out.println("Window.destroy(deep: "+deep+") CHILD BEGIN"); + System.out.println("Window.destroy(unrecoverable: "+unrecoverable+") CHILD BEGIN"); if(nw instanceof Window) { ((Window)nw).sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - if(deep) { - ((Window)nw).destroy(deep); + if(unrecoverable) { + ((Window)nw).destroy(unrecoverable); } } else { nw.destroy(); } - System.out.println("Window.destroy(deep: "+deep+") CHILD END"); + System.out.println("Window.destroy(unrecoverable: "+unrecoverable+") CHILD END"); } } // Now us .. - if(deep) { + if(unrecoverable) { synchronized(childWindowsLock) { childWindows = new ArrayList(); } @@ -444,24 +451,20 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer mouseListeners = new ArrayList(); keyListeners = new ArrayList(); } - Display dpy = null; Screen scr = null; if( null != screen && 0 != windowHandle ) { scr = screen; - dpy = screen.getDisplay(); - closeNative(); + closeNativeImpl(); } - invalidate(deep); - if(deep) { + invalidate(unrecoverable); + if(unrecoverable) { if(null!=scr) { - scr.destroy(); - } - if(null!=dpy) { - dpy.destroy(); + // only once .. at final destruction + scr.removeReference(); } } if(DEBUG_IMPLEMENTATION) { - System.out.println("Window.destroy(deep: "+deep+") END "+getThreadName()+", "+Window.this); + System.out.println("Window.destroy(unrecoverable: "+unrecoverable+") END "+getThreadName()+", "+Window.this); } } finally { windowUnlock(); @@ -486,18 +489,18 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer } /** - * @param deep if false only the native window handle is invalidated, otherwise all - * states (references and properties) are reset. Be aware that if you call - * this method with deep = true, you will not be able to regenerate the Window. + * @param unrecoverable If true, all states, size, position, parent handles, + * reference to it's Screen are reset. + * Otherwise you can recreate the window, via <code>setVisible(true)</code>. * @see #invalidate() * @see #destroy() * @see #destroy(boolean) */ - public void invalidate(boolean deep) { + public void invalidate(boolean unrecoverable) { windowLock(); try{ if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - String msg = new String("!!! Window Invalidate(deep: "+deep+") "+getThreadName()); + String msg = new String("!!! Window Invalidate(unrecoverable: "+unrecoverable+") "+getThreadName()); //System.out.println(msg); Exception e = new Exception(msg); e.printStackTrace(); @@ -506,7 +509,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer visible = false; fullscreen = false; - if(deep) { + if(unrecoverable) { screen = null; parentWindowHandle = 0; parentNativeWindow = null; @@ -523,13 +526,24 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer } } - /** @return true if the native window handle is valid and ready to operate */ - public boolean isNativeWindowValid() { - return 0 != windowHandle ; + /** @return true if the native window handle is valid and ready to operate, ie + * if the native window has been created, otherwise false. + * + * @see #setVisible(boolean) + * @see #destroy(boolean) + */ + public boolean isNativeValid() { + return null != screen && 0 != windowHandle ; } - public boolean isDestroyed() { - return null == screen ; + /** @return True if native window is valid, can be created or recovered. + * Otherwise false, ie this window is unrecoverable due to a <code>destroy(true)</code> call. + * + * @see #destroy(boolean) + * @see #setVisible(boolean) + */ + public boolean isValid() { + return null != screen ; } public boolean surfaceSwap() { @@ -713,7 +727,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer * this Screen is being used. */ public void reparentWindow(NativeWindow newParent, Screen newScreen) { - if(!isDestroyed()) { + if(isValid()) { runOnEDTIfAvail(true, new ReparentAction(newParent, newScreen)); if( isVisible() ) { sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener @@ -730,7 +744,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer public void run() { windowLock(); try{ - if( !isDestroyed() ) { + if( isValid() ) { if(!visible && childWindows.size()>0) { synchronized(childWindowsLock) { for(Iterator i = childWindows.iterator(); i.hasNext(); ) { @@ -805,7 +819,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer Exception ee = new Exception(msg); ee.printStackTrace(); } - if(!isDestroyed()) { + if(isValid()) { runOnEDTIfAvail(true, new VisibleAction(visible)); } } @@ -985,7 +999,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer } public void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) { - if(!getInnerWindow().isDestroyed()) { + if(getInnerWindow().isValid()) { getInnerWindow().getScreen().getDisplay().enqueueEvent(wait, event); } } @@ -1523,7 +1537,7 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - if(handleDestroyNotify && !isDestroyed()) { + if(handleDestroyNotify && isValid()) { destroy(); } diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 57647df5c..d7e75a5b9 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -55,7 +55,7 @@ import com.jogamp.newt.Window; import com.jogamp.newt.impl.Debug; public class NewtCanvasAWT extends java.awt.Canvas { - public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); + public static final boolean DEBUG = Debug.debug("Window"); NativeWindow parent = null; Window newtChild = null; @@ -93,7 +93,7 @@ public class NewtCanvasAWT extends java.awt.Canvas { class FocusActionImpl implements Runnable { public final boolean result = false; // NEWT shall always proceed requesting the native focus public void run() { - if(DEBUG_IMPLEMENTATION) { + if(DEBUG) { System.out.println("FocusActionImpl.run() "+Window.getThreadName()); } NewtCanvasAWT.this.requestFocusAWTParent(); @@ -150,7 +150,7 @@ public class NewtCanvasAWT extends java.awt.Canvas { super.addNotify(); disableBackgroundErase(); java.awt.Container cont = getContainer(this); - if(DEBUG_IMPLEMENTATION) { + if(DEBUG) { // if ( isShowing() == false ) -> Container was not visible yet. // if ( isShowing() == true ) -> Container is already visible. System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+ @@ -161,7 +161,7 @@ public class NewtCanvasAWT extends java.awt.Canvas { public void removeNotify() { java.awt.Container cont = getContainer(this); - if(DEBUG_IMPLEMENTATION) { + if(DEBUG) { System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont); } reparentWindow(false, cont); @@ -178,15 +178,19 @@ public class NewtCanvasAWT extends java.awt.Canvas { parent = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); } if(null!=parent) { - if(DEBUG_IMPLEMENTATION) { + if(DEBUG) { System.err.println("NewtCanvasAWT.reparentWindow: "+newtChild); } setSize(cont.getWidth(), cont.getHeight()); newtChild.setSize(cont.getWidth(), cont.getHeight()); Screen screen = null; - if( !newtChild.isNativeWindowValid() ) { - screen = NewtFactoryAWT.createCompatibleScreen(parent); + if( !newtChild.isNativeValid() ) { + Screen currentScreen = newtChild.getScreen(); + screen = NewtFactoryAWT.createCompatibleScreen(parent, currentScreen); + if( currentScreen != screen ) { + screen.setDestroyWhenUnused(true); + } } newtChild.reparentWindow(parent, screen); newtChild.setVisible(true); diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java index 6409ab7a8..bd5a6cd73 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java @@ -86,15 +86,57 @@ public class NewtFactoryAWT extends NewtFactory { } public static Screen createCompatibleScreen(NativeWindow parent) { + return createCompatibleScreen(parent, null); + } + + public static Screen createCompatibleScreen(NativeWindow parent, Screen childScreen) { // Get parent's NativeWindow details AWTGraphicsConfiguration parentConfig = (AWTGraphicsConfiguration) parent.getGraphicsConfiguration(); AWTGraphicsScreen parentScreen = (AWTGraphicsScreen) parentConfig.getScreen(); AWTGraphicsDevice parentDevice = (AWTGraphicsDevice) parentScreen.getDevice(); - // Prep NEWT's Display and Screen according to the parent final String type = NativeWindowFactory.getNativeWindowType(true); - Display display = NewtFactory.wrapDisplay(type, parentDevice.getHandle()); + + if(null != childScreen) { + // check if child Display/Screen is compatible already + Display childDisplay = childScreen.getDisplay(); + String parentDisplayName = childDisplay.validateDisplayName(null, parentDevice.getHandle()); + String childDisplayName = childDisplay.getName(); + boolean displayEqual = parentDisplayName.equals( childDisplayName ); + boolean screenEqual = parentScreen.getIndex() == childScreen.getIndex(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("NewtFactoryAWT.createCompatibleScreen: Display: "+ + parentDisplayName+" =? "+childDisplayName+" : "+displayEqual+"; Screen: "+ + parentScreen.getIndex()+" =? "+childScreen.getIndex()+" : "+screenEqual); + } + if( displayEqual && screenEqual ) { + // match: display/screen + return childScreen; + } + } + + // Prep NEWT's Display and Screen according to the parent + Display display = NewtFactory.createDisplay(type, parentDevice.getHandle()); return NewtFactory.createScreen(type, display, parentScreen.getIndex()); } + + public static boolean isScreenCompatible(NativeWindow parent, Screen childScreen) { + // Get parent's NativeWindow details + AWTGraphicsConfiguration parentConfig = (AWTGraphicsConfiguration) parent.getGraphicsConfiguration(); + AWTGraphicsScreen parentScreen = (AWTGraphicsScreen) parentConfig.getScreen(); + AWTGraphicsDevice parentDevice = (AWTGraphicsDevice) parentScreen.getDevice(); + + Display childDisplay = childScreen.getDisplay(); + String parentDisplayName = childDisplay.validateDisplayName(null, parentDevice.getHandle()); + String childDisplayName = childDisplay.getName(); + if( ! parentDisplayName.equals( childDisplayName ) ) { + return false; + } + + if( parentScreen.getIndex() != childScreen.getIndex() ) { + return false; + } + return true; + } } diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java index 9f0944ea0..c5a60226f 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java @@ -104,7 +104,7 @@ public class AWTParentWindowAdapter if(DEBUG_IMPLEMENTATION) { System.out.println("AWT: hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed); } - if(!newtWindow.isDestroyed()) { + if(newtWindow.isValid()) { newtWindow.runOnEDTIfAvail(false, new Runnable() { public void run() { newtWindow.setVisible(showing); diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java index 875401544..5df853610 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -131,7 +131,7 @@ public class AWTWindowAdapter } /** if(null==newtListener) { - if(!newtWindow.isDestroyed()) { + if(newtWindow.isValid()) { newtWindow.runOnEDTIfAvail(false, new Runnable() { public void run() { newtWindow.setVisible(true); @@ -148,7 +148,7 @@ public class AWTWindowAdapter } /** if(null==newtListener) { - if(!newtWindow.isDestroyed()) { + if(newtWindow.isValid()) { newtWindow.runOnEDTIfAvail(false, new Runnable() { public void run() { newtWindow.setVisible(false); diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java index 92c4e53eb..c9c6c63fc 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java @@ -44,7 +44,7 @@ public class AWTDisplay extends Display { public AWTDisplay() { } - protected void createNative() { + protected void createNativeImpl() { aDevice = (AWTGraphicsDevice) AWTGraphicsDevice.createDevice(null); // default } @@ -52,7 +52,7 @@ public class AWTDisplay extends Display { aDevice = d; } - protected void closeNative() { } + protected void closeNativeImpl() { } protected boolean getShallRunOnEDT() { return false; diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java index 8702686c0..eec83d721 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTScreen.java @@ -42,7 +42,7 @@ public class AWTScreen extends Screen { public AWTScreen() { } - protected void createNative(int index) { + protected void createNativeImpl() { aScreen = new AWTGraphicsScreen((AWTGraphicsDevice)display.getGraphicsDevice()); DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode(); @@ -60,6 +60,6 @@ public class AWTScreen extends Screen { super.setScreenSize(w, h); } - protected void closeNative() { } + protected void closeNativeImpl() { } } diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java index db55aee6f..9da1eb860 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java @@ -148,7 +148,7 @@ public class AWTWindow extends Window { this.windowHandle = 1; // just a marker .. } - protected void closeNative() { + protected void closeNativeImpl() { this.windowHandle = 0; // just a marker .. if(null!=container) { runOnEDT(true, new Runnable() { diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java index d19aaf796..c8e69dac6 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java @@ -58,7 +58,7 @@ public class Display extends com.jogamp.newt.Display { public Display() { } - protected void createNative() { + protected void createNativeImpl() { synchronized(Display.class) { if(0==initCounter) { displayHandle = CreateDisplay(); @@ -71,7 +71,7 @@ public class Display extends com.jogamp.newt.Display { aDevice = new DefaultGraphicsDevice(NativeWindowFactory.TYPE_DEFAULT, displayHandle); } - protected void closeNative() { + protected void closeNativeImpl() { if(0==displayHandle) { throw new NativeWindowException("displayHandle null; initCnt "+initCounter); } diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java index 3d9a5a309..3aded5df3 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Screen.java @@ -45,13 +45,13 @@ public class Screen extends com.jogamp.newt.Screen { public Screen() { } - protected void createNative(int index) { + protected void createNativeImpl() { AbstractGraphicsDevice adevice = getDisplay().getGraphicsDevice(); - GetScreenInfo(adevice.getHandle(), index); - aScreen = new DefaultGraphicsScreen(adevice, index); + GetScreenInfo(adevice.getHandle(), idx); + aScreen = new DefaultGraphicsScreen(adevice, idx); } - protected void closeNative() { } + protected void closeNativeImpl() { } //---------------------------------------------------------------------- // Internals only diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java index 14621807a..5f40a35ae 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java @@ -67,7 +67,7 @@ public class Window extends com.jogamp.newt.Window { } } - protected void closeNative() { + protected void closeNativeImpl() { if(0!=surfaceHandle) { synchronized(Window.class) { CloseSurface(getDisplayHandle(), surfaceHandle); diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java index 11f825282..9b8689114 100644 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java @@ -65,31 +65,24 @@ public class MacDisplay extends Display { dispatchMessages0(); } - protected void createNative() { + protected void createNativeImpl() { aDevice = new MacOSXGraphicsDevice(); } - protected void closeNative() { } + protected void closeNativeImpl() { } - public EDTUtil getEDTUtil() { - if( null == edtUtil ) { - synchronized (this) { - if( null == edtUtil ) { - if(NewtFactory.useEDT()) { - final Display f_dpy = this; - MainThread.addPumpMessage(this, - new Runnable() { - public void run() { - if(null!=f_dpy.getGraphicsDevice()) { - f_dpy.dispatchMessages(); - } } } ); - edtUtil = MainThread.getSingleton(); - edtUtil.start(); - } - } - } + protected void createEDTUtil() { + if(NewtFactory.useEDT()) { + final Display f_dpy = this; + MainThread.addPumpMessage(this, + new Runnable() { + public void run() { + if(null!=f_dpy.getGraphicsDevice()) { + f_dpy.dispatchMessages(); + } } } ); + edtUtil = MainThread.getSingleton(); + edtUtil.start(); } - return edtUtil; } protected void releaseEDTUtil() { diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java index d7deb13ee..317a3161c 100644 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacScreen.java @@ -44,12 +44,12 @@ public class MacScreen extends Screen { public MacScreen() { } - protected void createNative(int index) { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); - setScreenSize(getWidthImpl0(getIndex()), getHeightImpl0(getIndex())); + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx); + setScreenSize(getWidthImpl0(idx), getHeightImpl0(idx)); } - protected void closeNative() { } + protected void closeNativeImpl() { } private static native int getWidthImpl0(int scrn_idx); private static native int getHeightImpl0(int scrn_idx); diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java index a8e6febf5..7571c05be 100644 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -149,7 +149,7 @@ public class MacWindow extends Window { } } - protected void closeNative() { + protected void closeNativeImpl() { nsViewLock.lock(); try { if(DEBUG_IMPLEMENTATION) { System.out.println("MacWindow.CloseAction "+Thread.currentThread().getName()); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java index c2d323e56..8b8ce1f41 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java @@ -56,7 +56,7 @@ public class Display extends com.jogamp.newt.Display { public Display() { } - protected void createNative() { + protected void createNativeImpl() { long handle = CreateDisplay(Screen.fixedWidth, Screen.fixedHeight); if (handle == EGL.EGL_NO_DISPLAY) { throw new NativeWindowException("BC EGL CreateDisplay failed"); @@ -64,7 +64,7 @@ public class Display extends com.jogamp.newt.Display { aDevice = new EGLGraphicsDevice(handle); } - protected void closeNative() { + protected void closeNativeImpl() { if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) { DestroyDisplay(aDevice.getHandle()); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java index e30896468..f38e7b4dc 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Screen.java @@ -45,12 +45,12 @@ public class Screen extends com.jogamp.newt.Screen { public Screen() { } - protected void createNative(int index) { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx); setScreenSize(fixedWidth, fixedHeight); } - protected void closeNative() { } + protected void closeNativeImpl() { } //---------------------------------------------------------------------- // Internals only diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java index ca06699f5..d6b802a85 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java @@ -64,7 +64,7 @@ public class Window extends com.jogamp.newt.Window { } } - protected void closeNative() { + protected void closeNativeImpl() { if(0!=windowHandleClose) { CloseWindow(getDisplayHandle(), windowHandleClose); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java index 2ab30773f..1845342a0 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java @@ -57,7 +57,7 @@ public class KDDisplay extends Display { public KDDisplay() { } - protected void createNative() { + protected void createNativeImpl() { // FIXME: map name to EGL_*_DISPLAY long handle = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); if (handle == EGL.EGL_NO_DISPLAY) { @@ -69,7 +69,7 @@ public class KDDisplay extends Display { aDevice = new EGLGraphicsDevice(handle); } - protected void closeNative() { + protected void closeNativeImpl() { if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) { EGL.eglTerminate(aDevice.getHandle()); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java index d570d9f5b..c7db047f6 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDScreen.java @@ -44,11 +44,11 @@ public class KDScreen extends Screen { public KDScreen() { } - protected void createNative(int index) { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx); } - protected void closeNative() { } + protected void closeNativeImpl() { } // elevate access to this package .. protected void setScreenSize(int w, int h) { diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java index 2f534548b..43e4ac021 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java @@ -78,7 +78,7 @@ public class KDWindow extends Window { windowHandleClose = eglWindowHandle; } - protected void closeNative() { + protected void closeNativeImpl() { if(0!=windowHandleClose) { CloseWindow(windowHandleClose, windowUserData); windowUserData=0; diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java index ef033d1c8..cfc35e1f8 100644 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java @@ -60,11 +60,11 @@ public class WindowsDisplay extends Display { public WindowsDisplay() { } - protected void createNative() { + protected void createNativeImpl() { aDevice = new WindowsGraphicsDevice(); } - protected void closeNative() { + protected void closeNativeImpl() { // Can't do .. only at application shutdown // UnregisterWindowClass0(getWindowClassAtom(), getHInstance()); } diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java index 1b4be0d55..2197667cd 100644 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java @@ -45,12 +45,12 @@ public class WindowsScreen extends Screen { public WindowsScreen() { } - protected void createNative(int index) { - aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); - setScreenSize(getWidthImpl0(getIndex()), getHeightImpl0(getIndex())); + protected void createNativeImpl() { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), idx); + setScreenSize(getWidthImpl0(idx), getHeightImpl0(idx)); } - protected void closeNative() { } + protected void closeNativeImpl() { } private native int getWidthImpl0(int scrn_idx); private native int getHeightImpl0(int scrn_idx); diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java index 69cd62201..15d9ac8b0 100644 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -115,14 +115,14 @@ public class WindowsWindow extends Window { } } - protected void closeNative() { + protected void closeNativeImpl() { if (hdc != 0) { if(windowHandleClose != 0) { try { ReleaseDC0(windowHandleClose, hdc); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + Exception e = new Exception("closeNativeImpl failed - "+Thread.currentThread().getName(), t); e.printStackTrace(); } } @@ -134,7 +134,7 @@ public class WindowsWindow extends Window { DestroyWindow0(windowHandleClose); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + Exception e = new Exception("closeNativeImpl failed - "+Thread.currentThread().getName(), t); e.printStackTrace(); } } finally { diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java index 6701d6c8e..22b5e8470 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java @@ -61,26 +61,26 @@ public class X11Display extends Display { public X11Display() { } - protected String validateDisplayName(String name, long handle) { + public String validateDisplayName(String name, long handle) { return X11Util.validateDisplayName(name, handle); } - protected void createNative() { - long handle = X11Util.createThreadLocalDisplay(name); + protected void createNativeImpl() { + long handle = X11Util.createDisplay(name); if( 0 == handle ) { throw new RuntimeException("Error creating display: "+name); } try { CompleteDisplay0(handle); } catch(RuntimeException e) { - X11Util.closeThreadLocalDisplay(name); + X11Util.closeDisplay(handle); throw e; } aDevice = new X11GraphicsDevice(handle); } - protected void closeNative() { - X11Util.closeThreadLocalDisplay(name); + protected void closeNativeImpl() { + X11Util.closeDisplay(getHandle()); } protected void dispatchMessagesNative() { diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java index 453d8e5e1..aa53ea5d0 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Screen.java @@ -46,17 +46,17 @@ public class X11Screen extends Screen { public X11Screen() { } - protected void createNative(int index) { - long handle = GetScreen0(display.getHandle(), index); + protected void createNativeImpl() { + long handle = GetScreen0(display.getHandle(), idx); if (handle == 0 ) { - throw new RuntimeException("Error creating screen: "+index); + throw new RuntimeException("Error creating screen: "+idx); } - aScreen = new X11GraphicsScreen((X11GraphicsDevice)getDisplay().getGraphicsDevice(), index); - setScreenSize(getWidth0(display.getHandle(), index), - getHeight0(display.getHandle(), index)); + aScreen = new X11GraphicsScreen((X11GraphicsDevice)getDisplay().getGraphicsDevice(), idx); + setScreenSize(getWidth0(display.getHandle(), idx), + getHeight0(display.getHandle(), idx)); } - protected void closeNative() { } + protected void closeNativeImpl() { } //---------------------------------------------------------------------- // Internals only diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java index 7a770f770..894de9ae5 100644 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -67,7 +67,7 @@ public class X11Window extends Window { windowHandleClose = windowHandle; } - protected void closeNative() { + protected void closeNativeImpl() { if(0!=windowHandleClose && null!=getScreen() ) { X11Display display = (X11Display) getScreen().getDisplay(); try { @@ -75,7 +75,7 @@ public class X11Window extends Window { display.getJavaObjectAtom(), display.getWindowDeleteAtom()); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + Exception e = new Exception("closeNativeImpl failed - "+Thread.currentThread().getName(), t); e.printStackTrace(); } } finally { diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 99b4314a3..2aca37cab 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -82,8 +82,8 @@ public class GLWindow extends Window implements GLAutoDrawable { if( !windowIsLocked() && null == getAnimator() ) { destroy(); } else { - sendDestroy = true; - } + sendDestroy = true; + } } }); } @@ -125,12 +125,12 @@ public class GLWindow extends Window implements GLAutoDrawable { return new GLWindow(window); } - public boolean isNativeWindowValid() { - return (null!=window)?window.isNativeWindowValid():false; + public boolean isNativeValid() { + return (null!=window)?window.isNativeValid():false; } - public boolean isDestroyed() { - return (null!=window)?window.isDestroyed():true; + public boolean isValid() { + return (null!=window)?window.isValid():true; } public final Window getInnerWindow() { @@ -145,7 +145,7 @@ public class GLWindow extends Window implements GLAutoDrawable { shouldNotCallThis(); } - protected void closeNative() { + protected void closeNativeImpl() { shouldNotCallThis(); } @@ -158,23 +158,23 @@ public class GLWindow extends Window implements GLAutoDrawable { private DisposeAction disposeAction = new DisposeAction(); class DestroyAction implements Runnable { - boolean deep; - public DestroyAction(boolean deep) { - this.deep = deep; + boolean unrecoverable; + public DestroyAction(boolean unrecoverable) { + this.unrecoverable = unrecoverable; } public void run() { // Lock: Have to cover whole workflow (dispose all, context, drawable and window) windowLock(); try { - if( isDestroyed() ) { + if( !isValid() ) { return; // nop } if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - Exception e1 = new Exception("GLWindow.destroy("+deep+") "+Thread.currentThread()+", start: "+GLWindow.this); + Exception e1 = new Exception("GLWindow.destroy("+unrecoverable+") "+Thread.currentThread()+", start: "+GLWindow.this); e1.printStackTrace(); } - if( window.isNativeWindowValid() && null != drawable && drawable.isRealized() ) { + if( window.isNativeValid() && null != drawable && drawable.isRealized() ) { if( null != context && context.isCreated() ) { // Catch dispose GLExceptions by GLEventListener, just 'print' them // so we can continue with the destruction. @@ -193,14 +193,14 @@ public class GLWindow extends Window implements GLAutoDrawable { } if(null!=window) { - window.destroy(deep); + window.destroy(unrecoverable); } - if(deep) { + if(unrecoverable) { helper=null; } if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - System.out.println("GLWindow.destroy("+deep+") "+Thread.currentThread()+", fin: "+GLWindow.this); + System.out.println("GLWindow.destroy("+unrecoverable+") "+Thread.currentThread()+", fin: "+GLWindow.this); } } finally { windowUnlock(); @@ -208,15 +208,9 @@ public class GLWindow extends Window implements GLAutoDrawable { } } - /** - * @param deep If true, all resources, ie listeners, parent handles, size, position - * and the referenced NEWT screen and display, will be destroyed as well. Be aware that if you call - * this method with deep = true, you will not be able to regenerate the Window. - * @see #destroy() - */ - public void destroy(boolean deep) { - if( !isDestroyed() ) { - runOnEDTIfAvail(true, new DestroyAction(deep)); + public void destroy(boolean unrecoverable) { + if( isValid() ) { + runOnEDTIfAvail(true, new DestroyAction(unrecoverable)); } } @@ -269,7 +263,7 @@ public class GLWindow extends Window implements GLAutoDrawable { } public void setVisible(boolean visible) { - if(!isDestroyed()) { + if(isValid()) { runOnEDTIfAvail(true, new VisibleAction(visible)); } } @@ -512,17 +506,17 @@ public class GLWindow extends Window implements GLAutoDrawable { if( null == window ) { return; } if(sendDestroy || ( null!=window && window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) ) { - sendDestroy=false; - destroy(); - return; - } + sendDestroy=false; + destroy(); + return; + } if( null == context && window.isVisible() ) { // retry native window and drawable/context creation setVisible(true); } - if( window.isVisible() && window.isNativeWindowValid() && null != context ) { + if( window.isVisible() && window.isNativeValid() && null != context ) { if(forceReshape) { sendReshape = true; } diff --git a/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java b/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java index 87dfdb9d8..96bfc50e0 100644 --- a/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/DefaultEDTUtil.java @@ -47,8 +47,8 @@ public class DefaultEDTUtil implements EDTUtil { private ThreadGroup threadGroup; private volatile boolean shouldStop = false; private EventDispatchThread edt = null; - private Object edtLock = new Object(); - private ArrayList tasks = new ArrayList(); // one shot tasks + private Object edtLock = new Object(); // locking the EDT start/stop state + private ArrayList edtTasks = new ArrayList(); // one shot tasks private String name; private Runnable pumpMessages; @@ -56,123 +56,137 @@ public class DefaultEDTUtil implements EDTUtil { this.threadGroup = tg; this.name=new String(Thread.currentThread().getName()+"-"+"EDT-"+name); this.pumpMessages=pumpMessages; + this.edt = new EventDispatchThread(threadGroup, name); } - public void start() { + public final void reset() { synchronized(edtLock) { - if(null==edt) { - edt = new EventDispatchThread(threadGroup, name); + waitUntilStopped(); + if(edtTasks.size()>0) { + throw new RuntimeException("Remaining EDTTasks: "+edtTasks.size()); } + this.edt = new EventDispatchThread(threadGroup, name); + } + } + + public final void start() { + synchronized(edtLock) { if(!edt.isRunning()) { shouldStop = false; edt.start(); + if(DEBUG) { + System.out.println(Thread.currentThread()+": EDT START"); + } } - edtLock.notifyAll(); } } - public void stop() { + public final void stop() { synchronized(edtLock) { - if(null!=edt && edt.isRunning()) { + if(edt.isRunning()) { shouldStop = true; + if(DEBUG) { + System.out.println(Thread.currentThread()+": EDT signal STOP"); + } } edtLock.notifyAll(); - if(DEBUG) { - System.out.println(Thread.currentThread()+": EDT signal STOP"); - } } } - public boolean isCurrentThreadEDT() { - return null!=edt && edt == Thread.currentThread(); - } - - public boolean isRunning() { - return null!=edt && edt.isRunning() ; + public final boolean isCurrentThreadEDT() { + return edt == Thread.currentThread(); } - private void invokeLater(Runnable task) { - synchronized(edtLock) { - if(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) { - tasks.add(task); - edtLock.notifyAll(); - } else { - // if !running or isEDTThread, do it right away - task.run(); - } - } + public final boolean isRunning() { + return !shouldStop && edt.isRunning() ; } public void invoke(boolean wait, Runnable task) { if(task == null) { return; } - 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 ) { + RunnableTask rTask = null; + Object rTaskLock = new Object(); + synchronized(rTaskLock) { // lock the optional task execution + synchronized(edtLock) { // lock the EDT status + start(); // start if not started yet + if(isRunning() && edt != Thread.currentThread() ) { + rTask = new RunnableTask(task, wait?rTaskLock:null, true); + synchronized(edtTasks) { + edtTasks.add(rTask); + edtTasks.notifyAll(); + } + } else { + // if !running or isEDTThread, do it right away + wait = false; + task.run(); + } + } + // wait until task finished, if requested + // and no stop() call slipped through. + if( wait && !shouldStop ) { try { - lock.wait(); + rTaskLock.wait(); } catch (InterruptedException ie) { throwable = ie; } + if(null==throwable) { + throwable = rTask.getThrowable(); + } + if(null!=throwable) { + throw new RuntimeException(throwable); + } } } - if(null==throwable) { - throwable = rTask.getThrowable(); - } - if(null!=throwable) { - throw new RuntimeException(throwable); - } } public void waitUntilIdle() { - synchronized(edtLock) { - if(null!=edt && edt.isRunning() && tasks.size()>0 && edt != Thread.currentThread() ) { - try { - edtLock.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); + if(edt.isRunning() && edt != Thread.currentThread()) { + synchronized(edtTasks) { + while(edt.isRunning() && edtTasks.size()>0) { + try { + edtTasks.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } } } } } public void waitUntilStopped() { - synchronized(edtLock) { - while(null!=edt && edt.isRunning() && edt != Thread.currentThread() ) { - try { - edtLock.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); + if(edt.isRunning() && edt != Thread.currentThread() ) { + synchronized(edtLock) { + while(edt.isRunning()) { + try { + edtLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } } } } } class EventDispatchThread extends Thread { - boolean isRunning = false; + volatile boolean isRunning = false; public EventDispatchThread(ThreadGroup tg, String name) { super(tg, name); } - public synchronized boolean isRunning() { + public final boolean isRunning() { return isRunning; } public void start() throws IllegalThreadStateException { - synchronized(this) { - isRunning = true; - } + isRunning = true; super.start(); } /** - * Utilizing edtLock only for local resources and task execution, + * Utilizing locking only on edtTasks and its execution, * not for event dispatching. */ public void run() { @@ -180,41 +194,39 @@ public class DefaultEDTUtil implements EDTUtil { System.out.println(Thread.currentThread()+": EDT run() START"); } try { - while(!shouldStop) { - // wait for something todo - while(!shouldStop && tasks.size()==0) { - synchronized(edtLock) { - if(!shouldStop && tasks.size()==0) { - try { - edtLock.wait(defaultEDTPollGranularity); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - pumpMessages.run(); // event dispatch + do { + // event dispatch + if(!shouldStop) { + pumpMessages.run(); } - if(!shouldStop && tasks.size()>0) { - synchronized(edtLock) { - if(!shouldStop && tasks.size()>0) { - Runnable task = (Runnable) tasks.remove(0); - task.run(); // FIXME: could be run outside of lock - edtLock.notifyAll(); + // wait and work on tasks + synchronized(edtTasks) { + // wait for tasks + while(!shouldStop && edtTasks.size()==0) { + try { + edtTasks.wait(defaultEDTPollGranularity); + } catch (InterruptedException e) { + e.printStackTrace(); } } - pumpMessages.run(); // event dispatch + // execute one task, if available + if(edtTasks.size()>0) { + Runnable task = (Runnable) edtTasks.remove(0); + task.run(); + edtTasks.notifyAll(); + } } - } + } while(!shouldStop || edtTasks.size()>0) ; } catch (Throwable t) { // handle errors .. shouldStop = true; throw new RuntimeException(t); } finally { - synchronized(this) { + // check for tasks + // sync for waitUntilStopped() + synchronized(edtLock) { isRunning = !shouldStop; - } - if(!isRunning) { - synchronized(edtLock) { + if(!isRunning) { edtLock.notifyAll(); } } diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java index 1af102f43..91f35459b 100644 --- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -44,6 +44,8 @@ public interface EDTUtil { public static final long defaultEDTPollGranularity = 10; // 10ms, 1/100s + public void reset(); + public void start(); public void stop(); @@ -52,6 +54,7 @@ public interface EDTUtil { public boolean isRunning(); + /** Shall start the thread if not running */ public void invoke(boolean wait, Runnable task); public void waitUntilIdle(); diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java index ba886ade8..cb5c87a89 100644 --- a/src/newt/classes/com/jogamp/newt/util/MainThread.java +++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java @@ -243,6 +243,10 @@ public class MainThread implements EDTUtil { } } + public void reset() { + // nop + } + public void start() { // nop } |