diff options
author | Sven Gothel <[email protected]> | 2013-03-19 00:33:00 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-03-19 00:33:00 +0100 |
commit | 81cbcdc8469143587b2044661dd613c798ae02ba (patch) | |
tree | 813982c77435a9ca75225019b8ea0ebe3d22b08c /src/newt/classes | |
parent | f354fb204d8973453c538dda78a2c82c87be61dc (diff) |
OSX/NEWT: Following CALayer streaming design, i.e. issue NSWindow/NSView Ops on main-thread w/o blocking; NEWT/WindowImpl: Volatile multithreaded mutable values
Similar to commits:
28c6472335b924080d638b33a28f8f4eedb459b1
f354fb204d8973453c538dda78a2c82c87be61dc
main-thread operations cannot block main-thread.
Luckily we are able to create the NSWindow and NSView instance uninitialized (deferred) on the current thread,
while issuing their initialization on the main-thread w/o blocking.
Further more a size glitch is fixed, which didn't take the title bar into account.
+++
NEWT/WindowImpl: Volatile multithreaded mutable values
Since position, size and other attributes might get changes off-thread, these fields needs to be volatile.
Diffstat (limited to 'src/newt/classes')
-rw-r--r-- | src/newt/classes/jogamp/newt/DefaultEDTUtil.java | 1 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/WindowImpl.java | 17 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java | 165 |
3 files changed, 109 insertions, 74 deletions
diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index 3c015d3ec..651522799 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -332,6 +332,7 @@ public class DefaultEDTUtil implements EDTUtil { validateNoRecursiveLocksHold(); if(!task.hasWaiter() && null != task.getThrowable()) { // at least dump stack-trace in case nobody waits for result + System.err.println("DefaultEDT.run(): Catched exception occured on thread "+Thread.currentThread().getName()+": "+task.toString()); task.getThrowable().printStackTrace(); } } diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 448b192a2..c01f880fc 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -82,9 +82,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer /** Timeout of queued events (repaint and resize) */ static final long QUEUED_EVENT_TO = 1200; // ms - + + // + // Volatile: Multithread Mutable Access + // private volatile long windowHandle = 0; // lifecycle critical private volatile boolean visible = false; // lifecycle critical + private volatile boolean hasFocus = false; + private volatile int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user + private volatile int x = 64, y = 64; // client-area pos w/o insets + private volatile Insets insets = new Insets(); // insets of decoration (if top-level && decorated) + private RecursiveLock windowLock = LockFactory.createRecursiveLock(); // Window instance wide lock private int surfaceLockCount = 0; // surface lock recursion count @@ -95,12 +103,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private AbstractGraphicsConfiguration config = null; // control access due to delegation protected CapabilitiesImmutable capsRequested = null; protected CapabilitiesChooser capabilitiesChooser = null; // default null -> default - private boolean fullscreen = false, hasFocus = false, brokenFocusChange = false; - private int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user - private int x = 64, y = 64; // client-area pos w/o insets + private boolean fullscreen = false, brokenFocusChange = false; private boolean autoPosition = true; // default: true (allow WM to choose top-level position, if not set by user) - private Insets insets = new Insets(); // insets of decoration (if top-level && decorated) - + private int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets private NativeWindow nfs_parent = null; // non fullscreen parent, in case explicit reparenting is performed (offscreen) private String title = "Newt Window"; diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 6e9335f08..d3a92e023 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -49,7 +49,6 @@ import jogamp.newt.WindowImpl; import jogamp.newt.driver.DriverClearFocus; import jogamp.newt.driver.DriverUpdatePosition; -import com.jogamp.common.util.Function; import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.KeyEvent; @@ -86,7 +85,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl sscSurfaceHandle = 0; isOffscreenInstance = false; if (0 != handle) { - OSXUtil.RunOnMainThread(true, new Runnable() { + OSXUtil.RunOnMainThread(false, new Runnable() { public void run() { close0( handle ); } } ); @@ -101,18 +100,31 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override protected int lockSurfaceImpl() { - if(!isOffscreenInstance) { - return lockSurface0(getWindowHandle()) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY; + /** + * if( isOffscreenInstance ) { + * return LOCK_SUCCESS; + * } + */ + final long w = getWindowHandle(); + final long v = surfaceHandle; + if( 0 != v && 0 != w ) { + return lockSurface0(w, v) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY; } - return LOCK_SUCCESS; + return LOCK_SURFACE_NOT_READY; } @Override protected void unlockSurfaceImpl() { - if(!isOffscreenInstance) { - final long h = getWindowHandle(); - if(0 != h) { - unlockSurface0(h); + /** + * if( isOffscreenInstance ) { + * return; + * } + */ + final long w = getWindowHandle(); + final long v = surfaceHandle; + if(0 != w && 0 != v) { + if( !unlockSurface0(w, v) ) { + throw new NativeWindowException("Failed to unlock surface, probably not locked!"); } } } @@ -130,7 +142,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl sscSurfaceHandle = surfaceHandle; if (isNativeValid()) { if (0 != sscSurfaceHandle) { - orderOut0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); + orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); } /** this is done by recreation! else if (isVisible()){ orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); @@ -172,7 +184,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow: updatePosition() -> abs child-client-pos: "+pS); } - setWindowClientTopLeftPoint0(handle, pS.getX(), pS.getY()); + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + setWindowClientTopLeftPoint0(handle, pS.getX(), pS.getY()); + } } ); // no native event (fullscreen, some reparenting) positionChanged(true, pS.getX(), pS.getY()); } @@ -189,14 +204,17 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow: sizeChanged() "+newWidth+"x"+newHeight+" -> abs child-client-pos "+p0S); } - setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY()); + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY()); + } } ); } } super.sizeChanged(defer, newWidth, newHeight, force); } @Override - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, int flags) { final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent()); isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance; final PointImmutable pClientLevelOnSreen; @@ -224,7 +242,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl ", ioi: "+_isOffscreenInstance+ ") -> "+isOffscreenInstance+ "\n\t, "+getReconfigureFlagsAsString(null, flags)); - Thread.dumpStack(); + // Thread.dumpStack(); } if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { @@ -244,11 +262,12 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); } if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } - } - if( width>0 && height>0 && x>=0 && y>=0 ) { - if( !isOffscreenInstance ) { - // setContentSize0(getWindowHandle(), width, height); - setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height); + } else if( width>0 && height>0 ) { + if( !isOffscreenInstance ) { + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height); + } } ); } // else offscreen size is realized via recreation // no native event (fullscreen, some reparenting) positionChanged(true, x, y); @@ -297,19 +316,25 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl /** Callback for native screen position change event of the client area. */ protected void screenPositionChanged(boolean defer, int newX, int newY) { // passed coordinates are in screen position of the client area - if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow.positionChanged (Screen Pos): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); - } if(getWindowHandle()!=0) { final NativeWindow parent = getParent(); - if(null == parent) { + if( null == parent || isOffscreenInstance ) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); + } positionChanged(defer, newX, newY); } else { // screen position -> rel child window position Point absPos = new Point(newX, newY); - absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) ); + Point parentOnScreen = parent.getLocationOnScreen(null); + absPos.translate( parentOnScreen.scale(-1, -1) ); + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos); + } positionChanged(defer, absPos.getX(), absPos.getY()); } + } else if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); } } @@ -383,65 +408,69 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl final PointImmutable pS, final int width, final int height, final boolean fullscreen) { - if(0!=getWindowHandle() && !recreate) { + if( 0 != getWindowHandle() && !recreate ) { return; } try { - if(0!=getWindowHandle()) { - // save the view .. close the window - surfaceHandle = OSXUtil.RunOnMainThread(true, new Function<Long, Object>() { - public Long eval(Object... args) { - return Long.valueOf( - changeContentView0(getParentWindowHandle(), getWindowHandle(), 0) ); - } } ).longValue(); - if(recreate && 0==surfaceHandle) { - throw new NativeWindowException("Internal Error - recreate, window but no view"); - } - OSXUtil.RunOnMainThread(true, new Runnable() { - public void run() { - close0( getWindowHandle() ); - } } ); + final long parentWin = getParentWindowHandle(); + if( 0 != getWindowHandle() ) { + final long thisWin = getWindowHandle(); setWindowHandle(0); + + if( 0 == surfaceHandle ) { + throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView"); + } + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + changeContentView0(parentWin, thisWin, 0); + close0( thisWin ); + } } ); } else { - surfaceHandle = 0; + if( 0 != surfaceHandle ) { + throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView"); + } + surfaceHandle = createView0(pS.getX(), pS.getY(), width, height, fullscreen, getScreen().getIndex()); + if( 0 == surfaceHandle ) { + throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this); + } } - setWindowHandle( OSXUtil.RunOnMainThread(true, new Function<Long, Object>() { - public Long eval(Object... args) { - return Long.valueOf( - createWindow0( getParentWindowHandle(), - pS.getX(), pS.getY(), width, height, - (getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance), - fullscreen, - ( (isUndecorated() || offscreenInstance) ? NSBorderlessWindowMask : - NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask ), - NSBackingStoreBuffered, - getScreen().getIndex(), surfaceHandle) ); - } } ).longValue() ); - - if (getWindowHandle() == 0) { - throw new NativeWindowException("Could create native window "+Thread.currentThread().getName()+" "+this); - } - surfaceHandle = contentView0(getWindowHandle()); - if( offscreenInstance ) { - orderOut0(0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle()); - } else { - setTitle0(getWindowHandle(), getTitle()); + final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, fullscreen, + ( isUndecorated() || offscreenInstance ) ? NSBorderlessWindowMask : + NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask, + NSBackingStoreBuffered, getScreen().getIndex(), surfaceHandle); + if ( newWin == 0 ) { + throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this); } + setWindowHandle( newWin ); + + final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance; + // Non blocking initialization on main-thread! + OSXUtil.RunOnMainThread(false, new Runnable() { + public void run() { + initWindow0( parentWin, newWin, + pS.getX(), pS.getY(), width, height, + isOpaque, fullscreen, offscreenInstance, getScreen().getIndex(), surfaceHandle); + if( offscreenInstance ) { + orderOut0(0!=parentWin ? parentWin : newWin); + } else { + setTitle0(newWin, getTitle()); + } + } } ); } catch (Exception ie) { ie.printStackTrace(); } } protected static native boolean initIDs0(); + private native long createView0(int x, int y, int w, int h, boolean fullscreen, int screen_idx); + private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, int screen_idx, long view); /** Must be called on Main-Thread */ - private native long createWindow0(long parentWindowHandle, int x, int y, int w, int h, - boolean opaque, boolean fullscreen, int windowStyle, - int backingStoreType, - int screen_idx, long view); - private native boolean lockSurface0(long window); - private native void unlockSurface0(long window); + private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, + boolean opaque, boolean fullscreen, boolean offscreen, int screen_idx, long view); + private native boolean lockSurface0(long window, long view); + private native boolean unlockSurface0(long window, long view); private native void requestFocus0(long window, boolean force); private native void resignFocus0(long window); /** in case of a child window, it actually only issues orderBack(..) */ @@ -452,7 +481,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private native void setTitle0(long window, String title); private native long contentView0(long window); /** Must be called on Main-Thread */ - private native long changeContentView0(long parentWindowOrViewHandle, long window, long view); + private native void changeContentView0(long parentWindowOrView, long window, long view); private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h); private native void setWindowClientTopLeftPoint0(long window, int x, int y); private native void setAlwaysOnTop0(long window, boolean atop); |