aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/classes
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-03-19 00:33:00 +0100
committerSven Gothel <[email protected]>2013-03-19 00:33:00 +0100
commit81cbcdc8469143587b2044661dd613c798ae02ba (patch)
tree813982c77435a9ca75225019b8ea0ebe3d22b08c /src/newt/classes
parentf354fb204d8973453c538dda78a2c82c87be61dc (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.java1
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java17
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java165
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);