aboutsummaryrefslogtreecommitdiffstats
path: root/src/nativewindow/classes/jogamp
diff options
context:
space:
mode:
Diffstat (limited to 'src/nativewindow/classes/jogamp')
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/Debug.java98
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java13
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java (renamed from src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java)72
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java39
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java29
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java38
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java110
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java (renamed from src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java)68
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java152
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java172
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java46
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java47
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java98
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/WrappedWindow.java120
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java164
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTJNILibLoader.java27
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java488
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/JAWT_PlatformInfo.java14
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java341
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/windows/Win32SunJDKReflection.java31
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java39
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java44
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java29
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java22
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java350
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java24
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java35
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java95
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java22
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java71
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java6
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java54
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java45
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java406
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java50
35 files changed, 2494 insertions, 965 deletions
diff --git a/src/nativewindow/classes/jogamp/nativewindow/Debug.java b/src/nativewindow/classes/jogamp/nativewindow/Debug.java
index e07fd1b57..f2a45377e 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/Debug.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/Debug.java
@@ -1,44 +1,36 @@
-/*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
*/
package jogamp.nativewindow;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
import com.jogamp.common.util.PropertyAccess;
/** Helper routines for logging and debugging. */
@@ -47,41 +39,37 @@ public class Debug extends PropertyAccess {
// Some common properties
private static final boolean verbose;
private static final boolean debugAll;
-
+
static {
- PropertyAccess.addTrustedPrefix("nativewindow.", Debug.class);
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ PropertyAccess.addTrustedPrefix("nativewindow.");
+ return null;
+ } } );
verbose = isPropertyDefined("nativewindow.verbose", true);
debugAll = isPropertyDefined("nativewindow.debug", true);
if (verbose) {
- Package p = Package.getPackage("javax.media.nativewindow");
+ final Package p = Package.getPackage("javax.media.nativewindow");
System.err.println("NativeWindow specification version " + p.getSpecificationVersion());
System.err.println("NativeWindow implementation version " + p.getImplementationVersion());
System.err.println("NativeWindow implementation vendor " + p.getImplementationVendor());
}
}
- public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) {
- return PropertyAccess.isPropertyDefined(property, jnlpAlias, null);
- }
-
- public static String getProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getProperty(property, jnlpAlias, null);
- }
-
- public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getBooleanProperty(property, jnlpAlias, null);
- }
-
- public static boolean verbose() {
+ /** Ensures static init block has been issues, i.e. if calling through to {@link PropertyAccess#isPropertyDefined(String, boolean)}. */
+ public static final void initSingleton() {}
+
+ public static final boolean verbose() {
return verbose;
}
- public static boolean debugAll() {
+ public static final boolean debugAll() {
return debugAll;
}
- public static boolean debug(String subcomponent) {
+ public static final boolean debug(final String subcomponent) {
return debugAll() || isPropertyDefined("nativewindow.debug." + subcomponent, true);
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java b/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java
index 52e9c8308..6061c4e79 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -36,8 +36,9 @@ package jogamp.nativewindow;
import javax.media.nativewindow.*;
public class DefaultGraphicsConfigurationFactoryImpl extends GraphicsConfigurationFactory {
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID) {
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested, final CapabilitiesChooser chooser, final AbstractGraphicsScreen screen, final int nativeVisualID) {
return new DefaultGraphicsConfiguration(screen, capsChosen, capsRequested);
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java
index 743d371b7..4f6c0d155 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTToolkitLock.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright 2012 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -25,52 +25,58 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package jogamp.nativewindow.jawt.x11;
-import jogamp.nativewindow.jawt.*;
-import jogamp.nativewindow.x11.X11Lib;
-import jogamp.nativewindow.x11.X11Util;
+package jogamp.nativewindow;
+
import javax.media.nativewindow.ToolkitLock;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
/**
- * Implementing a recursive {@link javax.media.nativewindow.ToolkitLock}
- * utilizing JAWT's AWT lock via {@link JAWTUtil#lockToolkit()} and {@link X11Util#XLockDisplay(long)}.
- * <br>
- * This strategy should only be used if AWT is using the underlying native windowing toolkit
- * in a not intrinsic thread safe manner, e.g. under X11 where no XInitThreads() call
- * is issued before any other X11 usage. This is the current situation for e.g. Webstart or Applets.
+ * Implementing a global recursive {@link javax.media.nativewindow.ToolkitLock}.
+ * <p>
+ * This is the last resort for unstable driver where multiple X11 display connections
+ * to the same connection name are not treated thread safe within the GL/X11 driver.
+ * </p>
*/
-public class X11JAWTToolkitLock implements ToolkitLock {
- long displayHandle;
- RecursiveLock lock;
+public class GlobalToolkitLock implements ToolkitLock {
+ private static final RecursiveLock globalLock = LockFactory.createRecursiveLock();
+ private static GlobalToolkitLock singleton = new GlobalToolkitLock();
- public X11JAWTToolkitLock(long displayHandle) {
- this.displayHandle = displayHandle;
- if(!X11Util.isNativeLockAvailable()) {
- lock = LockFactory.createRecursiveLock();
- }
+ public static final GlobalToolkitLock getSingleton() {
+ return singleton;
}
+ private GlobalToolkitLock() { }
+
+ @Override
public final void lock() {
- if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.lock() - native: "+(null==lock)); }
- JAWTUtil.lockToolkit();
- if(null == lock) {
- X11Lib.XLockDisplay(displayHandle);
- } else {
- lock.lock();
- }
+ globalLock.lock();
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" GlobalToolkitLock: lock() "+toStringImpl()); }
}
+ @Override
public final void unlock() {
- if(TRACE_LOCK) { System.err.println("X11JAWTToolkitLock.unlock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XUnlockDisplay(displayHandle);
- } else {
- lock.unlock();
- }
- JAWTUtil.unlockToolkit();
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" GlobalToolkitLock: unlock() "+toStringImpl()); }
+ globalLock.unlock(); // implicit lock validation
+ }
+
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ globalLock.validateLocked();
+ }
+
+ @Override
+ public final void dispose() {
+ // nop
+ }
+
+ @Override
+ public String toString() {
+ return "GlobalToolkitLock["+toStringImpl()+"]";
+ }
+ private String toStringImpl() {
+ return "obj 0x"+Integer.toHexString(hashCode())+", isOwner "+globalLock.isOwner(Thread.currentThread())+", "+globalLock.toString();
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java b/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java
index 6c15f9a2b..8d0d04161 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/NWJNILibLoader.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,12 +20,12 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-
+
package jogamp.nativewindow;
@@ -37,20 +37,17 @@ import com.jogamp.common.os.Platform;
import com.jogamp.common.util.cache.TempJarCache;
public class NWJNILibLoader extends JNILibLoaderBase {
-
- public static boolean loadNativeWindow(final String ossuffix) {
- return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
- public Boolean run() {
- Platform.initSingleton();
- final String libName = "nativewindow_"+ossuffix ;
- if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) {
- // either: [jogl-all.jar, jogl-all-noawt.jar, jogl-all-mobile.jar] -> jogl-all-natives-<os.and.arch>.jar
- // or: nativewindow-core.jar -> nativewindow-natives-<os.and.arch>.jar
- addNativeJarLibs(new Class<?>[] { NWJNILibLoader.class }, "-all", new String[] { "-noawt", "-mobile", "-core" } );
- }
- return new Boolean(loadLibrary(libName, false, NWJNILibLoader.class.getClassLoader()));
- }
- }).booleanValue();
- }
-
+ public static boolean loadNativeWindow(final String ossuffix) {
+ return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Platform.initSingleton();
+ final String libName = "nativewindow_"+ossuffix ;
+ if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) {
+ JNILibLoaderBase.addNativeJarLibsJoglCfg(new Class<?>[] { jogamp.nativewindow.Debug.class });
+ }
+ return Boolean.valueOf(loadLibrary(libName, false, NWJNILibLoader.class.getClassLoader()));
+ }
+ }).booleanValue();
+ }
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java b/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java
index 29564da3b..40fca0f7b 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -46,12 +46,13 @@ public class NativeWindowFactoryImpl extends NativeWindowFactory {
private static final ToolkitLock nullToolkitLock = new NullToolkitLock();
public static ToolkitLock getNullToolkitLock() {
- return nullToolkitLock;
+ return nullToolkitLock;
}
-
+
// This subclass of NativeWindowFactory handles the case of
// NativeWindows being passed in
- protected NativeWindow getNativeWindowImpl(Object winObj, AbstractGraphicsConfiguration config) throws IllegalArgumentException {
+ @Override
+ protected NativeWindow getNativeWindowImpl(final Object winObj, final AbstractGraphicsConfiguration config) throws IllegalArgumentException {
if (winObj instanceof NativeWindow) {
// Use the NativeWindow directly
return (NativeWindow) winObj;
@@ -69,10 +70,10 @@ public class NativeWindowFactoryImpl extends NativeWindowFactory {
winObj.getClass().getName() + " is unsupported; expected " +
"javax.media.nativewindow.NativeWindow or "+AWTNames.ComponentClass);
}
-
+
private Constructor<?> nativeWindowConstructor = null;
- private NativeWindow getAWTNativeWindow(Object winObj, AbstractGraphicsConfiguration config) {
+ private NativeWindow getAWTNativeWindow(final Object winObj, final AbstractGraphicsConfiguration config) {
if (nativeWindowConstructor == null) {
try {
final String windowingType = getNativeWindowType(true);
@@ -93,16 +94,16 @@ public class NativeWindowFactoryImpl extends NativeWindowFactory {
}
nativeWindowConstructor = ReflectionUtil.getConstructor(
- windowClassName, new Class[] { Object.class, AbstractGraphicsConfiguration.class },
- getClass().getClassLoader());
- } catch (Exception e) {
+ windowClassName, new Class[] { Object.class, AbstractGraphicsConfiguration.class },
+ true, getClass().getClassLoader());
+ } catch (final Exception e) {
throw new IllegalArgumentException(e);
}
}
try {
return (NativeWindow) nativeWindowConstructor.newInstance(new Object[] { winObj, config });
- } catch (Exception ie) {
+ } catch (final Exception ie) {
throw new IllegalArgumentException(ie);
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java
index 1af6bf279..bbfb585ac 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java
@@ -28,26 +28,48 @@
package jogamp.nativewindow;
+import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ToolkitLock;
/**
- * Implementing a singleton global recursive {@link javax.media.nativewindow.ToolkitLock}
- * without any locking. Since there is no locking it all,
- * it is intrinsically recursive.
+ * Implementing a singleton global NOP {@link javax.media.nativewindow.ToolkitLock}
+ * without any locking. Since there is no locking it all, it is intrinsically recursive.
*/
public class NullToolkitLock implements ToolkitLock {
-
/** Singleton via {@link NativeWindowFactoryImpl#getNullToolkitLock()} */
protected NullToolkitLock() { }
-
+
+ @Override
public final void lock() {
if(TRACE_LOCK) {
- System.err.println("NullToolkitLock.lock()");
- // Thread.dumpStack();
+ System.err.println(Thread.currentThread()+" NullToolkitLock: lock() "+toStringImpl());
+ // ExceptionUtils.dumpStackTrace(System.err, 1, 4);
}
}
+ @Override
public final void unlock() {
- if(TRACE_LOCK) { System.err.println("NullToolkitLock.unlock()"); }
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" NullToolkitLock: unlock() "+toStringImpl()); }
+ }
+
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ if( NativeWindowFactory.requiresToolkitLock() ) {
+ throw new RuntimeException("NullToolkitLock does not lock, but locking is required.");
+ }
}
+
+ @Override
+ public final void dispose() {
+ // nop
+ }
+
+ @Override
+ public String toString() {
+ return "NullToolkitLock["+toStringImpl()+"]";
+ }
+ private String toStringImpl() {
+ return "obj 0x"+Integer.toHexString(hashCode());
+ }
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
index 63f56cbae..deb685b51 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
@@ -36,17 +36,15 @@ import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.SurfaceUpdatedListener;
import javax.media.nativewindow.UpstreamSurfaceHook;
-
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
-public abstract class ProxySurfaceImpl implements ProxySurface {
+public abstract class ProxySurfaceImpl implements ProxySurface {
private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
- protected long displayHandle; // convenient ref of config.screen.device.handle
private AbstractGraphicsConfiguration config; // control access due to delegation
private UpstreamSurfaceHook upstream;
private long surfaceHandle_old;
- private RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
+ private final RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
private int implBitfield;
private boolean upstreamSurfaceHookLifecycleEnabled;
@@ -57,7 +55,7 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
* owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
* otherwise <code>false</code>. Owning the device implies closing it at {@link #destroyNotify()}.
*/
- protected ProxySurfaceImpl(AbstractGraphicsConfiguration cfg, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ protected ProxySurfaceImpl(final AbstractGraphicsConfiguration cfg, final UpstreamSurfaceHook upstream, final boolean ownsDevice) {
if(null == cfg) {
throw new IllegalArgumentException("null AbstractGraphicsConfiguration");
}
@@ -65,38 +63,41 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
throw new IllegalArgumentException("null UpstreamSurfaceHook");
}
this.config = cfg;
- this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
this.upstream = upstream;
this.surfaceHandle_old = 0;
this.implBitfield = 0;
this.upstreamSurfaceHookLifecycleEnabled = true;
if(ownsDevice) {
addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
- }
+ }
+ }
+
+ @Override
+ public final NativeSurface getUpstreamSurface() {
+ return upstream.getUpstreamSurface();
}
@Override
public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; }
-
+
@Override
- public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook) {
+ public void setUpstreamSurfaceHook(final UpstreamSurfaceHook hook) {
if(null == hook) {
throw new IllegalArgumentException("null UpstreamSurfaceHook");
}
upstream = hook;
}
-
+
@Override
- public final void enableUpstreamSurfaceHookLifecycle(boolean enable) {
+ public final void enableUpstreamSurfaceHookLifecycle(final boolean enable) {
upstreamSurfaceHookLifecycleEnabled = enable;
}
-
+
@Override
- public void createNotify() {
+ public void createNotify() {
if(upstreamSurfaceHookLifecycleEnabled) {
upstream.create(this);
}
- this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
this.surfaceHandle_old = 0;
}
@@ -111,25 +112,15 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
}
invalidateImpl();
}
- this.displayHandle = 0;
this.surfaceHandle_old = 0;
}
-
- /**
+
+ /**
* Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed.
- * @see #destroyNotify()
+ * @see #destroyNotify()
*/
protected void invalidateImpl() {
- throw new InternalError("UpstreamSurfaceHook given, but required method not implemented.");
- }
-
- @Override
- public final long getDisplayHandle() {
- return displayHandle;
- }
-
- protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() {
- return config;
+ throw new InternalError("UpstreamSurfaceHook given, but required method not implemented.");
}
@Override
@@ -138,10 +129,15 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
}
@Override
- public final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) {
+ public final long getDisplayHandle() {
+ return config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ }
+
+ @Override
+ public final void setGraphicsConfiguration(final AbstractGraphicsConfiguration cfg) {
config = cfg;
}
-
+
@Override
public final int getScreenIndex() {
return getGraphicsConfiguration().getScreen().getIndex();
@@ -152,15 +148,15 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
@Override
public abstract void setSurfaceHandle(long surfaceHandle);
-
+
@Override
- public final int getWidth() {
- return upstream.getWidth(this);
+ public final int getSurfaceWidth() {
+ return upstream.getSurfaceWidth(this);
}
@Override
- public final int getHeight() {
- return upstream.getHeight(this);
+ public final int getSurfaceHeight() {
+ return upstream.getSurfaceHeight(this);
}
@Override
@@ -169,22 +165,22 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
}
@Override
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ public void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
}
@Override
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ public void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
}
@Override
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ public void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
}
@Override
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
}
@@ -253,7 +249,8 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
public final Thread getSurfaceLockOwner() {
return surfaceLock.getOwner();
}
-
+
+ @Override
public final StringBuilder getUpstreamOptionBits(StringBuilder sink) {
if(null == sink) {
sink = new StringBuilder();
@@ -285,38 +282,41 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
sink.append(" ]");
return sink;
}
-
+
@Override
public final int getUpstreamOptionBits() { return implBitfield; }
-
+
@Override
- public final boolean containsUpstreamOptionBits(int v) {
+ public final boolean containsUpstreamOptionBits(final int v) {
return v == ( implBitfield & v ) ;
}
-
+
@Override
- public final void addUpstreamOptionBits(int v) { implBitfield |= v; }
-
+ public final void addUpstreamOptionBits(final int v) { implBitfield |= v; }
+
@Override
- public final void clearUpstreamOptionBits(int v) { implBitfield &= ~v; }
-
+ public final void clearUpstreamOptionBits(final int v) { implBitfield &= ~v; }
+
@Override
public StringBuilder toString(StringBuilder sink) {
if(null == sink) {
sink = new StringBuilder();
}
- sink.append(getUpstreamSurfaceHook()).
- append(", displayHandle 0x" + Long.toHexString(getDisplayHandle())).
- append(", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle())).
- append(", size " + getWidth() + "x" + getHeight()).append(", ");
+ sink.append("displayHandle 0x" + Long.toHexString(getDisplayHandle())).
+ append("\n, surfaceHandle 0x" + Long.toHexString(getSurfaceHandle())).
+ append("\n, size " + getSurfaceWidth() + "x" + getSurfaceHeight()).append("\n, ");
getUpstreamOptionBits(sink);
- sink.append(", surfaceLock "+surfaceLock);
+ sink.append("\n, "+config).
+ append("\n, surfaceLock "+surfaceLock+"\n, ").
+ append(getUpstreamSurfaceHook()).
+ append("\n, upstreamSurface "+(null != getUpstreamSurface()));
+ // append("\n, upstreamSurface "+getUpstreamSurface());
return sink;
}
-
+
@Override
public String toString() {
- StringBuilder msg = new StringBuilder();
+ final StringBuilder msg = new StringBuilder();
msg.append(getClass().getSimpleName()).append("[ ");
toString(msg);
msg.append(" ]");
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java
index 5166ef577..e4e557d36 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright 2012 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
@@ -25,7 +25,8 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package jogamp.nativewindow.x11;
+
+package jogamp.nativewindow;
import javax.media.nativewindow.ToolkitLock;
@@ -33,38 +34,53 @@ import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
/**
- * Implementing a recursive {@link javax.media.nativewindow.ToolkitLock}
- * utilizing {@link X11Util#XLockDisplay(long)}.
- * <br>
- * This strategy should not be used in case XInitThreads() is being used,
- * or a higher level toolkit lock is required, ie AWT lock.
+ * Implementing a resource based recursive {@link javax.media.nativewindow.ToolkitLock}.
+ * <p>
+ * A resource handle maybe used within a unique object
+ * and can be synchronized across threads via an instance of ResourceToolkitLock.
+ * </p>
*/
-public class X11ToolkitLock implements ToolkitLock {
- long displayHandle;
- RecursiveLock lock;
+public class ResourceToolkitLock implements ToolkitLock {
+ public static final ResourceToolkitLock create() {
+ return new ResourceToolkitLock();
+ }
- public X11ToolkitLock(long displayHandle) {
- this.displayHandle = displayHandle;
- if(!X11Util.isNativeLockAvailable()) {
- lock = LockFactory.createRecursiveLock();
- }
+ private final RecursiveLock lock;
+
+ private ResourceToolkitLock() {
+ this.lock = LockFactory.createRecursiveLock();
}
+ @Override
public final void lock() {
- if(TRACE_LOCK) { System.err.println("X11ToolkitLock.lock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XLockDisplay(displayHandle);
- } else {
- lock.lock();
+ lock.lock();
+ if(TRACE_LOCK) {
+ System.err.println(Thread.currentThread()+" ResourceToolkitLock: lock() "+toStringImpl());
+ // ExceptionUtils.dumpStackTrace(System.err, 1, 4);
}
}
+ @Override
public final void unlock() {
- if(TRACE_LOCK) { System.err.println("X11ToolkitLock.unlock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XUnlockDisplay(displayHandle);
- } else {
- lock.unlock();
- }
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" ResourceToolkitLock: unlock() "+toStringImpl()); }
+ lock.unlock(); // implicit lock validation
+ }
+
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ lock.validateLocked();
+ }
+
+ @Override
+ public final void dispose() {
+ // nop
+ }
+
+ @Override
+ public String toString() {
+ return "ResourceToolkitLock["+toStringImpl()+"]";
+ }
+ private String toStringImpl() {
+ return "obj 0x"+Integer.toHexString(hashCode())+", isOwner "+lock.isOwner(Thread.currentThread())+", "+lock.toString();
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java
new file mode 100644
index 000000000..881fd56a6
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java
@@ -0,0 +1,152 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.nativewindow;
+
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.media.nativewindow.ToolkitLock;
+
+import com.jogamp.common.util.LongObjectHashMap;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+/**
+ * Implementing a shared resource based recursive {@link javax.media.nativewindow.ToolkitLock}.
+ * <p>
+ * A resource handle maybe used within many objects
+ * and can be synchronized across threads via an unique instance of SharedResourceToolkitLock.
+ * </p>
+ * <p>
+ * Implementation holds a synchronized map from handle to reference counted {@link SharedResourceToolkitLock}.
+ * New elements are added via {@link #get(long)} if new
+ * and removed via {@link #dispose()} if no more referenced.
+ * </p>
+ */
+public class SharedResourceToolkitLock implements ToolkitLock {
+ private static final LongObjectHashMap handle2Lock;
+ static {
+ handle2Lock = new LongObjectHashMap();
+ handle2Lock.setKeyNotFoundValue(null);
+ }
+
+ /**
+ * @return number of unclosed EGL Displays.<br>
+ */
+ public static int shutdown(final boolean verbose) {
+ if(DEBUG || verbose || handle2Lock.size() > 0 ) {
+ System.err.println("SharedResourceToolkitLock: Shutdown (open: "+handle2Lock.size()+")");
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ if( handle2Lock.size() > 0) {
+ dumpOpenDisplayConnections();
+ }
+ }
+ return handle2Lock.size();
+ }
+
+ public static void dumpOpenDisplayConnections() {
+ System.err.println("SharedResourceToolkitLock: Open ResourceToolkitLock's: "+handle2Lock.size());
+ int i=0;
+ for(final Iterator<LongObjectHashMap.Entry> iter = handle2Lock.iterator(); iter.hasNext(); i++) {
+ final LongObjectHashMap.Entry e = iter.next();
+ System.err.println("SharedResourceToolkitLock: Open["+i+"]: "+e.value);
+ }
+ }
+
+ public static final SharedResourceToolkitLock get(final long handle) {
+ SharedResourceToolkitLock res;
+ synchronized(handle2Lock) {
+ res = (SharedResourceToolkitLock) handle2Lock.get(handle);
+ if( null == res ) {
+ res = new SharedResourceToolkitLock(handle);
+ res.refCount.incrementAndGet();
+ handle2Lock.put(handle, res);
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.get() * NEW *: "+res); }
+ } else {
+ res.refCount.incrementAndGet();
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.get() * EXIST *: "+res); }
+ }
+ }
+ return res;
+ }
+
+ private final RecursiveLock lock;
+ private final long handle;
+ private final AtomicInteger refCount;
+
+ private SharedResourceToolkitLock(final long handle) {
+ this.lock = LockFactory.createRecursiveLock();
+ this.handle = handle;
+ this.refCount = new AtomicInteger(0);
+ }
+
+
+ @Override
+ public final void lock() {
+ lock.lock();
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" SharedResourceToolkitLock: lock() "+toStringImpl()); }
+ }
+
+ @Override
+ public final void unlock() {
+ if(TRACE_LOCK) { System.err.println(Thread.currentThread()+" SharedResourceToolkitLock: unlock() "+toStringImpl()); }
+ lock.unlock();
+ }
+
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ lock.validateLocked();
+ }
+
+ @Override
+ public final void dispose() {
+ if(0 < refCount.get()) { // volatile OK
+ synchronized(handle2Lock) {
+ if( 0 == refCount.decrementAndGet() ) {
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.dispose() * REMOV *: "+this); }
+ handle2Lock.remove(handle);
+ } else {
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.dispose() * DOWN *: "+this); }
+ }
+ }
+ } else {
+ if(DEBUG || TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.dispose() * NULL *: "+this); }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SharedResourceToolkitLock["+toStringImpl()+"]";
+ }
+ private String toStringImpl() {
+ return "refCount "+refCount+", handle 0x"+Long.toHexString(handle)+", obj 0x"+Integer.toHexString(hashCode())+", isOwner "+lock.isOwner(Thread.currentThread())+", "+lock.toString();
+ }
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java
new file mode 100644
index 000000000..73413cf59
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.ScalableSurface;
+
+/**
+ * Basic {@link ScalableSurface} utility to validate and compute pixel-scale values.
+ */
+public class SurfaceScaleUtils {
+
+ private static final int[] PlatformMaxPixelScale;
+ private static final boolean PlatformUniformPixelScale;
+ private static final boolean PlatformPixelScaleSupported;
+
+ static {
+ if( NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(true) ) {
+ PlatformMaxPixelScale = new int[] { jogamp.nativewindow.macosx.OSXUtil.MAX_PIXELSCALE, jogamp.nativewindow.macosx.OSXUtil.MAX_PIXELSCALE };
+ PlatformUniformPixelScale = true;
+ PlatformPixelScaleSupported = true;
+ } else {
+ PlatformMaxPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ PlatformUniformPixelScale = false;
+ PlatformPixelScaleSupported = false;
+ }
+ }
+
+ /**
+ * Compute a new valid pixelScale to be used by {@link NativeSurface} implementations,
+ * based on the given request and surface's pixelScale
+ *
+ * @param result int[2] storage for result, maybe same as <code>prePixelScale</code> for in-place
+ * @param prePixelScale previous pixelScale
+ * @param reqPixelScale requested pixelScale, validated via {@link #validateReqPixelScale(int[], int, String)}.
+ * @param newPixelScaleRaw new raw surface pixelScale
+ * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix
+ * @return true if pixelScale has changed, otherwise false
+ */
+ public static boolean computePixelScale(final int[] result, final int[] prePixelScale, final int[] reqPixelScale, final int[] newPixelScaleRaw, final String DEBUG_PREFIX) {
+ final int newPixelScaleSafeX = 0 < newPixelScaleRaw[0] ? newPixelScaleRaw[0] : ScalableSurface.IDENTITY_PIXELSCALE;
+ final int newPixelScaleSafeY = 0 < newPixelScaleRaw[1] ? newPixelScaleRaw[1] : ScalableSurface.IDENTITY_PIXELSCALE;
+ final boolean useHiDPI = ScalableSurface.IDENTITY_PIXELSCALE != reqPixelScale[0] || ScalableSurface.IDENTITY_PIXELSCALE != reqPixelScale[1];
+ final int prePixelScaleX = prePixelScale[0];
+ final int prePixelScaleY = prePixelScale[1];
+
+ if( useHiDPI ) {
+ result[0] = newPixelScaleSafeX;
+ result[1] = newPixelScaleSafeY;
+ } else {
+ result[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ result[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ }
+
+ final boolean changed = result[0] != prePixelScaleX || result[1] != prePixelScaleY;
+ if( null != DEBUG_PREFIX ) {
+ System.err.println(DEBUG_PREFIX+".computePixelScale: useHiDPI "+useHiDPI+", ["+prePixelScaleX+"x"+prePixelScaleY+" (pre), "+
+ reqPixelScale[0]+"x"+reqPixelScale[1]+" (req)] -> "+
+ newPixelScaleRaw[0]+"x"+newPixelScaleRaw[1]+" (raw) -> "+
+ newPixelScaleSafeX+"x"+newPixelScaleSafeY+" (safe) -> "+
+ result[0]+"x"+result[1]+" (use), changed "+changed);
+ }
+ return changed;
+ }
+
+ /**
+ * Validate the given requested pixelScale value pair, i.e. clip it to the
+ * limits of {@link ScalableSurface#AUTOMAX_PIXELSCALE} and {@link #getPlatformMaxPixelScale(int[])}
+ * <p>
+ * To be used by {@link ScalableSurface#setSurfaceScale(int[])} implementations.
+ * </p>
+ *
+ * @param result int[2] storage for result
+ * @param reqPixelScale requested pixelScale
+ * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix
+ */
+ public static void validateReqPixelScale(final int[] result, final int[] reqPixelScale, final String DEBUG_PREFIX) {
+ final int minPS = Math.min(reqPixelScale[0], reqPixelScale[1]);
+ if( ScalableSurface.AUTOMAX_PIXELSCALE >= minPS ) {
+ result[0] = ScalableSurface.AUTOMAX_PIXELSCALE;
+ result[1] = ScalableSurface.AUTOMAX_PIXELSCALE;
+ } else if( PlatformUniformPixelScale ) {
+ final int maxPS = Math.max(reqPixelScale[0], reqPixelScale[1]);
+ if( maxPS >= PlatformMaxPixelScale[0] ) {
+ result[0] = PlatformMaxPixelScale[0];
+ result[1] = PlatformMaxPixelScale[1];
+ } else {
+ result[0] = maxPS;
+ result[1] = maxPS;
+ }
+ } else {
+ if( reqPixelScale[0] >= PlatformMaxPixelScale[0] ) {
+ result[0] = PlatformMaxPixelScale[0];
+ } else {
+ result[0] = reqPixelScale[0];
+ }
+ if( reqPixelScale[1] >= PlatformMaxPixelScale[1] ) {
+ result[1] = PlatformMaxPixelScale[1];
+ } else {
+ result[1] = reqPixelScale[1];
+ }
+ }
+ if( null != DEBUG_PREFIX ) {
+ System.err.println(DEBUG_PREFIX+".validateReqPixelScale: ["+reqPixelScale[0]+"x"+reqPixelScale[1]+" (req), "+
+ PlatformMaxPixelScale[0]+"x"+PlatformMaxPixelScale[1]+" (max)] -> "+
+ result[0]+"x"+result[1]+" (valid)");
+ }
+ }
+
+ /**
+ * Replaces {@link ScalableSurface#AUTOMAX_PIXELSCALE} with {@link #getPlatformMaxPixelScale(int[])},
+ * for each component.
+ *
+ * @param pixelScale int[2] value array to be tested and replaced
+ */
+ public static void replaceAutoMaxWithPlatformMax(final int[] pixelScale) {
+ if( ScalableSurface.AUTOMAX_PIXELSCALE == pixelScale[0] ) {
+ pixelScale[0] = PlatformMaxPixelScale[0];
+ }
+ if( ScalableSurface.AUTOMAX_PIXELSCALE == pixelScale[1] ) {
+ pixelScale[1] = PlatformMaxPixelScale[1];
+ }
+ }
+
+ /**
+ * Returns the maximum platform pixelScale
+ */
+ public static int[] getPlatformMaxPixelScale(final int[] result) {
+ System.arraycopy(PlatformMaxPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ /**
+ * Returns true if platform pixelScale is uniform, i.e. same scale factor for x- and y-direction, otherwise false.
+ */
+ public static boolean isPlatformPixelScaleUniform() {
+ return PlatformUniformPixelScale;
+ }
+
+ /**
+ * Returns whether the platform supports pixelScale
+ */
+ public static boolean isPlatformPixelScaleSupported() {
+ return PlatformPixelScaleSupported;
+ }
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
index 4f68c6945..a7e136f76 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
@@ -3,14 +3,14 @@
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
@@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
@@ -36,48 +36,56 @@ import javax.media.nativewindow.SurfaceUpdatedListener;
public class SurfaceUpdatedHelper implements SurfaceUpdatedListener {
private final Object surfaceUpdatedListenersLock = new Object();
private final ArrayList<SurfaceUpdatedListener> surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>();
+ private volatile boolean isEmpty = true;
//
// Management Utils
- //
- public int size() { return surfaceUpdatedListeners.size(); }
- public SurfaceUpdatedListener get(int i) { return surfaceUpdatedListeners.get(i); }
-
+ //
+ public final int size() { return surfaceUpdatedListeners.size(); }
+ public final SurfaceUpdatedListener get(final int i) { return surfaceUpdatedListeners.get(i); }
+
//
// Implementation of NativeSurface SurfaceUpdatedListener methods
- //
-
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ //
+
+ public final void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
addSurfaceUpdatedListener(-1, l);
}
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l)
+ public final void addSurfaceUpdatedListener(int index, final SurfaceUpdatedListener l)
throws IndexOutOfBoundsException
{
if(l == null) {
return;
}
synchronized(surfaceUpdatedListenersLock) {
- if(0>index) {
- index = surfaceUpdatedListeners.size();
+ if(0>index) {
+ index = surfaceUpdatedListeners.size();
}
surfaceUpdatedListeners.add(index, l);
+ isEmpty = false;
}
}
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ public final boolean removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) {
if (l == null) {
- return;
+ return false;
}
synchronized(surfaceUpdatedListenersLock) {
- surfaceUpdatedListeners.remove(l);
+ final boolean res = surfaceUpdatedListeners.remove(l);
+ isEmpty = 0 == surfaceUpdatedListeners.size();
+ return res;
}
}
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ @Override
+ public final void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) {
+ if( isEmpty ) {
+ return;
+ }
synchronized(surfaceUpdatedListenersLock) {
for(int i = 0; i < surfaceUpdatedListeners.size(); i++ ) {
- SurfaceUpdatedListener l = surfaceUpdatedListeners.get(i);
+ final SurfaceUpdatedListener l = surfaceUpdatedListeners.get(i);
l.surfaceUpdated(updater, ns, when);
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java b/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java
new file mode 100644
index 000000000..47b3e63fa
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java
@@ -0,0 +1,47 @@
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.NativeWindowFactory;
+
+/**
+ * Marker interface.
+ * <p>
+ * Implementation requires to provide static methods:
+ * <pre>
+ public static void initSingleton() {}
+
+ public static void shutdown() {}
+
+ public static boolean requiresToolkitLock() {}
+
+ public static boolean hasThreadingIssues() {}
+ * </pre>
+ * Above static methods are invoked by {@link NativeWindowFactory#initSingleton()},
+ * or {@link NativeWindowFactory#shutdown()} via reflection.
+ * </p>
+ */
+public interface ToolkitProperties {
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
+ // void initSingleton();
+
+ /**
+ * Cleanup resources.
+ * <p>
+ * Called by {@link NativeWindowFactory#shutdown()}
+ * </p>
+ */
+ // void shutdown();
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
+ // boolean requiresToolkitLock();
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ */
+ // boolean hasThreadingIssues();
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
index e544bc61a..d3439b53f 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
@@ -31,17 +31,24 @@ package jogamp.nativewindow;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
-public class WrappedSurface extends ProxySurfaceImpl {
- protected long surfaceHandle;
+/**
+ * Generic Surface implementation which wraps an existing window handle.
+ *
+ * @see ProxySurface
+ */
+public class WrappedSurface extends ProxySurfaceImpl implements ScalableSurface {
+ private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private long surfaceHandle;
/**
* Utilizes a {@link UpstreamSurfaceHook.MutableSize} to hold the size information,
* which is being passed to the {@link ProxySurface} instance.
- *
+ *
* @param cfg the {@link AbstractGraphicsConfiguration} to be used
* @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
* @param initialWidth
@@ -50,11 +57,11 @@ public class WrappedSurface extends ProxySurfaceImpl {
* owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
* otherwise <code>false</code>. Owning the device implies closing it at {@link #destroyNotify()}.
*/
- public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, boolean ownsDevice) {
+ public WrappedSurface(final AbstractGraphicsConfiguration cfg, final long handle, final int initialWidth, final int initialHeight, final boolean ownsDevice) {
super(cfg, new UpstreamSurfaceHookMutableSize(initialWidth, initialHeight), ownsDevice);
surfaceHandle=handle;
}
-
+
/**
* @param cfg the {@link AbstractGraphicsConfiguration} to be used
* @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
@@ -63,14 +70,16 @@ public class WrappedSurface extends ProxySurfaceImpl {
* owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
* otherwise <code>false</code>.
*/
- public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ public WrappedSurface(final AbstractGraphicsConfiguration cfg, final long handle, final UpstreamSurfaceHook upstream, final boolean ownsDevice) {
super(cfg, upstream, ownsDevice);
surfaceHandle=handle;
}
@Override
- protected void invalidateImpl() {
+ protected void invalidateImpl() {
surfaceHandle = 0;
+ hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
}
@Override
@@ -79,10 +88,10 @@ public class WrappedSurface extends ProxySurfaceImpl {
}
@Override
- public final void setSurfaceHandle(long surfaceHandle) {
+ public final void setSurfaceHandle(final long surfaceHandle) {
this.surfaceHandle=surfaceHandle;
}
-
+
@Override
protected final int lockSurfaceImpl() {
return LOCK_SUCCESS;
@@ -92,4 +101,73 @@ public class WrappedSurface extends ProxySurfaceImpl {
protected final void unlockSurfaceImpl() {
}
-}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(int[]) given pixelScale} directly.
+ * </p>
+ */
+ @Override
+ public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
+ pixelUnitsAndResult[0] /= hasPixelScale[0];
+ pixelUnitsAndResult[1] /= hasPixelScale[1];
+ return pixelUnitsAndResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(int[]) given pixelScale} directly.
+ * </p>
+ */
+ @Override
+ public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
+ windowUnitsAndResult[0] *= hasPixelScale[0];
+ windowUnitsAndResult[1] *= hasPixelScale[1];
+ return windowUnitsAndResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * {@link WrappedSurface}'s implementation is to simply pass the given pixelScale
+ * from the caller <i>down</i> to this instance without validation to be applied in the {@link #convertToPixelUnits(int[]) conversion} {@link #convertToWindowUnits(int[]) methods} <b>only</b>.<br/>
+ * This allows the caller to pass down knowledge about window- and pixel-unit conversion and utilize mentioned conversion methods.
+ * </p>
+ * <p>
+ * The given pixelScale will not impact the actual {@link #getSurfaceWidth()} and {@link #getSurfaceHeight()},
+ * which is determinated by this instances {@link #getUpstreamSurface() upstream surface}.
+ * </p>
+ * <p>
+ * Implementation uses the default pixelScale {@link ScalableSurface#IDENTITY_PIXELSCALE}
+ * and resets to default values on {@link #invalidateImpl()}, i.e. {@link #destroyNotify()}.
+ * </p>
+ * <p>
+ * Implementation returns the given pixelScale array.
+ * </p>
+ */
+ @Override
+ public final void setSurfaceScale(final int[] pixelScale) {
+ hasPixelScale[0] = pixelScale[0];
+ hasPixelScale[1] = pixelScale[1];
+ }
+
+ @Override
+ public final int[] getRequestedSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final int[] getCurrentSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ @Override
+ public final int[] getNativeSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+} \ No newline at end of file
diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedWindow.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedWindow.java
new file mode 100644
index 000000000..fd39a3b4a
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedWindow.java
@@ -0,0 +1,120 @@
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+import javax.media.nativewindow.util.Insets;
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.Point;
+
+import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos;
+
+public class WrappedWindow extends WrappedSurface implements NativeWindow {
+ private final InsetsImmutable insets = new Insets(0, 0, 0, 0);
+ private long windowHandle;
+
+ /**
+ * Utilizes a {@link UpstreamWindowHookMutableSizePos} to hold the size and position information,
+ * which is being passed to the {@link ProxySurface} instance.
+ *
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param surfaceHandle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
+ * @param initialWinX
+ * @param initialWinY
+ * @param initialWinWidth
+ * @param initialWinHeight
+ * @param initialPixelWidth FIXME: pixel-dim == window-dim 'for now' ?
+ * @param initialPixelHeight FIXME: pixel-dim == window-dim 'for now' ?
+ * @param ownsDevice <code>true</code> if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise <code>false</code>. Owning the device implies closing it at {@link #destroyNotify()}.
+ */
+ public WrappedWindow(final AbstractGraphicsConfiguration cfg, final long surfaceHandle,
+ final int initialWinX, final int initialWinY, final int initialWinWidth, final int initialWinHeight,
+ final int initialPixelWidth, final int initialPixelHeight,
+ final boolean ownsDevice, final long windowHandle) {
+ this(cfg, surfaceHandle,
+ new UpstreamWindowHookMutableSizePos(initialWinX, initialWinY, initialWinWidth, initialWinHeight,
+ initialPixelWidth, initialPixelHeight),
+ ownsDevice, windowHandle);
+ }
+
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param surfaceHandle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
+ * @param upstream the {@link UpstreamSurfaceHook} to be used
+ * @param ownsDevice <code>true</code> if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise <code>false</code>.
+ */
+ public WrappedWindow(final AbstractGraphicsConfiguration cfg, final long surfaceHandle, final UpstreamWindowHookMutableSizePos upstream, final boolean ownsDevice, final long windowHandle) {
+ super(cfg, surfaceHandle, upstream, ownsDevice);
+ this.windowHandle = windowHandle;
+ }
+
+ @Override
+ protected void invalidateImpl() {
+ super.invalidateImpl();
+ windowHandle = 0;
+ }
+
+ @Override
+ public void destroy() {
+ destroyNotify();
+ }
+
+ @Override
+ public final NativeSurface getNativeSurface() { return this; }
+
+ @Override
+ public NativeWindow getParent() {
+ return null;
+ }
+
+ @Override
+ public long getWindowHandle() {
+ return windowHandle;
+ }
+
+ @Override
+ public InsetsImmutable getInsets() {
+ return insets;
+ }
+
+ @Override
+ public int getX() {
+ return ((UpstreamWindowHookMutableSizePos)getUpstreamSurfaceHook()).getX();
+ }
+
+ @Override
+ public int getY() {
+ return ((UpstreamWindowHookMutableSizePos)getUpstreamSurfaceHook()).getY();
+ }
+
+ @Override
+ public int getWidth() {
+ return ((UpstreamWindowHookMutableSizePos)getUpstreamSurfaceHook()).getWidth();
+ }
+
+ @Override
+ public int getHeight() {
+ return ((UpstreamWindowHookMutableSizePos)getUpstreamSurfaceHook()).getHeight();
+ }
+
+ @Override
+ public Point getLocationOnScreen(final Point point) {
+ if(null!=point) {
+ return point;
+ } else {
+ return new Point(0, 0);
+ }
+ }
+
+ @Override
+ public boolean hasFocus() {
+ return false;
+ }
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
index d77cd75ef..b0eda63b6 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
@@ -27,17 +27,31 @@
*/
package jogamp.nativewindow.awt;
+import java.awt.Cursor;
+import java.awt.FocusTraversalPolicy;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Toolkit;
import java.awt.Window;
import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
+import java.awt.image.BufferedImage;
+import java.util.HashMap;
+
+import javax.swing.JComponent;
import javax.swing.JFrame;
+import javax.swing.JRootPane;
import javax.swing.WindowConstants;
-
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelFormatUtil;
import javax.swing.MenuSelectionManager;
+import jogamp.nativewindow.jawt.JAWTUtil;
+
public class AWTMisc {
public static JFrame getJFrame(Component c) {
@@ -69,13 +83,157 @@ public class AWTMisc {
}
/**
+ * Return insets of the component w/o traversing up to parent,
+ * i.e. trying Window and JComponent.
+ * <p>
+ * Exception is JRootPane.
+ * Return it's parent's Window component's insets if available,
+ * otherwise return JRootPane's insets.<br>
+ * This is due to <i>experience</i> that <i>some</i> JRootPane's
+ * do not expose valid insets value.
+ * </p>
+ * @param topLevelOnly if true only returns insets of top-level components, i.e. Window and JRootPanel,
+ * otherwise for JComponent as well.
+ */
+ public static Insets getInsets(final Component c, final boolean topLevelOnly) {
+ if( c instanceof Window ) {
+ return ((Window)c).getInsets();
+ }
+ if( c instanceof JRootPane ) {
+ final Window w = getWindow(c);
+ if( null != w ) {
+ return w.getInsets();
+ }
+ return ((JRootPane)c).getInsets();
+ }
+ if( !topLevelOnly && c instanceof JComponent ) {
+ return ((JComponent)c).getInsets();
+ }
+ return null;
+ }
+
+ public static interface ComponentAction {
+ /**
+ * @param c the component to perform the action on
+ */
+ public void run(Component c);
+ }
+
+ public static int performAction(final Container c, final Class<?> cType, final ComponentAction action) {
+ int count = 0;
+ final int cc = c.getComponentCount();
+ for(int i=0; i<cc; i++) {
+ final Component e = c.getComponent(i);
+ if( e instanceof Container ) {
+ count += performAction((Container)e, cType, action);
+ } else if( cType.isInstance(e) ) {
+ action.run(e);
+ count++;
+ }
+ }
+ // we come at last ..
+ if( cType.isInstance(c) ) {
+ action.run(c);
+ count++;
+ }
+ return count;
+ }
+
+ /**
+ * Traverse to the next forward or backward component using the
+ * container's FocusTraversalPolicy.
+ *
+ * @param comp the assumed current focuse component
+ * @param forward if true, returns the next focus component, otherwise the previous one.
+ * @return
+ */
+ public static Component getNextFocus(Component comp, final boolean forward) {
+ Container focusContainer = comp.getFocusCycleRootAncestor();
+ while ( focusContainer != null &&
+ ( !focusContainer.isShowing() || !focusContainer.isFocusable() || !focusContainer.isEnabled() ) )
+ {
+ comp = focusContainer;
+ focusContainer = comp.getFocusCycleRootAncestor();
+ }
+ Component next = null;
+ if (focusContainer != null) {
+ final FocusTraversalPolicy policy = focusContainer.getFocusTraversalPolicy();
+ next = forward ? policy.getComponentAfter(focusContainer, comp) : policy.getComponentBefore(focusContainer, comp);
+ if (next == null) {
+ next = policy.getDefaultComponent(focusContainer);
+ }
+ }
+ return next;
+ }
+
+ /**
* Issue this when your non AWT toolkit gains focus to clear AWT menu path
*/
public static void clearAWTMenus() {
MenuSelectionManager.defaultManager().clearSelectedPath();
}
- public static WindowClosingProtocol.WindowClosingMode AWT2NWClosingOperation(int awtClosingOperation) {
+ static final HashMap<Integer, Cursor> cursorMap = new HashMap<Integer, Cursor>();
+ static final Cursor nulCursor;
+ static {
+ Cursor _nulCursor = null;
+ if( !JAWTUtil.isHeadlessMode() ) {
+ try {
+ final Toolkit toolkit = Toolkit.getDefaultToolkit();
+ final BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
+ _nulCursor = toolkit.createCustomCursor(img, new Point(0,0), "nullCursor");
+ } catch (final Exception he) {
+ if( JAWTUtil.DEBUG ) {
+ System.err.println("Caught exception: "+he.getMessage());
+ he.printStackTrace();
+ }
+ }
+ }
+ nulCursor = _nulCursor;
+ }
+
+ public static synchronized Cursor getNullCursor() { return nulCursor; }
+
+ public static synchronized Cursor getCursor(final PixelRectangle pixelrect, final Point hotSpot) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + pixelrect.hashCode();
+ hash = ((hash << 5) - hash) + hotSpot.hashCode();
+ final Integer key = Integer.valueOf(hash);
+
+ Cursor cursor = cursorMap.get(key);
+ if( null == cursor ) {
+ cursor = createCursor(pixelrect, hotSpot);
+ cursorMap.put(key, cursor);
+ }
+ return cursor;
+ }
+ private static synchronized Cursor createCursor(final PixelRectangle pixelrect, final Point hotSpot) {
+ final int width = pixelrect.getSize().getWidth();
+ final int height = pixelrect.getSize().getHeight();
+ final BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); // PixelFormat.BGRA8888
+ final PixelFormatUtil.PixelSink32 imgSink = new PixelFormatUtil.PixelSink32() {
+ public void store(final int x, final int y, final int pixel) {
+ img.setRGB(x, y, pixel);
+ }
+ @Override
+ public final PixelFormat getPixelformat() {
+ return PixelFormat.BGRA8888;
+ }
+ @Override
+ public int getStride() {
+ return width*4;
+ }
+ @Override
+ public final boolean isGLOriented() {
+ return false;
+ }
+ };
+ PixelFormatUtil.convert32(imgSink, pixelrect);
+ final Toolkit toolkit = Toolkit.getDefaultToolkit();
+ return toolkit.createCustomCursor(img, hotSpot, pixelrect.toString());
+ }
+
+ public static WindowClosingProtocol.WindowClosingMode AWT2NWClosingOperation(final int awtClosingOperation) {
switch (awtClosingOperation) {
case WindowConstants.DISPOSE_ON_CLOSE:
case WindowConstants.EXIT_ON_CLOSE:
@@ -88,7 +246,7 @@ public class AWTMisc {
}
}
- public static WindowClosingProtocol.WindowClosingMode getNWClosingOperation(Component c) {
+ public static WindowClosingProtocol.WindowClosingMode getNWClosingOperation(final Component c) {
final JFrame jf = getJFrame(c);
final int op = (null != jf) ? jf.getDefaultCloseOperation() : WindowConstants.DO_NOTHING_ON_CLOSE ;
return AWT2NWClosingOperation(op);
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTJNILibLoader.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTJNILibLoader.java
index f579da217..8aaffbd84 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTJNILibLoader.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTJNILibLoader.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -47,15 +47,16 @@ import java.awt.Toolkit;
import java.security.AccessController;
import java.security.PrivilegedAction;
-public class JAWTJNILibLoader extends NWJNILibLoader {
+public class JAWTJNILibLoader extends NWJNILibLoader {
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
// Make sure that awt.dll is loaded before loading jawt.dll. Otherwise
// a Dialog with "awt.dll not found" might pop up.
// See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4481947.
Toolkit.getDefaultToolkit();
-
+
// Must pre-load JAWT on all non-Mac platforms to
// ensure references from jogl_awt shared object
// will succeed since JAWT shared object isn't in
@@ -63,7 +64,7 @@ public class JAWTJNILibLoader extends NWJNILibLoader {
if ( NativeWindowFactory.TYPE_MACOSX != NativeWindowFactory.getNativeWindowType(false) ) {
try {
loadLibrary("jawt", null, true, JAWTJNILibLoader.class.getClassLoader());
- } catch (Throwable t) {
+ } catch (final Throwable t) {
// It might be ok .. if it's already loaded
if(DEBUG) {
t.printStackTrace();
@@ -74,9 +75,9 @@ public class JAWTJNILibLoader extends NWJNILibLoader {
}
});
}
-
+
public static void initSingleton() {
- // just exist to ensure static init has been run
+ // just exist to ensure static init has been run
}
-
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
index f1e8a786a..231a89c26 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -38,6 +38,8 @@
package jogamp.nativewindow.jawt;
import java.awt.EventQueue;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.lang.reflect.InvocationTargetException;
@@ -51,23 +53,30 @@ import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ToolkitLock;
+import jogamp.common.os.PlatformPropsImpl;
import jogamp.nativewindow.Debug;
+import jogamp.nativewindow.NWJNILibLoader;
import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
public class JAWTUtil {
public static final boolean DEBUG = Debug.debug("JAWT");
+ private static final boolean SKIP_AWT_HIDPI;
+
/** OSX JAWT version option to use CALayer */
public static final int JAWT_MACOSX_USE_CALAYER = 0x80000000;
-
+
/** OSX JAWT CALayer availability on Mac OS X >= 10.6 Update 4 (recommended) */
public static final VersionNumber JAWT_MacOSXCALayerMinVersion = new VersionNumber(10,6,4);
-
+
/** OSX JAWT CALayer required with Java >= 1.7.0 (implies OS X >= 10.7 */
- public static final VersionNumber JAWT_MacOSXCALayerRequiredForJavaVersion = new VersionNumber(1,7,0);
-
+ public static final VersionNumber JAWT_MacOSXCALayerRequiredForJavaVersion = Platform.Version17;
+
// See whether we're running in headless mode
private static final boolean headlessMode;
private static final JAWT jawtLockObject;
@@ -80,75 +89,196 @@ public class JAWTUtil {
private static final Method sunToolkitAWTUnlockMethod;
private static final boolean hasSunToolkitAWTLock;
+ private static final RecursiveLock jawtLock;
private static final ToolkitLock jawtToolkitLock;
+ private static final Method getScaleFactorMethod;
+
private static class PrivilegedDataBlob1 {
PrivilegedDataBlob1() {
ok = false;
- }
- Method sunToolkitAWTLockMethod;
- Method sunToolkitAWTUnlockMethod;
+ }
+ Method sunToolkitAWTLockMethod;
+ Method sunToolkitAWTUnlockMethod;
+ Method getScaleFactorMethod;
boolean ok;
}
-
+
/**
* Returns true if this platform's JAWT implementation supports offscreen layer.
*/
public static boolean isOffscreenLayerSupported() {
- return Platform.OS_TYPE == Platform.OSType.MACOS &&
- Platform.OS_VERSION_NUMBER.compareTo(JAWTUtil.JAWT_MacOSXCALayerMinVersion) >= 0;
+ return PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS &&
+ PlatformPropsImpl.OS_VERSION_NUMBER.compareTo(JAWTUtil.JAWT_MacOSXCALayerMinVersion) >= 0;
}
-
+
/**
* Returns true if this platform's JAWT implementation requires using offscreen layer.
*/
public static boolean isOffscreenLayerRequired() {
- return Platform.OS_TYPE == Platform.OSType.MACOS &&
- Platform.JAVA_VERSION_NUMBER.compareTo(JAWT_MacOSXCALayerRequiredForJavaVersion)>=0;
+ return PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS &&
+ PlatformPropsImpl.JAVA_VERSION_NUMBER.compareTo(JAWT_MacOSXCALayerRequiredForJavaVersion)>=0;
}
-
+
+ /**
+ * CALayer size needs to be set using the AWT component size.
+ * <p>
+ * AWT's super-calayer, i.e. the AWT's own component CALayer,
+ * does not layout our root-calayer in respect to this component's
+ * position and size, at least when resizing programmatically.
+ * </p>
+ * <p>
+ * As of today, this flag is enabled for all known AWT versions.
+ * </p>
+ * <p>
+ * Sync w/ NativeWindowProtocols.h
+ * </p>
+ */
+ public static final int JAWT_OSX_CALAYER_QUIRK_SIZE = 1 << 0;
+
+ /**
+ * CALayer position needs to be set to zero.
+ * <p>
+ * AWT's super-calayer, i.e. the AWT's own component CALayer,
+ * has a broken layout and needs it's sub-layers to be located at position 0/0.
+ * </p>
+ * <p>
+ * See <code>http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7172187</code>.
+ * </p>
+ * <p>
+ * Further more a re-layout seems to be required in this case,
+ * i.e. a programmatic forced resize +1 and it's inverted resize -1.
+ * </p>
+ * <p>
+ * This flag is enabled w/ AWT < 1.7.0_40.
+ * </p>
+ * <p>
+ * Sync w/ NativeWindowProtocols.h
+ * </p>
+ */
+ public static final int JAWT_OSX_CALAYER_QUIRK_POSITION = 1 << 1;
+
+ /**
+ * CALayer position needs to be derived from AWT position
+ * in relation to super CALayer.
+ * <p>
+ * AWT's super-calayer, i.e. the AWT top-container's CALayer,
+ * does not layout our root-calayer in respect to this component's
+ * position and size, at least when resizing programmatically.
+ * </p>
+ * <p>
+ * CALayer position has origin 0/0 at bottom/left,
+ * where AWT component has origin 0/0 at top/left.
+ * </p>
+ * <p>
+ * The super-calayer bounds exclude the frame's heavyweight border/insets.
+ * </p>
+ * <p>
+ * The super-calayer lies within the AWT top-container client space (content).
+ * </p>
+ * <p>
+ * Component's location in super-calayer:
+ * <pre>
+ p0 = c.locationOnScreen();
+ p0 -= c.getOutterComp.getPos();
+ p0 -= c.getOutterComp.getInsets();
+ * </pre>
+ * Where 'locationOnScreen()' is:
+ * <pre>
+ p0 = 0/0;
+ while( null != c ) {
+ p0 += c.getPos();
+ }
+ * </pre>
+ * </p>
+ * <p>
+ * This flags also sets {@link #JAWT_OSX_CALAYER_QUIRK_SIZE},
+ * i.e. they are related.
+ * </p>
+ * <p>
+ * As of today, this flag is enabled for w/ AWT >= 1.7.0_40.
+ * </p>
+ * <p>
+ * Sync w/ NativeWindowProtocols.h
+ * </p>
+ */
+ public static final int JAWT_OSX_CALAYER_QUIRK_LAYOUT = 1 << 2;
+
+ /**
+ * Returns bitfield of required JAWT OSX CALayer quirks to mediate AWT impl. bugs.
+ * <p>
+ * Returns zero, if platform is not {@link Platform.OSType#MACOS}
+ * or not supporting CALayer, i.e. OSX < 10.6.4.
+ * </p>
+ * <p>
+ * Otherwise includes
+ * <ul>
+ * <li>{@link #JAWT_OSX_CALAYER_QUIRK_SIZE} (always)</li>
+ * <li>{@link #JAWT_OSX_CALAYER_QUIRK_POSITION} if JVM < 1.7.0_40</li>
+ * <li>{@link #JAWT_OSX_CALAYER_QUIRK_LAYOUT} if JVM >= 1.7.0_40</li>
+ * </ul>
+ * </p>
+ */
+ public static int getOSXCALayerQuirks() {
+ int res = 0;
+ if( PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS &&
+ PlatformPropsImpl.OS_VERSION_NUMBER.compareTo(JAWTUtil.JAWT_MacOSXCALayerMinVersion) >= 0 ) {
+
+ /** Knowing impl. all expose the SIZE bug */
+ res |= JAWT_OSX_CALAYER_QUIRK_SIZE;
+
+ final int c = PlatformPropsImpl.JAVA_VERSION_NUMBER.compareTo(PlatformPropsImpl.Version17);
+ if( c < 0 || c == 0 && PlatformPropsImpl.JAVA_VERSION_UPDATE < 40 ) {
+ res |= JAWT_OSX_CALAYER_QUIRK_POSITION;
+ } else {
+ res |= JAWT_OSX_CALAYER_QUIRK_LAYOUT;
+ }
+ }
+ return res;
+ }
+
/**
* @param useOffscreenLayerIfAvailable
* @return
*/
- public static JAWT getJAWT(boolean useOffscreenLayerIfAvailable) {
- final int jawt_version_flags = JAWTFactory.JAWT_VERSION_1_4;
- JAWT jawt = JAWT.create();
-
+ public static JAWT getJAWT(final boolean useOffscreenLayerIfAvailable) {
+ final int jawt_version_flags = JAWTFactory.JAWT_VERSION_1_4;
+ final JAWT jawt = JAWT.create();
+
// default queries
boolean tryOffscreenLayer;
boolean tryOnscreen;
int jawt_version_flags_offscreen = jawt_version_flags;
-
+
if(isOffscreenLayerRequired()) {
- if(Platform.OS_TYPE == Platform.OSType.MACOS) {
- if(Platform.OS_VERSION_NUMBER.compareTo(JAWTUtil.JAWT_MacOSXCALayerMinVersion) >= 0) {
+ if(PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS) {
+ if(PlatformPropsImpl.OS_VERSION_NUMBER.compareTo(JAWTUtil.JAWT_MacOSXCALayerMinVersion) >= 0) {
jawt_version_flags_offscreen |= JAWTUtil.JAWT_MACOSX_USE_CALAYER;
tryOffscreenLayer = true;
tryOnscreen = false;
} else {
- throw new RuntimeException("OSX: Invalid version of Java ("+Platform.JAVA_VERSION_NUMBER+") / OS X ("+Platform.OS_VERSION_NUMBER+")");
+ throw new RuntimeException("OSX: Invalid version of Java ("+PlatformPropsImpl.JAVA_VERSION_NUMBER+") / OS X ("+PlatformPropsImpl.OS_VERSION_NUMBER+")");
}
} else {
- throw new InternalError("offscreen required, but n/a for: "+Platform.OS_TYPE);
+ throw new InternalError("offscreen required, but n/a for: "+PlatformPropsImpl.OS_TYPE);
}
} else if(useOffscreenLayerIfAvailable && isOffscreenLayerSupported()) {
- if(Platform.OS_TYPE == Platform.OSType.MACOS) {
+ if(PlatformPropsImpl.OS_TYPE == Platform.OSType.MACOS) {
jawt_version_flags_offscreen |= JAWTUtil.JAWT_MACOSX_USE_CALAYER;
tryOffscreenLayer = true;
tryOnscreen = true;
} else {
- throw new InternalError("offscreen requested and supported, but n/a for: "+Platform.OS_TYPE);
+ throw new InternalError("offscreen requested and supported, but n/a for: "+PlatformPropsImpl.OS_TYPE);
}
} else {
tryOffscreenLayer = false;
tryOnscreen = true;
- }
+ }
if(DEBUG) {
System.err.println("JAWTUtil.getJAWT(tryOffscreenLayer "+tryOffscreenLayer+", tryOnscreen "+tryOnscreen+")");
}
-
- StringBuilder errsb = new StringBuilder();
+
+ final StringBuilder errsb = new StringBuilder();
if(tryOffscreenLayer) {
errsb.append("Offscreen 0x").append(Integer.toHexString(jawt_version_flags_offscreen));
if( JAWT.getJAWT(jawt, jawt_version_flags_offscreen) ) {
@@ -162,82 +292,118 @@ public class JAWTUtil {
errsb.append("Onscreen 0x").append(Integer.toHexString(jawt_version_flags));
if( JAWT.getJAWT(jawt, jawt_version_flags) ) {
return jawt;
- }
+ }
}
throw new RuntimeException("Unable to initialize JAWT, trials: "+errsb.toString());
}
-
- public static boolean isJAWTUsingOffscreenLayer(JAWT jawt) {
+
+ public static boolean isJAWTUsingOffscreenLayer(final JAWT jawt) {
return 0 != ( jawt.getCachedVersion() & JAWTUtil.JAWT_MACOSX_USE_CALAYER );
}
-
+
static {
+ SKIP_AWT_HIDPI = PropertyAccess.isPropertyDefined("nativewindow.awt.nohidpi", true);
+
if(DEBUG) {
- System.err.println("JAWTUtil initialization (JAWT/JNI/...");
+ System.err.println("JAWTUtil initialization (JAWT/JNI/...); SKIP_AWT_HIDPI "+SKIP_AWT_HIDPI);
// Thread.dumpStack();
}
- JAWTJNILibLoader.initSingleton();
- if(!JAWTJNILibLoader.loadNativeWindow("awt")) {
- throw new NativeWindowException("NativeWindow AWT native library load error.");
- }
headlessMode = GraphicsEnvironment.isHeadless();
- boolean ok = false;
- Class<?> jC = null;
- Method m = null;
- if (!headlessMode) {
+
+ if( headlessMode ) {
+ // Headless case
+ jawtLockObject = null;
+ isQueueFlusherThread = null;
+ j2dExist = false;
+ sunToolkitAWTLockMethod = null;
+ sunToolkitAWTUnlockMethod = null;
+ hasSunToolkitAWTLock = false;
+ // hasSunToolkitAWTLock = false;
+ getScaleFactorMethod = null;
+ } else {
+ // Non-headless case
+ JAWTJNILibLoader.initSingleton(); // load libjawt.so
+ if(!NWJNILibLoader.loadNativeWindow("awt")) { // load libnativewindow_awt.so
+ throw new NativeWindowException("NativeWindow AWT native library load error.");
+ }
jawtLockObject = getJAWT(false); // don't care for offscreen layer here
+
+ boolean j2dExistTmp = false;
+ Class<?> java2DClass = null;
+ Method isQueueFlusherThreadTmp = null;
try {
- jC = Class.forName("jogamp.opengl.awt.Java2D");
- m = jC.getMethod("isQueueFlusherThread", (Class[])null);
- ok = true;
- } catch (Exception e) {
+ java2DClass = Class.forName("jogamp.opengl.awt.Java2D");
+ isQueueFlusherThreadTmp = java2DClass.getMethod("isQueueFlusherThread", (Class[])null);
+ j2dExistTmp = true;
+ } catch (final Exception e) {
}
- } else {
- jawtLockObject = null; // headless !
- }
- isQueueFlusherThread = m;
- j2dExist = ok;
-
- PrivilegedDataBlob1 pdb1 = (PrivilegedDataBlob1) AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- PrivilegedDataBlob1 d = new PrivilegedDataBlob1();
- try {
- final Class<?> sunToolkitClass = Class.forName("sun.awt.SunToolkit");
- d.sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[]{});
- d.sunToolkitAWTLockMethod.setAccessible(true);
- d.sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[]{});
- d.sunToolkitAWTUnlockMethod.setAccessible(true);
- d.ok=true;
- } catch (Exception e) {
- // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
+ isQueueFlusherThread = isQueueFlusherThreadTmp;
+ j2dExist = j2dExistTmp;
+
+ final PrivilegedDataBlob1 pdb1 = (PrivilegedDataBlob1) AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ final PrivilegedDataBlob1 d = new PrivilegedDataBlob1();
+ try {
+ final Class<?> sunToolkitClass = Class.forName("sun.awt.SunToolkit");
+ d.sunToolkitAWTLockMethod = sunToolkitClass.getDeclaredMethod("awtLock", new Class[]{});
+ d.sunToolkitAWTLockMethod.setAccessible(true);
+ d.sunToolkitAWTUnlockMethod = sunToolkitClass.getDeclaredMethod("awtUnlock", new Class[]{});
+ d.sunToolkitAWTUnlockMethod.setAccessible(true);
+ d.ok=true;
+ } catch (final Exception e) {
+ // Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
+ }
+ try {
+ final GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
+ d.getScaleFactorMethod = gd.getClass().getDeclaredMethod("getScaleFactor");
+ d.getScaleFactorMethod.setAccessible(true);
+ } catch (final Throwable t) {}
+ return d;
+ }
+ });
+ sunToolkitAWTLockMethod = pdb1.sunToolkitAWTLockMethod;
+ sunToolkitAWTUnlockMethod = pdb1.sunToolkitAWTUnlockMethod;
+ getScaleFactorMethod = pdb1.getScaleFactorMethod;
+
+ boolean _hasSunToolkitAWTLock = false;
+ if ( pdb1.ok ) {
+ try {
+ sunToolkitAWTLockMethod.invoke(null, (Object[])null);
+ sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
+ _hasSunToolkitAWTLock = true;
+ } catch (final Exception e) {
}
- return d;
- }
- });
- sunToolkitAWTLockMethod = pdb1.sunToolkitAWTLockMethod;
- sunToolkitAWTUnlockMethod = pdb1.sunToolkitAWTUnlockMethod;
-
- boolean _hasSunToolkitAWTLock = false;
- if ( pdb1.ok ) {
- try {
- sunToolkitAWTLockMethod.invoke(null, (Object[])null);
- sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
- _hasSunToolkitAWTLock = true;
- } catch (Exception e) {
}
+ hasSunToolkitAWTLock = _hasSunToolkitAWTLock;
+ // hasSunToolkitAWTLock = false;
}
- hasSunToolkitAWTLock = _hasSunToolkitAWTLock;
- // hasSunToolkitAWTLock = false;
+
+ jawtLock = LockFactory.createRecursiveLock();
jawtToolkitLock = new ToolkitLock() {
+ @Override
public final void lock() {
JAWTUtil.lockToolkit();
- }
+ }
+ @Override
public final void unlock() {
JAWTUtil.unlockToolkit();
}
- };
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ JAWTUtil.validateLocked();
+ }
+ @Override
+ public final void dispose() {
+ // nop
+ }
+ @Override
+ public String toString() {
+ return "JAWTToolkitLock[obj 0x"+Integer.toHexString(hashCode())+", isOwner "+jawtLock.isOwner(Thread.currentThread())+", "+jawtLock+"]";
+ }
+ };
// trigger native AWT toolkit / properties initialization
Map<?,?> desktophints = null;
@@ -247,8 +413,9 @@ public class JAWTUtil {
} else {
final ArrayList<Map<?,?>> desktophintsBucket = new ArrayList<Map<?,?>>(1);
EventQueue.invokeAndWait(new Runnable() {
+ @Override
public void run() {
- Map<?,?> _desktophints = (Map<?,?>)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints"));
+ final Map<?,?> _desktophints = (Map<?,?>)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints"));
if(null!=_desktophints) {
desktophintsBucket.add(_desktophints);
}
@@ -256,9 +423,9 @@ public class JAWTUtil {
});
desktophints = ( desktophintsBucket.size() > 0 ) ? desktophintsBucket.get(0) : null ;
}
- } catch (InterruptedException ex) {
+ } catch (final InterruptedException ex) {
ex.printStackTrace();
- } catch (InvocationTargetException ex) {
+ } catch (final InvocationTargetException ex) {
ex.printStackTrace();
}
@@ -266,7 +433,7 @@ public class JAWTUtil {
System.err.println("JAWTUtil: Has sun.awt.SunToolkit.awtLock/awtUnlock " + hasSunToolkitAWTLock);
System.err.println("JAWTUtil: Has Java2D " + j2dExist);
System.err.println("JAWTUtil: Is headless " + headlessMode);
- int hints = ( null != desktophints ) ? desktophints.size() : 0 ;
+ final int hints = ( null != desktophints ) ? desktophints.size() : 0 ;
System.err.println("JAWTUtil: AWT Desktop hints " + hints);
System.err.println("JAWTUtil: OffscreenLayer Supported: "+isOffscreenLayerSupported()+" - Required "+isOffscreenLayerRequired());
}
@@ -278,11 +445,11 @@ public class JAWTUtil {
public static void initSingleton() {
// just exist to ensure static init has been run
}
-
+
/**
* Called by {@link NativeWindowFactory#shutdown()}
*/
- public static void shutdown() {
+ public static void shutdown() {
}
public static boolean hasJava2D() {
@@ -294,7 +461,7 @@ public class JAWTUtil {
if(j2dExist) {
try {
b = ((Boolean)isQueueFlusherThread.invoke(null, (Object[])null)).booleanValue();
- } catch (Exception e) {}
+ } catch (final Exception e) {}
}
return b;
}
@@ -304,58 +471,123 @@ public class JAWTUtil {
}
/**
- * Locks the AWT's global ReentrantLock.<br>
- *
+ * Locks the AWT's global ReentrantLock.
+ * <p>
* JAWT's native Lock() function calls SunToolkit.awtLock(),
- * which just uses AWT's global ReentrantLock.<br>
+ * which just uses AWT's global ReentrantLock.
+ * </p>
+ * <p>
+ * AWT locking is wrapped through a recursive lock object.
+ * </p>
*/
- private static void awtLock() {
- if(hasSunToolkitAWTLock) {
- try {
- sunToolkitAWTLockMethod.invoke(null, (Object[])null);
- } catch (Exception e) {
- throw new NativeWindowException("SunToolkit.awtLock failed", e);
+ public static void lockToolkit() throws NativeWindowException {
+ jawtLock.lock();
+ if( 1 == jawtLock.getHoldCount() ) {
+ if(!headlessMode && !isJava2DQueueFlusherThread()) {
+ if(hasSunToolkitAWTLock) {
+ try {
+ sunToolkitAWTLockMethod.invoke(null, (Object[])null);
+ } catch (final Exception e) {
+ throw new NativeWindowException("SunToolkit.awtLock failed", e);
+ }
+ } else {
+ jawtLockObject.Lock();
+ }
}
- } else {
- jawtLockObject.Lock();
}
+ if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.lock(): "+jawtLock); }
}
/**
- * Unlocks the AWT's global ReentrantLock.<br>
- *
+ * Unlocks the AWT's global ReentrantLock.
+ * <p>
* JAWT's native Unlock() function calls SunToolkit.awtUnlock(),
- * which just uses AWT's global ReentrantLock.<br>
+ * which just uses AWT's global ReentrantLock.
+ * </p>
+ * <p>
+ * AWT unlocking is wrapped through a recursive lock object.
+ * </p>
*/
- private static void awtUnlock() {
- if(hasSunToolkitAWTLock) {
- try {
- sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
- } catch (Exception e) {
- throw new NativeWindowException("SunToolkit.awtUnlock failed", e);
+ public static void unlockToolkit() {
+ jawtLock.validateLocked();
+ if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.unlock(): "+jawtLock); }
+ if( 1 == jawtLock.getHoldCount() ) {
+ if(!headlessMode && !isJava2DQueueFlusherThread()) {
+ if(hasSunToolkitAWTLock) {
+ try {
+ sunToolkitAWTUnlockMethod.invoke(null, (Object[])null);
+ } catch (final Exception e) {
+ throw new NativeWindowException("SunToolkit.awtUnlock failed", e);
+ }
+ } else {
+ jawtLockObject.Unlock();
+ }
}
- } else {
- jawtLockObject.Unlock();
}
+ jawtLock.unlock();
}
- public static void lockToolkit() throws NativeWindowException {
- if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.lock()"); }
- if(!headlessMode && !isJava2DQueueFlusherThread()) {
- awtLock();
- }
- }
-
- public static void unlockToolkit() {
- if(ToolkitLock.TRACE_LOCK) { System.err.println("JAWTUtil-ToolkitLock.unlock()"); }
- if(!headlessMode && !isJava2DQueueFlusherThread()) {
- awtUnlock();
- }
+ public static final void validateLocked() throws RuntimeException {
+ jawtLock.validateLocked();
}
public static ToolkitLock getJAWTToolkitLock() {
return jawtToolkitLock;
}
-
+
+ /**
+ * Returns the pixel scale factor of the given {@link GraphicsDevice}, if supported.
+ * <p>
+ * If the component does not support pixel scaling the default
+ * <code>one</code> is returned.
+ * </p>
+ * <p>
+ * Note: Currently only supported on OSX since 1.7.0_40 for HiDPI retina displays
+ * </p>
+ * @param device the {@link GraphicsDevice} instance used to query the pixel scale
+ * @return the pixel scale factor
+ */
+ public static final int getPixelScale(final GraphicsDevice device) {
+ if( !SKIP_AWT_HIDPI ) {
+ if( null != getScaleFactorMethod ) {
+ try {
+ final Object res = getScaleFactorMethod.invoke(device);
+ if (res instanceof Integer) {
+ return ((Integer)res).intValue();
+ }
+ } catch (final Throwable t) {}
+ }
+ }
+ return 1;
+ }
+
+ /**
+ * Returns the pixel scale factor of the given {@link GraphicsConfiguration}'s {@link GraphicsDevice}, if supported.
+ * <p>
+ * If the {@link GraphicsDevice} is <code>null</code>, <code>zero</code> is returned.
+ * </p>
+ * <p>
+ * If the component does not support pixel scaling the default
+ * <code>one</code> is returned.
+ * </p>
+ * <p>
+ * Note: Currently only supported on OSX since 1.7.0_40 for HiDPI retina displays
+ * </p>
+ * @param gc the {@link GraphicsConfiguration} instance used to query the pixel scale
+ * @return the pixel scale factor
+ */
+ public static final int getPixelScale(final GraphicsConfiguration gc) {
+ final GraphicsDevice device = null != gc ? gc.getDevice() : null;
+ final int ps;
+ if( null == device ) {
+ ps = 0;
+ } else {
+ ps = JAWTUtil.getPixelScale(device);
+ }
+ if( DEBUG ) {
+ System.err.println("JAWTUtil.updatePixelScale: Fetched "+ps);
+ }
+ return ps;
+ }
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWT_PlatformInfo.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWT_PlatformInfo.java
index 40d7b8032..4f12d1925 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWT_PlatformInfo.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWT_PlatformInfo.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
index 5fd242247..fae8db52a 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,30 +29,35 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package jogamp.nativewindow.jawt.macosx;
+import java.awt.Component;
import java.nio.Buffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.MutableSurface;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.util.PropertyAccess;
import com.jogamp.nativewindow.awt.JAWTWindow;
+import jogamp.nativewindow.Debug;
+import jogamp.nativewindow.awt.AWTMisc;
import jogamp.nativewindow.jawt.JAWT;
import jogamp.nativewindow.jawt.JAWTFactory;
import jogamp.nativewindow.jawt.JAWTUtil;
@@ -62,72 +67,191 @@ import jogamp.nativewindow.jawt.macosx.JAWT_MacOSXDrawingSurfaceInfo;
import jogamp.nativewindow.macosx.OSXUtil;
public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
- public MacOSXJAWTWindow(Object comp, AbstractGraphicsConfiguration config) {
+ /** May lead to deadlock, due to AWT pos comparison .. don't enable for Applets! */
+ private static final boolean DEBUG_CALAYER_POS_CRITICAL;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_CALAYER_POS_CRITICAL = PropertyAccess.isPropertyDefined("nativewindow.debug.JAWT.OSXCALayerPos", true /* jnlpAlias */);
+ }
+
+ public MacOSXJAWTWindow(final Object comp, final AbstractGraphicsConfiguration config) {
super(comp, config);
if(DEBUG) {
dumpInfo();
}
}
+ @Override
protected void invalidateNative() {
- offscreenSurfaceHandle=0;
- offscreenSurfaceHandleSet=false;
- if(isOffscreenLayerSurfaceEnabled()) {
- if(0 != rootSurfaceLayerHandle) {
- OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
- rootSurfaceLayerHandle = 0;
- }
+ if(DEBUG) {
+ System.err.println("MacOSXJAWTWindow.invalidateNative(): osh-enabled "+isOffscreenLayerSurfaceEnabled()+
+ ", osd-set "+offscreenSurfaceDrawableSet+
+ ", osd "+toHexString(offscreenSurfaceDrawable)+
+ ", osl "+toHexString(getAttachedSurfaceLayer())+
+ ", rsl "+toHexString(rootSurfaceLayer)+
+ ", wh "+toHexString(windowHandle)+" - "+Thread.currentThread().getName());
+ }
+ offscreenSurfaceDrawable=0;
+ offscreenSurfaceDrawableSet=false;
+ if( isOffscreenLayerSurfaceEnabled() ) {
if(0 != windowHandle) {
OSXUtil.DestroyNSWindow(windowHandle);
}
+ OSXUtil.RunOnMainThread(false, true /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ if( 0 != rootSurfaceLayer ) {
+ if( 0 != jawtSurfaceLayersHandle) {
+ UnsetJAWTRootSurfaceLayer0(jawtSurfaceLayersHandle, rootSurfaceLayer);
+ }
+ OSXUtil.DestroyCALayer(rootSurfaceLayer);
+ rootSurfaceLayer = 0;
+ }
+ jawtSurfaceLayersHandle = 0;
+ }
+ });
}
windowHandle=0;
}
+ @Override
+ public void setSurfaceScale(final int[] pixelScale) {
+ super.setSurfaceScale(pixelScale);
+ if( 0 != getWindowHandle() ) { // locked at least once !
+ final int hadPixelScaleX = getPixelScaleX();
+ updatePixelScale();
+
+ if( hadPixelScaleX != getPixelScaleX() && 0 != getAttachedSurfaceLayer() ) {
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ final long osl = getAttachedSurfaceLayer();
+ if( 0 != osl ) {
+ OSXUtil.SetCALayerPixelScale(rootSurfaceLayer, osl, getPixelScaleX());
+ }
+ }
+ });
+ }
+ }
+ }
+
+ @Override
protected void attachSurfaceLayerImpl(final long layerHandle) {
- OSXUtil.AddCASublayer(rootSurfaceLayerHandle, layerHandle);
+ OSXUtil.RunOnMainThread(false, false /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ // AWT position is top-left w/ insets, where CALayer position is bottom/left from root CALayer w/o insets.
+ // Determine p0: components location on screen w/o insets.
+ // CALayer position will be determined in native code.
+ // See detailed description in {@link JAWTUtil#JAWT_OSX_CALAYER_QUIRK_LAYOUT}
+ final Point p0 = new Point();
+ final Component outterComp = getLocationOnScreenNonBlocking(p0, component);
+ final java.awt.Insets outterInsets = AWTMisc.getInsets(outterComp, true);
+ final Point p1 = (Point)p0.cloneMutable();
+ p1.translate(-outterComp.getX(), -outterComp.getY());
+ if( null != outterInsets ) {
+ p1.translate(-outterInsets.left, -outterInsets.top);
+ }
+
+ if( DEBUG_CALAYER_POS_CRITICAL ) {
+ final java.awt.Point pA0 = component.getLocationOnScreen();
+ final Point pA1 = new Point(pA0.x, pA0.y);
+ pA1.translate(-outterComp.getX(), -outterComp.getY());
+ if( null != outterInsets ) {
+ pA1.translate(-outterInsets.left, -outterInsets.top);
+ }
+ System.err.println("JAWTWindow.attachSurfaceLayerImpl: "+toHexString(layerHandle) + ", [ins "+outterInsets+"], pA "+pA0+" -> "+pA1+
+ ", p0 "+p0+" -> "+p1+", bounds "+bounds);
+ } else if( DEBUG ) {
+ System.err.println("JAWTWindow.attachSurfaceLayerImpl: "+toHexString(layerHandle) + ", [ins "+outterInsets+"], p0 "+p0+" -> "+p1+", bounds "+bounds);
+ }
+ // HiDPI: uniform pixel scale
+ OSXUtil.AddCASublayer(rootSurfaceLayer, layerHandle, p1.getX(), p1.getY(), getWidth(), getHeight(), getPixelScaleX(), JAWTUtil.getOSXCALayerQuirks());
+ } } );
+ }
+
+ @Override
+ protected void layoutSurfaceLayerImpl(final long layerHandle, final boolean visible) {
+ final int caLayerQuirks = JAWTUtil.getOSXCALayerQuirks();
+ // AWT position is top-left w/ insets, where CALayer position is bottom/left from root CALayer w/o insets.
+ // Determine p0: components location on screen w/o insets.
+ // CALayer position will be determined in native code.
+ // See detailed description in {@link JAWTUtil#JAWT_OSX_CALAYER_QUIRK_LAYOUT}
+ final Point p0 = new Point();
+ final Component outterComp = getLocationOnScreenNonBlocking(p0, component);
+ final java.awt.Insets outterInsets = AWTMisc.getInsets(outterComp, true);
+ final Point p1 = (Point)p0.cloneMutable();
+ p1.translate(-outterComp.getX(), -outterComp.getY());
+ if( null != outterInsets ) {
+ p1.translate(-outterInsets.left, -outterInsets.top);
+ }
+
+ if( DEBUG_CALAYER_POS_CRITICAL ) {
+ final java.awt.Point pA0 = component.getLocationOnScreen();
+ final Point pA1 = new Point(pA0.x, pA0.y);
+ pA1.translate(-outterComp.getX(), -outterComp.getY());
+ if( null != outterInsets ) {
+ pA1.translate(-outterInsets.left, -outterInsets.top);
+ }
+ System.err.println("JAWTWindow.layoutSurfaceLayerImpl: "+toHexString(layerHandle) + ", quirks "+caLayerQuirks+", visible "+visible+
+ ", [ins "+outterInsets+"], pA "+pA0+" -> "+pA1+
+ ", p0 "+p0+" -> "+p1+", bounds "+bounds);
+ } else if( DEBUG ) {
+ System.err.println("JAWTWindow.layoutSurfaceLayerImpl: "+toHexString(layerHandle) + ", quirks "+caLayerQuirks+", visible "+visible+
+ ", [ins "+outterInsets+"], p0 "+p0+" -> "+p1+", bounds "+bounds);
+ }
+ OSXUtil.FixCALayerLayout(rootSurfaceLayer, layerHandle, visible, p1.getX(), p1.getY(), getWidth(), getHeight(), caLayerQuirks);
}
-
- protected void detachSurfaceLayerImpl(final long layerHandle) {
- OSXUtil.RemoveCASublayer(rootSurfaceLayerHandle, layerHandle);
+
+ @Override
+ protected void detachSurfaceLayerImpl(final long layerHandle, final Runnable detachNotify) {
+ OSXUtil.RunOnMainThread(false, true /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ detachNotify.run();
+ OSXUtil.RemoveCASublayer(rootSurfaceLayer, layerHandle);
+ } });
}
-
+
@Override
public final long getWindowHandle() {
return windowHandle;
}
-
+
@Override
public final long getSurfaceHandle() {
- return offscreenSurfaceHandleSet ? offscreenSurfaceHandle : drawable /* super.getSurfaceHandle() */ ;
+ return offscreenSurfaceDrawableSet ? offscreenSurfaceDrawable : drawable /* super.getSurfaceHandle() */ ;
}
-
- public void setSurfaceHandle(long surfaceHandle) {
+
+ @Override
+ public void setSurfaceHandle(final long surfaceHandle) {
if( !isOffscreenLayerSurfaceEnabled() ) {
throw new java.lang.UnsupportedOperationException("Not using CALAYER");
}
if(DEBUG) {
- System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
+ System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): "+toHexString(surfaceHandle));
}
- this.offscreenSurfaceHandle = surfaceHandle;
- this.offscreenSurfaceHandleSet = true;
+ this.offscreenSurfaceDrawable = surfaceHandle;
+ this.offscreenSurfaceDrawableSet = true;
}
+ @Override
protected JAWT fetchJAWTImpl() throws NativeWindowException {
// use offscreen if supported and [ applet or requested ]
return JAWTUtil.getJAWT(getShallUseOffscreenLayer() || isApplet());
}
+
+ @Override
protected int lockSurfaceImpl() throws NativeWindowException {
- int ret = NativeWindow.LOCK_SURFACE_NOT_READY;
- if(null == ds) {
- ds = getJAWT().GetDrawingSurface(component);
- if (ds == null) {
- // Widget not yet realized
- unlockSurfaceImpl();
- return NativeWindow.LOCK_SURFACE_NOT_READY;
- }
+ int ret = NativeSurface.LOCK_SURFACE_NOT_READY;
+ ds = getJAWT().GetDrawingSurface(component);
+ if (ds == null) {
+ // Widget not yet realized
+ unlockSurfaceImpl();
+ return NativeSurface.LOCK_SURFACE_NOT_READY;
}
- int res = ds.Lock();
+ final int res = ds.Lock();
dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ;
if (!dsLocked) {
unlockSurfaceImpl();
@@ -139,25 +263,24 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
// conditions can cause this code to be triggered -- should test
// more)
if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
- ret = NativeWindow.LOCK_SURFACE_CHANGED;
+ ret = NativeSurface.LOCK_SURFACE_CHANGED;
}
- if(null == dsi) {
- if (firstLock) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- dsi = ds.GetDrawingSurfaceInfo();
- return null;
- }
- });
- } else {
- dsi = ds.GetDrawingSurfaceInfo();
- }
- if (dsi == null) {
- unlockSurfaceImpl();
- return NativeWindow.LOCK_SURFACE_NOT_READY;
- }
+ if (firstLock) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ dsi = ds.GetDrawingSurfaceInfo();
+ return null;
+ }
+ });
+ } else {
+ dsi = ds.GetDrawingSurfaceInfo();
}
- updateBounds(dsi.getBounds());
+ if (dsi == null) {
+ unlockSurfaceImpl();
+ return NativeSurface.LOCK_SURFACE_NOT_READY;
+ }
+ updateLockedData(dsi.getBounds());
if (DEBUG && firstLock ) {
dumpInfo();
}
@@ -166,24 +289,24 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
macosxdsi = (JAWT_MacOSXDrawingSurfaceInfo) dsi.platformInfo(getJAWT());
if (macosxdsi == null) {
unlockSurfaceImpl();
- return NativeWindow.LOCK_SURFACE_NOT_READY;
+ return NativeSurface.LOCK_SURFACE_NOT_READY;
}
drawable = macosxdsi.getCocoaViewRef();
-
+
if (drawable == 0) {
unlockSurfaceImpl();
- return NativeWindow.LOCK_SURFACE_NOT_READY;
+ return NativeSurface.LOCK_SURFACE_NOT_READY;
} else {
windowHandle = OSXUtil.GetNSWindow(drawable);
- ret = NativeWindow.LOCK_SUCCESS;
+ ret = NativeSurface.LOCK_SUCCESS;
}
} else {
/**
* Only create a fake invisible NSWindow for the drawable handle
* to please frameworks requiring such (eg. NEWT).
- *
- * The actual surface/ca-layer shall be created/attached
- * by the upper framework (JOGL) since they require more information.
+ *
+ * The actual surface/ca-layer shall be created/attached
+ * by the upper framework (JOGL) since they require more information.
*/
String errMsg = null;
if(0 == drawable) {
@@ -193,31 +316,44 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
} else {
drawable = OSXUtil.GetNSView(windowHandle);
if(0 == drawable) {
- errMsg = "Null NSView of NSWindow 0x"+Long.toHexString(windowHandle);
+ errMsg = "Null NSView of NSWindow "+toHexString(windowHandle);
}
}
if(null == errMsg) {
- // fix caps reflecting offscreen! (no GL available here ..)
- Capabilities caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable();
+ // Fix caps reflecting offscreen! (no GL available here ..)
+ final Capabilities caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable();
caps.setOnscreen(false);
setChosenCapabilities(caps);
}
}
if(null == errMsg) {
- if(0 == rootSurfaceLayerHandle) {
- rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
- if(0 == rootSurfaceLayerHandle) {
- errMsg = "Could not create root CALayer";
- } else if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) {
- errMsg = "Could not set JAWT rootSurfaceLayerHandle 0x"+Long.toHexString(rootSurfaceLayerHandle);
- }
- }
+ jawtSurfaceLayersHandle = GetJAWTSurfaceLayersHandle0(dsi.getBuffer());
+ OSXUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ String errMsg = null;
+ if(0 == rootSurfaceLayer && 0 != jawtSurfaceLayersHandle) {
+ rootSurfaceLayer = OSXUtil.CreateCALayer(bounds.getWidth(), bounds.getHeight(), getPixelScaleX()); // HiDPI: uniform pixel scale
+ if(0 == rootSurfaceLayer) {
+ errMsg = "Could not create root CALayer";
+ } else {
+ try {
+ SetJAWTRootSurfaceLayer0(jawtSurfaceLayersHandle, rootSurfaceLayer);
+ } catch(final Exception e) {
+ errMsg = "Could not set JAWT rootSurfaceLayerHandle "+toHexString(rootSurfaceLayer)+", cause: "+e.getMessage();
+ }
+ }
+ if(null != errMsg) {
+ if(0 != rootSurfaceLayer) {
+ OSXUtil.DestroyCALayer(rootSurfaceLayer);
+ rootSurfaceLayer = 0;
+ }
+ throw new NativeWindowException(errMsg+": "+MacOSXJAWTWindow.this);
+ }
+ }
+ } } );
}
if(null != errMsg) {
- if(0 != rootSurfaceLayerHandle) {
- OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
- rootSurfaceLayerHandle = 0;
- }
if(0 != windowHandle) {
OSXUtil.DestroyNSWindow(windowHandle);
windowHandle = 0;
@@ -226,12 +362,13 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
unlockSurfaceImpl();
throw new NativeWindowException(errMsg+": "+this);
}
- ret = NativeWindow.LOCK_SUCCESS;
+ ret = NativeSurface.LOCK_SUCCESS;
}
-
+
return ret;
}
-
+
+ @Override
protected void unlockSurfaceImpl() throws NativeWindowException {
if(null!=ds) {
if (null!=dsi) {
@@ -250,7 +387,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
System.err.println("MaxOSXJAWTWindow: 0x"+Integer.toHexString(this.hashCode())+" - thread: "+Thread.currentThread().getName());
dumpJAWTInfo();
}
-
+
/**
* {@inheritDoc}
* <p>
@@ -260,32 +397,48 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
* ..
* ds = getJAWT().GetDrawingSurface(component);
* due to a SIGSEGV.
- *
+ *
* Hence we have some threading / sync issues with the native JAWT implementation.
- * </p>
+ * </p>
*/
@Override
- public Point getLocationOnScreen(Point storage) {
- return getLocationOnScreenNonBlocking(storage, component);
- }
+ public Point getLocationOnScreen(Point storage) {
+ if( null == storage ) {
+ storage = new Point();
+ }
+ getLocationOnScreenNonBlocking(storage, component);
+ return storage;
+ }
+ @Override
protected Point getLocationOnScreenNativeImpl(final int x0, final int y0) { return null; }
- private static native boolean SetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
- // private static native boolean UnsetJAWTRootSurfaceLayer0(Buffer jawtDrawingSurfaceInfoBuffer, long caLayer);
-
+
+ private static native long GetJAWTSurfaceLayersHandle0(Buffer jawtDrawingSurfaceInfoBuffer);
+
+ /**
+ * Set the given root CALayer in the JAWT surface
+ */
+ private static native void SetJAWTRootSurfaceLayer0(long jawtSurfaceLayersHandle, long caLayer);
+
+ /**
+ * Unset the given root CALayer in the JAWT surface, passing the NIO DrawingSurfaceInfo buffer
+ */
+ private static native void UnsetJAWTRootSurfaceLayer0(long jawtSurfaceLayersHandle, long caLayer);
+
// Variables for lockSurface/unlockSurface
private JAWT_DrawingSurface ds;
private boolean dsLocked;
private JAWT_DrawingSurfaceInfo dsi;
-
+ private long jawtSurfaceLayersHandle;
+
private JAWT_MacOSXDrawingSurfaceInfo macosxdsi;
-
- private long rootSurfaceLayerHandle = 0; // attached to the JAWT_SurfaceLayer
-
+
+ private volatile long rootSurfaceLayer = 0; // attached to the JAWT_SurfaceLayer
+
private long windowHandle = 0;
- private long offscreenSurfaceHandle = 0;
- private boolean offscreenSurfaceHandleSet = false;
-
+ private long offscreenSurfaceDrawable = 0;
+ private boolean offscreenSurfaceDrawableSet = false;
+
// Workaround for instance of 4796548
private boolean firstLock = true;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/Win32SunJDKReflection.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/Win32SunJDKReflection.java
index 74dabb67f..5d191f7e5 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/Win32SunJDKReflection.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/Win32SunJDKReflection.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -65,6 +65,7 @@ public class Win32SunJDKReflection {
static {
AccessController.doPrivileged(new PrivilegedAction() {
+ @Override
public Object run() {
try {
win32GraphicsDeviceClass = Class.forName("sun.awt.Win32GraphicsDevice");
@@ -74,7 +75,7 @@ public class Win32SunJDKReflection {
win32GraphicsConfigGetVisualMethod = win32GraphicsConfigClass.getDeclaredMethod("getVisual", new Class[] {});
win32GraphicsConfigGetVisualMethod.setAccessible(true);
initted = true;
- } catch (Exception e) {
+ } catch (final Exception e) {
// Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
}
return null;
@@ -82,37 +83,37 @@ public class Win32SunJDKReflection {
});
}
- public static GraphicsConfiguration graphicsConfigurationGet(GraphicsDevice device, int pfdID) {
+ public static GraphicsConfiguration graphicsConfigurationGet(final GraphicsDevice device, final int pfdID) {
if (!initted) {
return null;
}
try {
- return (GraphicsConfiguration) win32GraphicsConfigGetConfigMethod.invoke(null, new Object[] { device, new Integer(pfdID) });
- } catch (Exception e) {
+ return (GraphicsConfiguration) win32GraphicsConfigGetConfigMethod.invoke(null, new Object[] { device, Integer.valueOf(pfdID) });
+ } catch (final Exception e) {
return null;
}
}
- public static int graphicsConfigurationGetPixelFormatID(AbstractGraphicsConfiguration config) {
+ public static int graphicsConfigurationGetPixelFormatID(final AbstractGraphicsConfiguration config) {
try {
if (config instanceof AWTGraphicsConfiguration) {
return graphicsConfigurationGetPixelFormatID(((AWTGraphicsConfiguration) config).getAWTGraphicsConfiguration());
}
return 0;
- } catch (Exception e) {
+ } catch (final Exception e) {
return 0;
}
}
- public static int graphicsConfigurationGetPixelFormatID(GraphicsConfiguration config) {
+ public static int graphicsConfigurationGetPixelFormatID(final GraphicsConfiguration config) {
if (!initted) {
return 0;
}
try {
return ((Integer) win32GraphicsConfigGetVisualMethod.invoke(config, (Object[])null)).intValue();
- } catch (Exception e) {
+ } catch (final Exception e) {
return 0;
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
index 5d1d43792..7ad914e0a 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -41,6 +41,7 @@
package jogamp.nativewindow.jawt.windows;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.util.Point;
@@ -56,34 +57,30 @@ import jogamp.nativewindow.windows.GDIUtil;
public class WindowsJAWTWindow extends JAWTWindow {
- public WindowsJAWTWindow(Object comp, AbstractGraphicsConfiguration config) {
+ public WindowsJAWTWindow(final Object comp, final AbstractGraphicsConfiguration config) {
super(comp, config);
}
+ @Override
protected void invalidateNative() {
windowHandle = 0;
}
- protected void attachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
- protected void detachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
-
+ @Override
protected JAWT fetchJAWTImpl() throws NativeWindowException {
return JAWTUtil.getJAWT(false); // no offscreen
}
-
+
+ @Override
protected int lockSurfaceImpl() throws NativeWindowException {
- int ret = NativeWindow.LOCK_SUCCESS;
+ int ret = NativeSurface.LOCK_SUCCESS;
ds = getJAWT().GetDrawingSurface(component);
if (ds == null) {
// Widget not yet realized
unlockSurfaceImpl();
return LOCK_SURFACE_NOT_READY;
}
- int res = ds.Lock();
+ final int res = ds.Lock();
dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ;
if (!dsLocked) {
unlockSurfaceImpl();
@@ -102,7 +99,7 @@ public class WindowsJAWTWindow extends JAWTWindow {
unlockSurfaceImpl();
return LOCK_SURFACE_NOT_READY;
}
- updateBounds(dsi.getBounds());
+ updateLockedData(dsi.getBounds());
win32dsi = (JAWT_Win32DrawingSurfaceInfo) dsi.platformInfo(getJAWT());
if (win32dsi == null) {
unlockSurfaceImpl();
@@ -117,6 +114,7 @@ public class WindowsJAWTWindow extends JAWTWindow {
return ret;
}
+ @Override
protected void unlockSurfaceImpl() throws NativeWindowException {
drawable = 0; // invalid HDC
if(null!=ds) {
@@ -138,7 +136,8 @@ public class WindowsJAWTWindow extends JAWTWindow {
return windowHandle;
}
- protected Point getLocationOnScreenNativeImpl(int x, int y) {
+ @Override
+ protected Point getLocationOnScreenNativeImpl(final int x, final int y) {
return GDIUtil.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
index 736718de8..9abaed731 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -38,6 +38,7 @@
package jogamp.nativewindow.jawt.x11;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.util.Point;
@@ -53,32 +54,28 @@ import jogamp.nativewindow.x11.X11Lib;
public class X11JAWTWindow extends JAWTWindow {
- public X11JAWTWindow(Object comp, AbstractGraphicsConfiguration config) {
+ public X11JAWTWindow(final Object comp, final AbstractGraphicsConfiguration config) {
super(comp, config);
}
+ @Override
protected void invalidateNative() { }
- protected void attachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
- protected void detachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
-
+ @Override
protected JAWT fetchJAWTImpl() throws NativeWindowException {
return JAWTUtil.getJAWT(false); // no offscreen
}
-
+
+ @Override
protected int lockSurfaceImpl() throws NativeWindowException {
- int ret = NativeWindow.LOCK_SUCCESS;
+ int ret = NativeSurface.LOCK_SUCCESS;
ds = getJAWT().GetDrawingSurface(component);
if (ds == null) {
// Widget not yet realized
unlockSurfaceImpl();
return LOCK_SURFACE_NOT_READY;
}
- int res = ds.Lock();
+ final int res = ds.Lock();
dsLocked = ( 0 == ( res & JAWTFactory.JAWT_LOCK_ERROR ) ) ;
if (!dsLocked) {
unlockSurfaceImpl();
@@ -97,7 +94,7 @@ public class X11JAWTWindow extends JAWTWindow {
unlockSurfaceImpl();
return LOCK_SURFACE_NOT_READY;
}
- updateBounds(dsi.getBounds());
+ updateLockedData(dsi.getBounds());
x11dsi = (JAWT_X11DrawingSurfaceInfo) dsi.platformInfo(getJAWT());
if (x11dsi == null) {
unlockSurfaceImpl();
@@ -111,6 +108,7 @@ public class X11JAWTWindow extends JAWTWindow {
return ret;
}
+ @Override
protected void unlockSurfaceImpl() throws NativeWindowException {
if(null!=ds) {
if (null!=dsi) {
@@ -126,14 +124,16 @@ public class X11JAWTWindow extends JAWTWindow {
x11dsi = null;
}
- protected Point getLocationOnScreenNativeImpl(int x, int y) {
- return X11Lib.GetRelativeLocation( getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
+ @Override
+ protected Point getLocationOnScreenNativeImpl(final int x, final int y) {
+ // surface is locked and hence the device
+ return X11Lib.GetRelativeLocation(getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
}
-
+
// Variables for lockSurface/unlockSurface
private JAWT_DrawingSurface ds;
private boolean dsLocked;
private JAWT_DrawingSurfaceInfo dsi;
private JAWT_X11DrawingSurfaceInfo x11dsi;
-
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java
index 27e0a5e50..fea1be11a 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11SunJDKReflection.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -65,6 +65,7 @@ public class X11SunJDKReflection {
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
try {
x11GraphicsDeviceClass = Class.forName("sun.awt.X11GraphicsDevice");
@@ -75,7 +76,7 @@ public class X11SunJDKReflection {
x11GraphicsConfigGetVisualMethod = x11GraphicsConfigClass.getDeclaredMethod("getVisual", new Class[] {});
x11GraphicsConfigGetVisualMethod.setAccessible(true);
initialized = true;
- } catch (Exception e) {
+ } catch (final Exception e) {
// Either not a Sun JDK or the interfaces have changed since 1.4.2 / 1.5
}
return null;
@@ -83,37 +84,37 @@ public class X11SunJDKReflection {
});
}
- public static long graphicsDeviceGetDisplay(GraphicsDevice device) {
+ public static long graphicsDeviceGetDisplay(final GraphicsDevice device) {
if (!initialized) {
return 0;
}
try {
return ((Long) x11GraphicsDeviceGetDisplayMethod.invoke(device, (Object[])null)).longValue();
- } catch (Exception e) {
+ } catch (final Exception e) {
return 0;
}
}
- public static int graphicsConfigurationGetVisualID(AbstractGraphicsConfiguration config) {
+ public static int graphicsConfigurationGetVisualID(final AbstractGraphicsConfiguration config) {
try {
if (config instanceof AWTGraphicsConfiguration) {
return graphicsConfigurationGetVisualID(((AWTGraphicsConfiguration) config).getAWTGraphicsConfiguration());
}
return 0;
- } catch (Exception e) {
+ } catch (final Exception e) {
return 0;
}
}
- public static int graphicsConfigurationGetVisualID(GraphicsConfiguration config) {
+ public static int graphicsConfigurationGetVisualID(final GraphicsConfiguration config) {
if (!initialized) {
return 0;
}
try {
return ((Integer) x11GraphicsConfigGetVisualMethod.invoke(config, (Object[])null)).intValue();
- } catch (Exception e) {
+ } catch (final Exception e) {
return 0;
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java
index de3206c0c..6b54c32ea 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java
@@ -9,39 +9,39 @@ import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
public class OSXDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
long nsWindow;
-
+
/**
- * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
- * not the actual dummy surface width.
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)},
+ * not the actual dummy surface width.
* The latter is platform specific and small
- * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)},
* not the actual dummy surface height,
* The latter is platform specific and small
*/
- public OSXDummyUpstreamSurfaceHook(int width, int height) {
+ public OSXDummyUpstreamSurfaceHook(final int width, final int height) {
super(width, height);
nsWindow = 0;
}
-
+
@Override
- public final void create(ProxySurface s) {
+ public final void create(final ProxySurface s) {
if(0 == nsWindow && 0 == s.getSurfaceHandle()) {
nsWindow = OSXUtil.CreateNSWindow(0, 0, 64, 64);
if(0 == nsWindow) {
throw new NativeWindowException("Error NS window 0");
}
- long nsView = OSXUtil.GetNSView(nsWindow);
+ final long nsView = OSXUtil.GetNSView(nsWindow);
if(0 == nsView) {
throw new NativeWindowException("Error NS view 0");
}
s.setSurfaceHandle(nsView);
- s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
}
s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
}
-
+
@Override
- public final void destroy(ProxySurface s) {
+ public final void destroy(final ProxySurface s) {
if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
if( 0 == nsWindow || 0 == s.getSurfaceHandle() ) {
throw new InternalError("Owns upstream surface, but no OSX view/window: "+s+", nsWindow 0x"+Long.toHexString(nsWindow));
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index b7a83e133..cf163bd82 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -32,15 +32,24 @@ import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.util.Function;
+import com.jogamp.common.util.FunctionTask;
+import com.jogamp.common.util.RunnableTask;
+
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NWJNILibLoader;
+import jogamp.nativewindow.ToolkitProperties;
-public class OSXUtil {
- private static boolean isInit = false;
+public class OSXUtil implements ToolkitProperties {
+ private static boolean isInit = false;
private static final boolean DEBUG = Debug.debug("OSXUtil");
-
+
+ /** FIXME HiDPI: OSX unique and maximum value {@value} */
+ public static final int MAX_PIXELSCALE = 2;
+
/**
* Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
*/
public static synchronized void initSingleton() {
if(!isInit) {
@@ -50,121 +59,318 @@ public class OSXUtil {
if(!NWJNILibLoader.loadNativeWindow("macosx")) {
throw new NativeWindowException("NativeWindow MacOSX native library load error.");
}
-
+
if( !initIDs0() ) {
throw new NativeWindowException("MacOSX: Could not initialized native stub");
- }
+ }
isInit = true;
}
}
/**
* Called by {@link NativeWindowFactory#shutdown()}
+ * @see ToolkitProperties
*/
- public static void shutdown() {
- }
-
- public static boolean requiresToolkitLock() {
- return false;
- }
-
- public static boolean isNSView(long object) {
- return isNSView0(object);
+ public static void shutdown() { }
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static boolean requiresToolkitLock() { return false; }
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static final boolean hasThreadingIssues() { return false; }
+
+ public static boolean isNSView(final long object) {
+ return 0 != object ? isNSView0(object) : false;
}
-
- public static boolean isNSWindow(long object) {
- return isNSWindow0(object);
+
+ public static boolean isNSWindow(final long object) {
+ return 0 != object ? isNSWindow0(object) : false;
}
-
+
/**
- * In case the <code>windowOrView</code> is top-level,
- * you shall set <code>topLevel</code> to true where
- * insets gets into account to compute the client position as follows:
- * <pre>
- if(topLevel) {
- // top-level position -> client window position
- final Insets insets = GetInsets(windowOrView);
- los.setX(los.getX() + insets.getLeftWidth());
- los.setY(los.getY() + insets.getTopHeight());
- }
- * </pre>
* @param windowOrView
- * @param topLevel
* @param src_x
* @param src_y
- * @return the client position
+ * @return top-left client-area position in window units
*/
- public static Point GetLocationOnScreen(long windowOrView, boolean topLevel, int src_x, int src_y) {
- final Point los = (Point) GetLocationOnScreen0(windowOrView, src_x, src_y);
- if(topLevel) {
- // top-level position -> client window position
- final Insets insets = GetInsets(windowOrView);
- los.setX(los.getX() + insets.getLeftWidth());
- los.setY(los.getY() + insets.getTopHeight());
- }
- return los;
+ public static Point GetLocationOnScreen(final long windowOrView, final int src_x, final int src_y) {
+ return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y);
}
-
- public static Insets GetInsets(long windowOrView) {
+
+ public static Insets GetInsets(final long windowOrView) {
return (Insets) GetInsets0(windowOrView);
}
-
- public static long CreateNSWindow(int x, int y, int width, int height) {
+
+ public static double GetPixelScale(final int screenIndex) {
+ return GetPixelScale0(screenIndex);
+ }
+
+ public static double GetPixelScale(final long windowOrView) {
+ return GetPixelScale1(windowOrView);
+ }
+
+ public static long CreateNSWindow(final int x, final int y, final int width, final int height) {
return CreateNSWindow0(x, y, width, height);
}
- public static void DestroyNSWindow(long nsWindow) {
+ public static void DestroyNSWindow(final long nsWindow) {
DestroyNSWindow0(nsWindow);
}
- public static long GetNSView(long nsWindow) {
+ public static long GetNSView(final long nsWindow) {
return GetNSView0(nsWindow);
}
- public static long GetNSWindow(long nsView) {
+ public static long GetNSWindow(final long nsView) {
return GetNSWindow0(nsView);
}
-
- public static long CreateCALayer(int x, int y, int width, int height) {
- return CreateCALayer0(x, y, width, height);
+
+ /**
+ * Create a CALayer suitable to act as a root CALayer.
+ * @param width width of the CALayer in window units (points)
+ * @param height height of the CALayer in window units (points)
+ * @param contentsScale scale for HiDPI support: pixel-dim = window-dim x scale
+ * @return the new CALayer object
+ * @see #DestroyCALayer(long)
+ * @see #AddCASublayer(long, long)
+ */
+ public static long CreateCALayer(final int width, final int height, final float contentsScale) {
+ final long l = CreateCALayer0(width, height, contentsScale);
+ if(DEBUG) {
+ System.err.println("OSXUtil.CreateCALayer: 0x"+Long.toHexString(l)+" - "+Thread.currentThread().getName());
+ }
+ return l;
}
- public static void AddCASublayer(long rootCALayer, long subCALayer) {
+
+ /**
+ * Attach a sub CALayer to the root CALayer
+ * <p>
+ * Method will trigger a <code>display</code>
+ * call to the CALayer hierarchy to enforce resource creation if required, e.g. an NSOpenGLContext.
+ * </p>
+ * <p>
+ * Hence it is important that related resources are not locked <i>if</i>
+ * they will be used for creation.
+ * </p>
+ * @param rootCALayer
+ * @param subCALayer
+ * @param x x-coord of the sub-CALayer in window units (points)
+ * @param y y-coord of the sub-CALayer in window units (points)
+ * @param width width of the sub-CALayer in window units (points)
+ * @param height height of the sub-CALayer in window units (points)
+ * @param contentsScale scale for HiDPI support: pixel-dim = window-dim x scale
+ * @param caLayerQuirks
+ * @see #CreateCALayer(int, int, float)
+ * @see #RemoveCASublayer(long, long, boolean)
+ */
+ public static void AddCASublayer(final long rootCALayer, final long subCALayer,
+ final int x, final int y, final int width, final int height,
+ final float contentsScale, final int caLayerQuirks) {
if(0==rootCALayer || 0==subCALayer) {
throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
}
- AddCASublayer0(rootCALayer, subCALayer);
+ if(DEBUG) {
+ System.err.println("OSXUtil.AttachCALayer: caLayerQuirks "+caLayerQuirks+", 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
+ }
+ AddCASublayer0(rootCALayer, subCALayer, x, y, width, height, contentsScale, caLayerQuirks);
+ }
+
+ /**
+ * Fix root and sub CALayer position to 0/0 and size
+ * <p>
+ * If the sub CALayer implements the Objective-C NativeWindow protocol NWDedicatedSize (e.g. JOGL's MyNSOpenGLLayer),
+ * the dedicated size is passed to the layer, which propagates it appropriately.
+ * </p>
+ * <p>
+ * On OSX/Java7 our root CALayer's frame position and size gets corrupted by its NSView,
+ * hence we have created the NWDedicatedSize protocol.
+ * </p>
+ *
+ * @param rootCALayer the root surface layer, maybe null.
+ * @param subCALayer the client surface layer, maybe null.
+ * @param visible TODO
+ * @param width the expected width in window units (points)
+ * @param height the expected height in window units (points)
+ * @param caLayerQuirks TODO
+ */
+ public static void FixCALayerLayout(final long rootCALayer, final long subCALayer, final boolean visible, final int x, final int y, final int width, final int height, final int caLayerQuirks) {
+ if( 0==rootCALayer && 0==subCALayer ) {
+ return;
+ }
+ FixCALayerLayout0(rootCALayer, subCALayer, visible, x, y, width, height, caLayerQuirks);
+ }
+
+ /**
+ * Set root and sub CALayer pixelScale / contentScale for HiDPI
+ *
+ * @param rootCALayer the root surface layer, maybe null.
+ * @param subCALayer the client surface layer, maybe null.
+ * @param contentsScale scale for HiDPI support: pixel-dim = window-dim x scale
+ */
+ public static void SetCALayerPixelScale(final long rootCALayer, final long subCALayer, final float contentsScale) {
+ if( 0==rootCALayer && 0==subCALayer ) {
+ return;
+ }
+ SetCALayerPixelScale0(rootCALayer, subCALayer, contentsScale);
}
- public static void RemoveCASublayer(long rootCALayer, long subCALayer) {
+
+ /**
+ * Detach a sub CALayer from the root CALayer.
+ */
+ public static void RemoveCASublayer(final long rootCALayer, final long subCALayer) {
if(0==rootCALayer || 0==subCALayer) {
throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
}
+ if(DEBUG) {
+ System.err.println("OSXUtil.DetachCALayer: 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
+ }
RemoveCASublayer0(rootCALayer, subCALayer);
}
- public static void DestroyCALayer(long caLayer) {
+
+ /**
+ * Destroy a CALayer.
+ * @see #CreateCALayer(int, int, float)
+ */
+ public static void DestroyCALayer(final long caLayer) {
if(0==caLayer) {
throw new IllegalArgumentException("caLayer 0x"+Long.toHexString(caLayer));
}
- DestroyCALayer0(caLayer);
+ if(DEBUG) {
+ System.err.println("OSXUtil.DestroyCALayer: 0x"+Long.toHexString(caLayer)+" - "+Thread.currentThread().getName());
+ }
+ DestroyCALayer0(caLayer);
}
-
- public static void RunOnMainThread(boolean waitUntilDone, Runnable runnable) {
- if(IsMainThread0()) {
+
+ /**
+ * Run on OSX UI main thread.
+ * <p>
+ * 'waitUntilDone' is implemented on Java site via lock/wait on {@link RunnableTask} to not freeze OSX main thread.
+ * </p>
+ *
+ * @param waitUntilDone
+ * @param kickNSApp if <code>true</code> issues {@link #KickNSApp()}
+ * @param runnable
+ */
+ public static void RunOnMainThread(final boolean waitUntilDone, final boolean kickNSApp, final Runnable runnable) {
+ if( IsMainThread0() ) {
runnable.run(); // don't leave the JVM
} else {
- RunOnMainThread0(waitUntilDone, runnable);
+ // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
+ // otherwise we may freeze the OSX main thread.
+ Throwable throwable = null;
+ final Object sync = new Object();
+ final RunnableTask rt = new RunnableTask( runnable, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err );
+ synchronized(sync) {
+ RunOnMainThread0(kickNSApp, rt);
+ if( waitUntilDone ) {
+ try {
+ sync.wait();
+ } catch (final InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rt.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Run later on ..
+ * @param onMain if true, run on main-thread, otherwise on the current OSX thread.
+ * @param runnable
+ * @param delay delay to run the runnable in milliseconds
+ */
+ public static void RunLater(final boolean onMain, final Runnable runnable, final int delay) {
+ RunLater0(onMain, false /* kickNSApp */, new RunnableTask( runnable, null, true, System.err ), delay);
+ }
+
+ /**
+ * Wakes up NSApp thread by sending an empty NSEvent ..
+ * <p>
+ * This is deemed important <i>sometimes</i> where resources shall get freed ASAP, e.g. GL context etc.
+ * </p>
+ * <p>
+ * The following scenarios requiring this <i>wake-up</i> are currently known:
+ * <ul>
+ * <li>Destruction of an OpenGL context</li>
+ * <li>Destruction of Windows .. ?</li>
+ * <li>Stopping the NSApp</li>
+ * </ul>
+ * </p>
+ * FIXME: Complete list of scenarios and reason it.
+ */
+ public static void KickNSApp() {
+ KickNSApp0();
+ }
+
+ private static Runnable _nop = new Runnable() { @Override public void run() {}; };
+
+ /** Issues a {@link #RunOnMainThread(boolean, boolean, Runnable)} w/ an <i>NOP</i> runnable, while waiting until done and issuing {@link #KickNSApp()}. */
+ public static void WaitUntilFinish() {
+ RunOnMainThread(true, true /* kickNSApp */, _nop);
+ }
+
+ /**
+ * Run on OSX UI main thread.
+ * <p>
+ * 'waitUntilDone' is implemented on Java site via lock/wait on {@link FunctionTask} to not freeze OSX main thread.
+ * </p>
+ *
+ * @param waitUntilDone
+ * @param kickNSApp if <code>true</code> issues {@link #KickNSApp()}
+ * @param func
+ */
+ public static <R,A> R RunOnMainThread(final boolean waitUntilDone, final boolean kickNSApp, final Function<R,A> func, final A... args) {
+ if( IsMainThread0() ) {
+ return func.eval(args); // don't leave the JVM
+ } else {
+ // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
+ // otherwise we may freeze the OSX main thread.
+ Throwable throwable = null;
+ final Object sync = new Object();
+ final FunctionTask<R,A> rt = new FunctionTask<R,A>( func, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err );
+ synchronized(sync) {
+ rt.setArgs(args);
+ RunOnMainThread0(kickNSApp, rt);
+ if( waitUntilDone ) {
+ try {
+ sync.wait();
+ } catch (final InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rt.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+ return rt.getResult();
}
}
-
+
public static boolean IsMainThread() {
return IsMainThread0();
}
-
+
/** Returns the screen refresh rate in Hz. If unavailable, returns 60Hz. */
- public static int GetScreenRefreshRate(int scrn_idx) {
+ public static int GetScreenRefreshRate(final int scrn_idx) {
return GetScreenRefreshRate0(scrn_idx);
}
-
+
/***
private static boolean isAWTEDTMainThreadInit = false;
private static boolean isAWTEDTMainThread;
-
+
public synchronized static boolean isAWTEDTMainThread() {
if(!isAWTEDTMainThreadInit) {
isAWTEDTMainThreadInit = true;
@@ -178,24 +384,30 @@ public class OSXUtil {
} else {
isAWTEDTMainThread = false;
}
- }
+ }
return isAWTEDTMainThread;
} */
-
+
private static native boolean initIDs0();
private static native boolean isNSView0(long object);
private static native boolean isNSWindow0(long object);
private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y);
private static native Object GetInsets0(long windowOrView);
+ private static native double GetPixelScale0(int screenIndex);
+ private static native double GetPixelScale1(long windowOrView);
private static native long CreateNSWindow0(int x, int y, int width, int height);
private static native void DestroyNSWindow0(long nsWindow);
private static native long GetNSView0(long nsWindow);
private static native long GetNSWindow0(long nsView);
- private static native long CreateCALayer0(int x, int y, int width, int height);
- private static native void AddCASublayer0(long rootCALayer, long subCALayer);
+ private static native long CreateCALayer0(int width, int height, float contentsScale);
+ private static native void AddCASublayer0(long rootCALayer, long subCALayer, int x, int y, int width, int height, float contentsScale, int caLayerQuirks);
+ private static native void FixCALayerLayout0(long rootCALayer, long subCALayer, boolean visible, int x, int y, int width, int height, int caLayerQuirks);
+ private static native void SetCALayerPixelScale0(long rootCALayer, long subCALayer, float contentsScale);
private static native void RemoveCASublayer0(long rootCALayer, long subCALayer);
private static native void DestroyCALayer0(long caLayer);
- private static native void RunOnMainThread0(boolean waitUntilDone, Runnable runnable);
+ private static native void RunOnMainThread0(boolean kickNSApp, Runnable runnable);
+ private static native void RunLater0(boolean onMain, boolean kickNSApp, Runnable runnable, int delay);
+ private static native void KickNSApp0();
private static native boolean IsMainThread0();
private static native int GetScreenRefreshRate0(int scrn_idx);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java
index aa5f3dac5..a08cf9b51 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java
@@ -9,33 +9,33 @@ import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
public class GDIDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
/**
- * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
- * not the actual dummy surface width.
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)},
+ * not the actual dummy surface width.
* The latter is platform specific and small
- * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)},
* not the actual dummy surface height,
* The latter is platform specific and small
*/
- public GDIDummyUpstreamSurfaceHook(int width, int height) {
+ public GDIDummyUpstreamSurfaceHook(final int width, final int height) {
super(width, height);
}
-
+
@Override
- public final void create(ProxySurface s) {
+ public final void create(final ProxySurface s) {
final GDISurface ms = (GDISurface)s;
- if(0 == ms.getWindowHandle()) {
+ if(0 == ms.getWindowHandle()) {
final long windowHandle = GDIUtil.CreateDummyWindow(0, 0, 64, 64);
if(0 == windowHandle) {
throw new NativeWindowException("Error windowHandle 0, werr: "+GDI.GetLastError());
- }
+ }
ms.setWindowHandle(windowHandle);
- ms.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ ms.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
}
s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
}
-
+
@Override
- public final void destroy(ProxySurface s) {
+ public final void destroy(final ProxySurface s) {
final GDISurface ms = (GDISurface)s;
if( ms.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
if( 0 == ms.getWindowHandle() ) {
@@ -46,5 +46,5 @@ public class GDIDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize
ms.setWindowHandle(0);
ms.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
}
- }
+ }
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
index 3db2b5fc9..2f335c428 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
@@ -43,10 +43,12 @@ import jogamp.nativewindow.windows.GDI;
* allowing the use of HDC via lockSurface()/unlockSurface() protocol.
* The latter will get and release the HDC.
* The size via getWidth()/getHeight() is invalid.
+ *
+ * @see ProxySurface
*/
public class GDISurface extends ProxySurfaceImpl {
- protected long windowHandle;
- protected long surfaceHandle;
+ private long windowHandle;
+ private long surfaceHandle;
/**
* @param cfg the {@link AbstractGraphicsConfiguration} to be used
@@ -56,37 +58,37 @@ public class GDISurface extends ProxySurfaceImpl {
* owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
* otherwise <code>false</code>. Owning the device implies closing it at {@link #destroyNotify()}.
*/
- public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ public GDISurface(final AbstractGraphicsConfiguration cfg, final long windowHandle, final UpstreamSurfaceHook upstream, final boolean ownsDevice) {
super(cfg, upstream, ownsDevice);
this.windowHandle=windowHandle;
this.surfaceHandle=0;
}
@Override
- protected void invalidateImpl() {
+ protected void invalidateImpl() {
if(0 != surfaceHandle) {
throw new NativeWindowException("didn't release surface Handle: "+this);
}
windowHandle = 0;
// surfaceHandle = 0;
}
-
+
/**
* {@inheritDoc}
* <p>
- * Actually the window handle (HWND), since the surfaceHandle (HDC) is derived
+ * Actually the window handle (HWND), since the surfaceHandle (HDC) is derived
* from it at {@link #lockSurface()}.
- * </p>
+ * </p>
*/
@Override
- public final void setSurfaceHandle(long surfaceHandle) {
+ public final void setSurfaceHandle(final long surfaceHandle) {
this.windowHandle = surfaceHandle;
}
/**
- * Sets the window handle (HWND).
+ * Sets the window handle (HWND).
*/
- public final void setWindowHandle(long windowHandle) {
+ public final void setWindowHandle(final long windowHandle) {
this.windowHandle = windowHandle;
}
@@ -116,7 +118,7 @@ public class GDISurface extends ProxySurfaceImpl {
final protected void unlockSurfaceImpl() {
if (0 != surfaceHandle) {
if(0 == GDI.ReleaseDC(windowHandle, surfaceHandle)) {
- throw new NativeWindowException("DC not released: "+this+", isWindow "+GDI.IsWindow(windowHandle)+", werr "+GDI.GetLastError()+", thread: "+Thread.currentThread().getName());
+ throw new NativeWindowException("DC not released: "+this+", isWindow "+GDI.IsWindow(windowHandle)+", werr "+GDI.GetLastError()+", thread: "+Thread.currentThread().getName());
}
surfaceHandle=0;
}
@@ -126,4 +128,15 @@ public class GDISurface extends ProxySurfaceImpl {
final public long getSurfaceHandle() {
return surfaceHandle;
}
+
+ @Override
+ public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
+ return pixelUnitsAndResult; // no pixelScale factor
+ }
+
+ @Override
+ public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
+ return windowUnitsAndResult; // no pixelScale factor
+ }
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
index 613c76032..c409b6a39 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
@@ -33,21 +33,22 @@ import javax.media.nativewindow.NativeWindowFactory;
import jogamp.nativewindow.NWJNILibLoader;
import jogamp.nativewindow.Debug;
-import jogamp.nativewindow.x11.X11Util;
+import jogamp.nativewindow.ToolkitProperties;
-public class GDIUtil {
+public class GDIUtil implements ToolkitProperties {
private static final boolean DEBUG = Debug.debug("GDIUtil");
-
+
private static final String dummyWindowClassNameBase = "_dummyWindow_clazz" ;
private static RegisteredClassFactory dummyWindowClassFactory;
- private static boolean isInit = false;
-
+ private static volatile boolean isInit = false;
+
/**
* Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
*/
public static synchronized void initSingleton() {
if(!isInit) {
- synchronized(X11Util.class) {
+ synchronized(GDIUtil.class) {
if(!isInit) {
if(DEBUG) {
System.out.println("GDI.initSingleton()");
@@ -58,53 +59,95 @@ public class GDIUtil {
if( !initIDs0() ) {
throw new NativeWindowException("GDI: Could not initialized native stub");
}
- dummyWindowClassFactory = new RegisteredClassFactory(dummyWindowClassNameBase, getDummyWndProc0());
+ dummyWindowClassFactory = new RegisteredClassFactory(dummyWindowClassNameBase, getDummyWndProc0(),
+ true /* useDummyDispatchThread */,
+ 0 /* iconSmallHandle */, 0 /* iconBigHandle */);
+ if(DEBUG) {
+ System.out.println("GDI.initSingleton() dummyWindowClassFactory "+dummyWindowClassFactory);
+ }
isInit = true;
}
}
}
}
-
+
/**
* Called by {@link NativeWindowFactory#shutdown()}
+ * @see ToolkitProperties
*/
- public static void shutdown() {
+ public static void shutdown() {
}
-
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
public static boolean requiresToolkitLock() { return false; }
-
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static final boolean hasThreadingIssues() { return false; }
+
private static RegisteredClass dummyWindowClass = null;
private static Object dummyWindowSync = new Object();
-
- public static long CreateDummyWindow(int x, int y, int width, int height) {
+
+ public static long CreateDummyWindow(final int x, final int y, final int width, final int height) {
synchronized(dummyWindowSync) {
dummyWindowClass = dummyWindowClassFactory.getSharedClass();
- return CreateDummyWindow0(dummyWindowClass.getHandle(), dummyWindowClass.getName(), dummyWindowClass.getName(), x, y, width, height);
+ if(DEBUG) {
+ System.out.println("GDI.CreateDummyWindow() dummyWindowClassFactory "+dummyWindowClassFactory);
+ System.out.println("GDI.CreateDummyWindow() dummyWindowClass "+dummyWindowClass);
+ }
+ return CreateDummyWindow0(dummyWindowClass.getHInstance(), dummyWindowClass.getName(), dummyWindowClass.getHDispThreadContext(), dummyWindowClass.getName(), x, y, width, height);
}
}
-
- public static boolean DestroyDummyWindow(long hwnd) {
+
+ public static boolean DestroyDummyWindow(final long hwnd) {
boolean res;
synchronized(dummyWindowSync) {
if( null == dummyWindowClass ) {
throw new InternalError("GDI Error ("+dummyWindowClassFactory.getSharedRefCount()+"): SharedClass is null");
}
- res = GDI.DestroyWindow(hwnd);
+ res = DestroyWindow0(dummyWindowClass.getHDispThreadContext(), hwnd);
dummyWindowClassFactory.releaseSharedClass();
}
return res;
}
-
- public static Point GetRelativeLocation(long src_win, long dest_win, int src_x, int src_y) {
+
+ public static Point GetRelativeLocation(final long src_win, final long dest_win, final int src_x, final int src_y) {
return (Point) GetRelativeLocation0(src_win, dest_win, src_x, src_y);
}
-
- public static native boolean CreateWindowClass(long hInstance, String clazzName, long wndProc);
- public static native boolean DestroyWindowClass(long hInstance, String className);
-
+
+ public static boolean IsUndecorated(final long win) {
+ return IsUndecorated0(win);
+ }
+
+ public static boolean IsChild(final long win) {
+ return IsChild0(win);
+ }
+
+ public static void SetProcessThreadsAffinityMask(final long affinityMask, final boolean verbose) {
+ SetProcessThreadsAffinityMask0(affinityMask, verbose);
+ }
+
+ private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
+
+ /** Creates WNDCLASSEX instance */
+ static native boolean CreateWindowClass0(long hInstance, String clazzName, long wndProc, long iconSmallHandle, long iconBigHandle);
+ /** Destroys WNDCLASSEX instance */
+ static native boolean DestroyWindowClass0(long hInstance, String className, long dispThreadCtx);
+ static native long CreateDummyDispatchThread0();
+
private static native boolean initIDs0();
- private static native long getDummyWndProc0();
+ private static native long getDummyWndProc0();
private static native Object GetRelativeLocation0(long src_win, long dest_win, int src_x, int src_y);
-
- static native long CreateDummyWindow0(long hInstance, String className, String windowName, int x, int y, int width, int height);
+ private static native boolean IsChild0(long win);
+ private static native boolean IsUndecorated0(long win);
+
+ private static native void SetProcessThreadsAffinityMask0(long affinityMask, boolean verbose);
+
+ private static native long CreateDummyWindow0(long hInstance, String className, long dispThreadCtx, String windowName, int x, int y, int width, int height);
+ private static native boolean DestroyWindow0(long dispThreadCtx, long win);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
index afb3daf7c..3c7b1adfb 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClass.java
@@ -29,17 +29,25 @@
package jogamp.nativewindow.windows;
public class RegisteredClass {
- long hInstance;
- String className;
+ private final long hInstance;
+ private final String className;
+ private final long hDDTCtx;
- RegisteredClass(long hInst, String name) {
- hInstance = hInst;
- className = name;
+ RegisteredClass(final long hInst, final String name, final long hDispatchThreadCtx) {
+ this.hInstance = hInst;
+ this.className = name;
+ this.hDDTCtx = hDispatchThreadCtx;
}
- public final long getHandle() { return hInstance; }
+ /** Application handle, same as {@link RegisteredClassFactory#getHInstance()}. */
+ public final long getHInstance() { return hInstance; }
+
+ /** Unique Window Class Name */
public final String getName() { return className; }
+ /** Unique associated dispatch thread context for this Window Class, or 0 for none. */
+ public final long getHDispThreadContext() { return hDDTCtx; }
+
@Override
- public final String toString() { return "RegisteredClass[handle 0x"+Long.toHexString(hInstance)+", "+className+"]"; }
+ public final String toString() { return "RegisteredClass[handle 0x"+Long.toHexString(hInstance)+", "+className+", dtx 0x"+Long.toHexString(hDDTCtx)+"]"; }
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java
index 00bedfc8e..e3ea49314 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/RegisteredClassFactory.java
@@ -29,46 +29,76 @@
package jogamp.nativewindow.windows;
import jogamp.nativewindow.Debug;
+
import java.util.ArrayList;
+
import javax.media.nativewindow.NativeWindowException;
public class RegisteredClassFactory {
- static final boolean DEBUG = Debug.debug("RegisteredClass");
- private static ArrayList<RegisteredClassFactory> registeredFactories = new ArrayList<RegisteredClassFactory>();
-
- private String classBaseName;
- private long wndProc;
+ private static final boolean DEBUG = Debug.debug("RegisteredClass");
+ private static final ArrayList<RegisteredClassFactory> registeredFactories;
+ private static final long hInstance;
+
+ static {
+ hInstance = GDI.GetApplicationHandle();
+ if( 0 == hInstance ) {
+ throw new NativeWindowException("Error: Null ModuleHandle for Application");
+ }
+ registeredFactories = new ArrayList<RegisteredClassFactory>();
+ }
+
+ private final String classBaseName;
+ private final long wndProc;
+ private final boolean useDummyDispatchThread;
+ private final long iconSmallHandle, iconBigHandle;
private RegisteredClass sharedClass = null;
private int classIter = 0;
private int sharedRefCount = 0;
private final Object sync = new Object();
+ private String toHexString(final long l) { return "0x"+Long.toHexString(l); }
+
+ @Override
+ public final String toString() { return "RegisteredClassFactory[moduleHandle "+toHexString(hInstance)+", "+classBaseName+
+ ", wndProc "+toHexString(wndProc)+", useDDT "+useDummyDispatchThread+", shared[refCount "+sharedRefCount+", class "+sharedClass+"]]"; }
+
/**
- * Release the {@link RegisteredClass} of all {@link RegisteredClassFactory}.
+ * Release the {@link RegisteredClass} of all {@link RegisteredClassFactory}.
*/
public static void shutdownSharedClasses() {
synchronized(registeredFactories) {
+ if( DEBUG ) {
+ System.err.println("RegisteredClassFactory.shutdownSharedClasses: "+registeredFactories.size());
+ }
for(int j=0; j<registeredFactories.size(); j++) {
final RegisteredClassFactory rcf = registeredFactories.get(j);
synchronized(rcf.sync) {
if(null != rcf.sharedClass) {
- GDIUtil.DestroyWindowClass(rcf.sharedClass.getHandle(), rcf.sharedClass.getName());
+ GDIUtil.DestroyWindowClass0(rcf.sharedClass.getHInstance(), rcf.sharedClass.getName(), rcf.sharedClass.getHDispThreadContext());
rcf.sharedClass = null;
rcf.sharedRefCount = 0;
- rcf.classIter = 0;
+ rcf.classIter = 0;
if(DEBUG) {
- System.err.println("RegisteredClassFactory #"+j+"/"+registeredFactories.size()+" shutdownSharedClasses : "+rcf.sharedClass);
+ System.err.println("RegisteredClassFactory #"+j+"/"+registeredFactories.size()+": shutdownSharedClasses : "+rcf.sharedClass);
}
+ } else if(DEBUG) {
+ System.err.println("RegisteredClassFactory #"+j+"/"+registeredFactories.size()+": null");
}
}
}
}
}
- public RegisteredClassFactory(String classBaseName, long wndProc) {
+ /** Application handle. */
+ public static long getHInstance() { return hInstance; }
+
+ public RegisteredClassFactory(final String classBaseName, final long wndProc, final boolean useDummyDispatchThread, final long iconSmallHandle, final long iconBigHandle) {
this.classBaseName = classBaseName;
this.wndProc = wndProc;
+ this.useDummyDispatchThread = useDummyDispatchThread;
+ this.iconSmallHandle = iconSmallHandle;
+ this.iconBigHandle = iconBigHandle;
synchronized(registeredFactories) {
registeredFactories.add(this);
}
@@ -80,23 +110,28 @@ public class RegisteredClassFactory {
if( null != sharedClass ) {
throw new InternalError("Error ("+sharedRefCount+"): SharedClass not null: "+sharedClass);
}
- long hInstance = GDI.GetApplicationHandle();
- if( 0 == hInstance ) {
- throw new NativeWindowException("Error: Null ModuleHandle for Application");
- }
String clazzName = null;
boolean registered = false;
- final int classIterMark = classIter - 1;
+ final int classIterMark = classIter - 1;
while ( !registered && classIterMark != classIter ) {
// Retry with next clazz name, this could happen if more than one JVM is running
clazzName = classBaseName + classIter;
classIter++;
- registered = GDIUtil.CreateWindowClass(hInstance, clazzName, wndProc);
+ registered = GDIUtil.CreateWindowClass0(hInstance, clazzName, wndProc, iconSmallHandle, iconBigHandle);
}
if( !registered ) {
throw new NativeWindowException("Error: Could not create WindowClass: "+clazzName);
}
- sharedClass = new RegisteredClass(hInstance, clazzName);
+ final long hDispatchThread;
+ if( useDummyDispatchThread ) {
+ hDispatchThread = GDIUtil.CreateDummyDispatchThread0();
+ if( 0 == hDispatchThread ) {
+ throw new NativeWindowException("Error: Could not create DDT "+clazzName);
+ }
+ } else {
+ hDispatchThread = 0;
+ }
+ sharedClass = new RegisteredClass(hInstance, clazzName, hDispatchThread);
if(DEBUG) {
System.err.println("RegisteredClassFactory getSharedClass ("+sharedRefCount+") initialized: "+sharedClass);
}
@@ -121,7 +156,7 @@ public class RegisteredClassFactory {
throw new InternalError("Error ("+sharedRefCount+"): SharedClass is null");
}
if( 0 == sharedRefCount ) {
- GDIUtil.DestroyWindowClass(sharedClass.getHandle(), sharedClass.getName());
+ GDIUtil.DestroyWindowClass0(sharedClass.getHInstance(), sharedClass.getName(), sharedClass.getHDispThreadContext());
if(DEBUG) {
System.err.println("RegisteredClassFactory releaseSharedClass ("+sharedRefCount+") released: "+sharedClass);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java
index 4f8cff8c5..0ac3d4a2e 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Capabilities.java
@@ -35,7 +35,7 @@ import javax.media.nativewindow.VisualIDHolder;
public class X11Capabilities extends Capabilities {
final private XVisualInfo xVisualInfo; // maybe null if !onscreen
- public X11Capabilities(XVisualInfo xVisualInfo) {
+ public X11Capabilities(final XVisualInfo xVisualInfo) {
super();
this.xVisualInfo = xVisualInfo;
}
@@ -49,7 +49,7 @@ public class X11Capabilities extends Capabilities {
public Object clone() {
try {
return super.clone();
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
throw new NativeWindowException(e);
}
}
@@ -59,7 +59,7 @@ public class X11Capabilities extends Capabilities {
final public boolean hasXVisualInfo() { return null!=xVisualInfo; }
@Override
- final public int getVisualID(VIDType type) throws NativeWindowException {
+ final public int getVisualID(final VIDType type) throws NativeWindowException {
switch(type) {
case INTRINSIC:
case NATIVE:
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
index 55a29dd5e..7e61ba6d0 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
@@ -14,47 +14,57 @@ import com.jogamp.nativewindow.x11.X11GraphicsScreen;
public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
/**
- * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
- * not the actual dummy surface width.
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)},
+ * not the actual dummy surface width.
* The latter is platform specific and small
- * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)},
* not the actual dummy surface height,
* The latter is platform specific and small
*/
- public X11DummyUpstreamSurfaceHook(int width, int height) {
+ public X11DummyUpstreamSurfaceHook(final int width, final int height) {
super(width, height);
}
-
+
@Override
- public final void create(ProxySurface s) {
+ public final void create(final ProxySurface s) {
final X11GraphicsConfiguration cfg = (X11GraphicsConfiguration) s.getGraphicsConfiguration();
final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen();
final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice();
- if(0 == device.getHandle()) {
- device.open();
- s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
- }
- if( 0 == s.getSurfaceHandle() ) {
- final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64);
- if(0 == windowHandle) {
- throw new NativeWindowException("Creating dummy window failed w/ "+cfg);
+ device.lock();
+ try {
+ if(0 == device.getHandle()) {
+ device.open();
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ if( 0 == s.getSurfaceHandle() ) {
+ final long windowHandle = X11Lib.CreateWindow(0, device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64, false, false);
+ if(0 == windowHandle) {
+ throw new NativeWindowException("Creating dummy window failed w/ "+cfg);
+ }
+ s.setSurfaceHandle(windowHandle);
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
}
- s.setSurfaceHandle(windowHandle);
- s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ } finally {
+ device.unlock();
}
- s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
}
-
+
@Override
- public final void destroy(ProxySurface s) {
+ public final void destroy(final ProxySurface s) {
if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
final X11GraphicsDevice device = (X11GraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice();
if( 0 == s.getSurfaceHandle() ) {
throw new InternalError("Owns upstream surface, but no X11 window: "+s);
}
- X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle());
- s.setSurfaceHandle(0);
- s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ device.lock();
+ try {
+ X11Lib.DestroyWindow(device.getHandle(), s.getSurfaceHandle());
+ s.setSurfaceHandle(0);
+ s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ } finally {
+ device.unlock();
+ }
}
}
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java
index b11dd1df1..e12c3fd13 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -47,12 +47,13 @@ import com.jogamp.nativewindow.x11.X11GraphicsScreen;
public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactory {
public static void registerFactory() {
GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class, new X11GraphicsConfigurationFactory());
- }
+ }
private X11GraphicsConfigurationFactory() {
}
-
+
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID)
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested, final CapabilitiesChooser chooser, final AbstractGraphicsScreen screen, final int nativeVisualID)
throws IllegalArgumentException, NativeWindowException {
if(!(screen instanceof X11GraphicsScreen)) {
@@ -71,15 +72,15 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor
return res;
}
- public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, int visualID)
+ public static XVisualInfo getXVisualInfo(final AbstractGraphicsScreen screen, final int visualID)
{
- XVisualInfo xvi_temp = XVisualInfo.create();
+ final XVisualInfo xvi_temp = XVisualInfo.create();
xvi_temp.setVisualid(visualID);
xvi_temp.setScreen(screen.getIndex());
- int num[] = { -1 };
- long display = screen.getDevice().getHandle();
+ final int num[] = { -1 };
+ final long display = screen.getDevice().getHandle();
- XVisualInfo[] xvis = X11Lib.XGetVisualInfo(display, X11Lib.VisualIDMask|X11Lib.VisualScreenMask, xvi_temp, num, 0);
+ final XVisualInfo[] xvis = X11Lib.XGetVisualInfo(display, X11Lib.VisualIDMask|X11Lib.VisualScreenMask, xvi_temp, num, 0);
if(xvis==null || num[0]<1) {
return null;
@@ -88,28 +89,28 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor
return XVisualInfo.create(xvis[0]);
}
- public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, CapabilitiesImmutable capabilities)
+ public static XVisualInfo getXVisualInfo(final AbstractGraphicsScreen screen, final CapabilitiesImmutable capabilities)
{
- XVisualInfo xv = getXVisualInfoImpl(screen, capabilities, 4 /* TrueColor */);
+ final XVisualInfo xv = getXVisualInfoImpl(screen, capabilities, 4 /* TrueColor */);
if(null!=xv) return xv;
return getXVisualInfoImpl(screen, capabilities, 5 /* DirectColor */);
}
- private static XVisualInfo getXVisualInfoImpl(AbstractGraphicsScreen screen, CapabilitiesImmutable capabilities, int c_class)
+ private static XVisualInfo getXVisualInfoImpl(final AbstractGraphicsScreen screen, final CapabilitiesImmutable capabilities, final int c_class)
{
XVisualInfo ret = null;
- int[] num = { -1 };
+ final int[] num = { -1 };
- XVisualInfo vinfo_template = XVisualInfo.create();
+ final XVisualInfo vinfo_template = XVisualInfo.create();
vinfo_template.setScreen(screen.getIndex());
vinfo_template.setC_class(c_class);
- long display = screen.getDevice().getHandle();
+ final long display = screen.getDevice().getHandle();
- XVisualInfo[] vinfos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, vinfo_template, num, 0);
+ final XVisualInfo[] vinfos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, vinfo_template, num, 0);
XVisualInfo best=null;
- int rdepth = capabilities.getRedBits() + capabilities.getGreenBits() + capabilities.getBlueBits() + capabilities.getAlphaBits();
+ final int rdepth = capabilities.getRedBits() + capabilities.getGreenBits() + capabilities.getBlueBits() + capabilities.getAlphaBits();
for (int i = 0; vinfos!=null && i < num[0]; i++) {
- if ( best == null ||
+ if ( best == null ||
best.getDepth() < vinfos[i].getDepth() )
{
best = vinfos[i];
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index 93b7f3487..2414248b4 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -34,6 +34,7 @@
package jogamp.nativewindow.x11;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -42,22 +43,27 @@ import javax.media.nativewindow.NativeWindowFactory;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NWJNILibLoader;
+import jogamp.nativewindow.ToolkitProperties;
import com.jogamp.common.util.LongObjectHashMap;
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
/**
* Contains a thread safe X11 utility to retrieve display connections.
*/
-public class X11Util {
- /**
+public class X11Util implements ToolkitProperties {
+ public static final boolean DEBUG = Debug.debug("X11Util");
+
+ /**
* See Bug 515 - https://jogamp.org/bugzilla/show_bug.cgi?id=515
- * <p>
+ * <p>
* It is observed that ATI X11 drivers, eg.
- * <ul>
+ * <ul>
* <li>fglrx 8.78.6,</li>
* <li>fglrx 11.08/8.881 and </li>
* <li>fglrx 11.11/8.911</li>
- * </ul>
+ * </ul>
* are quite sensitive to multiple Display connections.
* </p>
* <p>
@@ -70,33 +76,39 @@ public class X11Util {
* See also native test: jogl/test-native/displayMultiple02.c
* </p>
* <p>
- * Workaround is to not close them at all if driver vendor is ATI.
+ * Workaround is to not close them at all if driver vendor is ATI
+ * during operation.
+ * </p>
+ * <p>
+ * With ATI X11 drivers all connections must be closed at JVM shutdown,
+ * otherwise a SIGSEGV (after JVM safepoint) will be caused.
* </p>
*/
public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true);
- /** Value is <code>true</code>, best 'stable' results if always using XInitThreads(). */
- public static final boolean XINITTHREADS_ALWAYS_ENABLED = true;
-
- /** Value is <code>true</code>, best 'stable' results if not using XLockDisplay/XUnlockDisplay at all. */
- public static final boolean HAS_XLOCKDISPLAY_BUG = true;
-
- public static final boolean DEBUG = Debug.debug("X11Util");
+ /** See {@link #ATI_HAS_XCLOSEDISPLAY_BUG}. */
+ public static final boolean HAS_XCLOSEDISPLAY_BUG = Debug.isPropertyDefined("nativewindow.debug.X11Util.HAS_XCLOSEDISPLAY_BUG", true);
+
+ /**
+ * See Bug 623 - https://jogamp.org/bugzilla/show_bug.cgi?id=623
+ */
+ public static final boolean ATI_HAS_MULTITHREADING_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_MULTITHREADING_BUG", true);
+
public static final boolean XSYNC_ENABLED = Debug.isPropertyDefined("nativewindow.debug.X11Util.XSync", true);
public static final boolean XERROR_STACKDUMP = DEBUG || Debug.isPropertyDefined("nativewindow.debug.X11Util.XErrorStackDump", true);
private static final boolean TRACE_DISPLAY_LIFECYCLE = Debug.isPropertyDefined("nativewindow.debug.X11Util.TraceDisplayLifecycle", true);
private static String nullDisplayName = null;
- private static boolean isX11LockAvailable = false;
- private static boolean requiresX11Lock = true;
private static volatile boolean isInit = false;
- private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues
+ private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues, or GLRendererQuirks.DontCloseX11Display
+ private static boolean hasThreadingIssues = false; // ATI/AMD X11 driver issues
- private static int setX11ErrorHandlerRecCount = 0;
- private static Object setX11ErrorHandlerLock = new Object();
+ private static final Object setX11ErrorHandlerLock = new Object();
+ private static final String X11_EXTENSION_ATIFGLRXDRI = "ATIFGLRXDRI";
+ private static final String X11_EXTENSION_ATIFGLEXTENSION = "ATIFGLEXTENSION";
-
/**
* Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
*/
public static void initSingleton() {
if(!isInit) {
@@ -104,59 +116,84 @@ public class X11Util {
if(!isInit) {
isInit = true;
if(DEBUG) {
- System.out.println("X11UtilUtil.initSingleton()");
+ System.out.println("X11Util.initSingleton()");
}
if(!NWJNILibLoader.loadNativeWindow("x11")) {
throw new NativeWindowException("NativeWindow X11 native library load error.");
}
-
- final boolean callXInitThreads = XINITTHREADS_ALWAYS_ENABLED ;
- final boolean isXInitThreadsOK = initialize0( callXInitThreads, XERROR_STACKDUMP);
- isX11LockAvailable = isXInitThreadsOK && !HAS_XLOCKDISPLAY_BUG ;
-
- final long dpy = X11Lib.XOpenDisplay(null);
+
+ final boolean isInitOK = initialize0( XERROR_STACKDUMP );
+
+ final boolean hasX11_EXTENSION_ATIFGLRXDRI, hasX11_EXTENSION_ATIFGLEXTENSION;
+ final long dpy = X11Lib.XOpenDisplay(PropertyAccess.getProperty("nativewindow.x11.display.default", true));
if(0 != dpy) {
if(XSYNC_ENABLED) {
X11Lib.XSynchronize(dpy, true);
- }
+ }
try {
nullDisplayName = X11Lib.XDisplayString(dpy);
+ hasX11_EXTENSION_ATIFGLRXDRI = X11Lib.QueryExtension(dpy, X11_EXTENSION_ATIFGLRXDRI);
+ hasX11_EXTENSION_ATIFGLEXTENSION = X11Lib.QueryExtension(dpy, X11_EXTENSION_ATIFGLEXTENSION);
} finally {
X11Lib.XCloseDisplay(dpy);
}
} else {
nullDisplayName = "nil";
+ hasX11_EXTENSION_ATIFGLRXDRI = false;
+ hasX11_EXTENSION_ATIFGLEXTENSION = false;
+ }
+ final boolean isATIFGLRX = hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION ;
+ hasThreadingIssues = ATI_HAS_MULTITHREADING_BUG && isATIFGLRX;
+ if ( !markAllDisplaysUnclosable ) {
+ markAllDisplaysUnclosable = ( ATI_HAS_XCLOSEDISPLAY_BUG && isATIFGLRX ) || HAS_XCLOSEDISPLAY_BUG;
}
-
+
if(DEBUG) {
- System.err.println("X11Util requiresX11Lock "+requiresX11Lock+
- ", XInitThreads [called "+callXInitThreads+", OK "+isXInitThreadsOK+"]"+
- ", isX11LockAvailable "+isX11LockAvailable+
- ", X11 Display(NULL) <"+nullDisplayName+">"+
- ", XSynchronize Enabled: "+XSYNC_ENABLED);
+ System.err.println("X11Util.initSingleton(): OK "+isInitOK+"]"+
+ ",\n\t X11 Display(NULL) <"+nullDisplayName+">"+
+ ",\n\t XSynchronize Enabled: " + XSYNC_ENABLED+
+ ",\n\t X11_EXTENSION_ATIFGLRXDRI " + hasX11_EXTENSION_ATIFGLRXDRI+
+ ",\n\t X11_EXTENSION_ATIFGLEXTENSION " + hasX11_EXTENSION_ATIFGLEXTENSION+
+ ",\n\t requiresToolkitLock "+requiresToolkitLock()+
+ ",\n\t hasThreadingIssues "+hasThreadingIssues()+
+ ",\n\t markAllDisplaysUnclosable "+getMarkAllDisplaysUnclosable()
+ );
// Thread.dumpStack();
}
}
}
}
}
-
- /**
+
+ // not exactly thread safe, but good enough for our purpose,
+ // which is to tag a NamedDisplay uncloseable after creation.
+ private static Object globalLock = new Object();
+ private static LongObjectHashMap openDisplayMap = new LongObjectHashMap(); // handle -> name
+ private static List<NamedDisplay> openDisplayList = new ArrayList<NamedDisplay>(); // open, no close attempt
+ private static List<NamedDisplay> reusableDisplayList = new ArrayList<NamedDisplay>(); // close attempt, marked uncloseable, for reuse
+ private static List<NamedDisplay> pendingDisplayList = new ArrayList<NamedDisplay>(); // all open (close attempt or reusable) in creation order
+ private static final HashMap<String /* displayName */, Boolean> displayXineramaEnabledMap = new HashMap<String, Boolean>();
+
+ /**
* Cleanup resources.
* <p>
* Called by {@link NativeWindowFactory#shutdown()}
* </p>
+ * @see ToolkitProperties
*/
public static void shutdown() {
if(isInit) {
synchronized(X11Util.class) {
- if(isInit) {
+ if(isInit) {
final boolean isJVMShuttingDown = NativeWindowFactory.isJVMShuttingDown() ;
- if(DEBUG || openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0) {
+ if( DEBUG ||
+ ( ( openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0 ) &&
+ ( reusableDisplayList.size() != pendingDisplayList.size() || !markAllDisplaysUnclosable )
+ ) ) {
System.err.println("X11Util.Display: Shutdown (JVM shutdown: "+isJVMShuttingDown+
", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+
", reusable (open, marked uncloseable): "+reusableDisplayList.size()+
- ", pending (post closing): "+pendingDisplayList.size()+
+ ", pending (open in creation order): "+pendingDisplayList.size()+
")");
if(DEBUG) {
Thread.dumpStack();
@@ -164,21 +201,24 @@ public class X11Util {
if( openDisplayList.size() > 0) {
X11Util.dumpOpenDisplayConnections();
}
- if( reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0 ) {
- X11Util.dumpPendingDisplayConnections();
+ if(DEBUG) {
+ if( reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0 ) {
+ X11Util.dumpPendingDisplayConnections();
+ }
}
}
-
- synchronized(globalLock) {
- // Only at JVM shutdown time, since AWT impl. seems to
- // dislike closing of X11 Display's (w/ ATI driver).
- if( isJVMShuttingDown ) {
- isInit = false;
- closePendingDisplayConnections();
+
+ // Only at JVM shutdown time, since AWT impl. seems to
+ // dislike closing of X11 Display's (w/ ATI driver).
+ if( isJVMShuttingDown ) {
+ synchronized(globalLock) {
+ isInit = false;
+ closePendingDisplayConnections();
openDisplayList.clear();
reusableDisplayList.clear();
pendingDisplayList.clear();
openDisplayMap.clear();
+ displayXineramaEnabledMap.clear();
shutdown0();
}
}
@@ -187,53 +227,52 @@ public class X11Util {
}
}
- public static synchronized boolean isNativeLockAvailable() {
- return isX11LockAvailable;
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static final boolean requiresToolkitLock() {
+ return true; // JAWT locking: yes, instead of native X11 locking w use a recursive lock per display connection.
}
- public static synchronized boolean requiresToolkitLock() {
- return requiresX11Lock;
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static final boolean hasThreadingIssues() {
+ return hasThreadingIssues; // JOGL impl. may utilize special locking "somewhere"
}
- public static void setX11ErrorHandler(boolean onoff, boolean quiet) {
+ public static void setX11ErrorHandler(final boolean onoff, final boolean quiet) {
synchronized(setX11ErrorHandlerLock) {
- if(onoff) {
- if(0==setX11ErrorHandlerRecCount) {
- setX11ErrorHandler0(true, quiet);
- }
- setX11ErrorHandlerRecCount++;
- } else {
- if(0 >= setX11ErrorHandlerRecCount) {
- throw new InternalError();
- }
- setX11ErrorHandlerRecCount--;
- if(0==setX11ErrorHandlerRecCount) {
- setX11ErrorHandler0(false, false);
- }
- }
+ setX11ErrorHandler0(onoff, quiet);
}
}
public static String getNullDisplayName() {
return nullDisplayName;
}
-
+
+ public static void markAllDisplaysUnclosable() {
+ synchronized(globalLock) {
+ markAllDisplaysUnclosable = true;
+ for(int i=0; i<openDisplayList.size(); i++) {
+ openDisplayList.get(i).setUncloseable(true);
+ }
+ for(int i=0; i<reusableDisplayList.size(); i++) {
+ reusableDisplayList.get(i).setUncloseable(true);
+ }
+ for(int i=0; i<pendingDisplayList.size(); i++) {
+ pendingDisplayList.get(i).setUncloseable(true);
+ }
+ }
+ }
+
public static boolean getMarkAllDisplaysUnclosable() {
return markAllDisplaysUnclosable;
}
- public static void setMarkAllDisplaysUnclosable(boolean v) {
- markAllDisplaysUnclosable = v;
- }
-
- private X11Util() {}
- // not exactly thread safe, but good enough for our purpose,
- // which is to tag a NamedDisplay uncloseable after creation.
- private static Object globalLock = new Object();
- private static LongObjectHashMap openDisplayMap = new LongObjectHashMap(); // handle -> name
- private static List<NamedDisplay> openDisplayList = new ArrayList<NamedDisplay>();
- private static List<NamedDisplay> reusableDisplayList = new ArrayList<NamedDisplay>();
- private static List<NamedDisplay> pendingDisplayList = new ArrayList<NamedDisplay>();
+ private X11Util() {}
public static class NamedDisplay {
final String name;
@@ -243,7 +282,7 @@ public class X11Util {
boolean unCloseable;
Throwable creationStack;
- protected NamedDisplay(String name, long handle) {
+ protected NamedDisplay(final String name, final long handle) {
this.name=name;
this.handle=handle;
this.refCount=0;
@@ -261,58 +300,58 @@ public class X11Util {
}
}
+ @Override
public final int hashCode() {
return hash32;
}
-
- public final boolean equals(Object obj) {
+
+ @Override
+ public final boolean equals(final Object obj) {
if(this == obj) { return true; }
if(obj instanceof NamedDisplay) {
return handle == ((NamedDisplay) obj).handle;
}
return false;
}
-
+
public final void addRef() { refCount++; }
public final void removeRef() { refCount--; }
-
+
public final String getName() { return name; }
public final long getHandle() { return handle; }
public final int getRefCount() { return refCount; }
- public final void setUncloseable(boolean v) { unCloseable = v; }
+ public final void setUncloseable(final boolean v) { unCloseable = v; }
public final boolean isUncloseable() { return unCloseable; }
public final Throwable getCreationStack() { return creationStack; }
@Override
- public Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
-
- @Override
public String toString() {
return "NamedX11Display["+name+", 0x"+Long.toHexString(handle)+", refCount "+refCount+", unCloseable "+unCloseable+"]";
}
}
/**
- * Closing pending Display connections in reverse order.
+ * Closing pending Display connections in original creation order, if {@link #getMarkAllDisplaysUnclosable()} is true.
*
* @return number of closed Display connections
*/
- public static int closePendingDisplayConnections() {
+ private static int closePendingDisplayConnections() {
int num=0;
synchronized(globalLock) {
- if(DEBUG) {
- System.err.println("X11Util: Closing Pending X11 Display Connections in order of their creation: "+pendingDisplayList.size());
- }
- for(int i=0; i<pendingDisplayList.size(); i++) {
- NamedDisplay ndpy = (NamedDisplay) pendingDisplayList.get(i);
+ if( getMarkAllDisplaysUnclosable() ) {
+ for(int i=0; i<pendingDisplayList.size(); i++) {
+ final NamedDisplay ndpy = pendingDisplayList.get(i);
+ if(DEBUG) {
+ final boolean closeAttempted = !openDisplayMap.containsKey(ndpy.getHandle());
+ System.err.println("X11Util.closePendingDisplayConnections(): Closing ["+i+"]: "+ndpy+" - closeAttempted "+closeAttempted);
+ }
+ XCloseDisplay(ndpy.getHandle());
+ num++;
+ }
if(DEBUG) {
- System.err.println("X11Util.closePendingDisplayConnections(): Closing ["+i+"]: "+ndpy);
+ System.err.println("X11Util.closePendingDisplayConnections(): Closed "+num+" pending display connections");
}
- XCloseDisplay(ndpy.getHandle());
- num++;
}
}
return num;
@@ -323,15 +362,15 @@ public class X11Util {
return openDisplayList.size();
}
}
-
+
public static void dumpOpenDisplayConnections() {
synchronized(globalLock) {
System.err.println("X11Util: Open X11 Display Connections: "+openDisplayList.size());
for(int i=0; i<openDisplayList.size(); i++) {
- NamedDisplay ndpy = openDisplayList.get(i);
+ final NamedDisplay ndpy = openDisplayList.get(i);
System.err.println("X11Util: Open["+i+"]: "+ndpy);
if(null!=ndpy) {
- Throwable t = ndpy.getCreationStack();
+ final Throwable t = ndpy.getCreationStack();
if(null!=t) {
t.printStackTrace();
}
@@ -339,7 +378,7 @@ public class X11Util {
}
}
}
-
+
public static int getReusableDisplayConnectionNumber() {
synchronized(globalLock) {
return reusableDisplayList.size();
@@ -356,10 +395,10 @@ public class X11Util {
synchronized(globalLock) {
System.err.println("X11Util: Reusable X11 Display Connections: "+reusableDisplayList.size());
for(int i=0; i<reusableDisplayList.size(); i++) {
- NamedDisplay ndpy = (NamedDisplay) reusableDisplayList.get(i);
+ final NamedDisplay ndpy = reusableDisplayList.get(i);
System.err.println("X11Util: Reusable["+i+"]: "+ndpy);
if(null!=ndpy) {
- Throwable t = ndpy.getCreationStack();
+ final Throwable t = ndpy.getCreationStack();
if(null!=t) {
t.printStackTrace();
}
@@ -367,10 +406,10 @@ public class X11Util {
}
System.err.println("X11Util: Pending X11 Display Connections (creation order): "+pendingDisplayList.size());
for(int i=0; i<pendingDisplayList.size(); i++) {
- NamedDisplay ndpy = (NamedDisplay) pendingDisplayList.get(i);
+ final NamedDisplay ndpy = pendingDisplayList.get(i);
System.err.println("X11Util: Pending["+i+"]: "+ndpy);
if(null!=ndpy) {
- Throwable t = ndpy.getCreationStack();
+ final Throwable t = ndpy.getCreationStack();
if(null!=t) {
t.printStackTrace();
}
@@ -379,7 +418,7 @@ public class X11Util {
}
}
- public static boolean markDisplayUncloseable(long handle) {
+ public static boolean markDisplayUncloseable(final long handle) {
NamedDisplay ndpy;
synchronized(globalLock) {
ndpy = (NamedDisplay) openDisplayMap.get(handle);
@@ -397,8 +436,8 @@ public class X11Util {
NamedDisplay namedDpy = null;
name = validateDisplayName(name);
boolean reused = false;
-
- synchronized(globalLock) {
+
+ synchronized(globalLock) {
for(int i=0; i<reusableDisplayList.size(); i++) {
if(reusableDisplayList.get(i).getName().equals(name)) {
namedDpy = reusableDisplayList.remove(i);
@@ -431,11 +470,9 @@ public class X11Util {
return namedDpy.getHandle();
}
- public static void closeDisplay(long handle) {
- NamedDisplay namedDpy;
-
+ public static void closeDisplay(final long handle) {
synchronized(globalLock) {
- namedDpy = (NamedDisplay) openDisplayMap.remove(handle);
+ final NamedDisplay namedDpy = (NamedDisplay) openDisplayMap.remove(handle);
if(null==namedDpy) {
X11Util.dumpPendingDisplayConnections();
throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped. Thread "+Thread.currentThread().getName());
@@ -444,38 +481,43 @@ public class X11Util {
X11Util.dumpPendingDisplayConnections();
throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") Mapping error: "+namedDpy+". Thread "+Thread.currentThread().getName());
}
-
+
namedDpy.removeRef();
if(!openDisplayList.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); }
-
- if(!namedDpy.isUncloseable()) {
+
+ if( markAllDisplaysUnclosable ) {
+ // if set-mark 'slipped' this one .. just to be safe!
+ namedDpy.setUncloseable(true);
+ }
+ if( !namedDpy.isUncloseable() ) {
XCloseDisplay(namedDpy.getHandle());
pendingDisplayList.remove(namedDpy);
} else {
// for reuse
+ X11Lib.XSync(namedDpy.getHandle(), true); // flush output buffer and discard all events
reusableDisplayList.add(namedDpy);
}
-
+
if(DEBUG) {
System.err.println("X11Util.Display: Closed (real: "+(!namedDpy.isUncloseable())+") "+namedDpy+". Thread "+Thread.currentThread().getName());
- }
+ }
}
}
- public static NamedDisplay getNamedDisplay(long handle) {
+ public static NamedDisplay getNamedDisplay(final long handle) {
synchronized(globalLock) {
return (NamedDisplay) openDisplayMap.get(handle);
}
}
- /**
+ /**
* @return If name is null, it returns the previous queried NULL display name,
* otherwise the name. */
- public static String validateDisplayName(String name) {
+ public static String validateDisplayName(final String name) {
return ( null == name || AbstractGraphicsDevice.DEFAULT_CONNECTION.equals(name) ) ? getNullDisplayName() : name ;
}
- public static String validateDisplayName(String name, long handle) {
+ public static String validateDisplayName(String name, final long handle) {
if( ( null==name || AbstractGraphicsDevice.DEFAULT_CONNECTION.equals(name) ) && 0!=handle) {
name = X11Lib.XDisplayString(handle);
}
@@ -488,54 +530,61 @@ public class X11Util {
**
*******************************/
- public static long XOpenDisplay(String arg0) {
- NativeWindowFactory.getDefaultToolkitLock().lock();
- try {
- long handle = X11Lib.XOpenDisplay(arg0);
- if(XSYNC_ENABLED && 0 != handle) {
- X11Lib.XSynchronize(handle, true);
- }
- if(TRACE_DISPLAY_LIFECYCLE) {
- System.err.println(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle));
- // Thread.dumpStack();
- }
- return handle;
- } finally {
- NativeWindowFactory.getDefaultToolkitLock().unlock();
+ public static long XOpenDisplay(final String arg0) {
+ final long handle = X11Lib.XOpenDisplay(arg0);
+ if(XSYNC_ENABLED && 0 != handle) {
+ X11Lib.XSynchronize(handle, true);
}
+ if(TRACE_DISPLAY_LIFECYCLE) {
+ System.err.println(Thread.currentThread()+" - X11Util.XOpenDisplay("+arg0+") 0x"+Long.toHexString(handle));
+ // Thread.dumpStack();
+ }
+ return handle;
}
- public static int XCloseDisplay(long display) {
- NativeWindowFactory.getDefaultToolkitLock().lock();
+ public static int XCloseDisplay(final long display) {
+ if(TRACE_DISPLAY_LIFECYCLE) {
+ System.err.println(Thread.currentThread()+" - X11Util.XCloseDisplay() 0x"+Long.toHexString(display));
+ // Thread.dumpStack();
+ }
+ int res = -1;
try {
- if(TRACE_DISPLAY_LIFECYCLE) {
- System.err.println(Thread.currentThread()+" - X11Util.XCloseDisplay() 0x"+Long.toHexString(display));
- // Thread.dumpStack();
- }
- int res = -1;
- X11Util.setX11ErrorHandler(true, DEBUG ? false : true);
- try {
- res = X11Lib.XCloseDisplay(display);
- } catch (Exception ex) {
- System.err.println("X11Util: Catched Exception:");
- ex.printStackTrace();
- } finally {
- X11Util.setX11ErrorHandler(false, false);
- }
- return res;
- } finally {
- NativeWindowFactory.getDefaultToolkitLock().unlock();
+ res = X11Lib.XCloseDisplay(display);
+ } catch (final Exception ex) {
+ System.err.println("X11Util: Caught exception:");
+ ex.printStackTrace();
}
+ return res;
}
static volatile boolean XineramaFetched = false;
static long XineramaLibHandle = 0;
static long XineramaQueryFunc = 0;
-
- public static boolean XineramaIsEnabled(long display) {
- if(0==display) {
- throw new IllegalArgumentException("Display NULL");
+
+ public static boolean XineramaIsEnabled(final X11GraphicsDevice device) {
+ if(null == device) {
+ throw new IllegalArgumentException("X11 Display device is NULL");
}
+ device.lock();
+ try {
+ return XineramaIsEnabled(device.getHandle());
+ } finally {
+ device.unlock();
+ }
+ }
+
+ public static boolean XineramaIsEnabled(final long displayHandle) {
+ if( 0 == displayHandle ) {
+ throw new IllegalArgumentException("X11 Display handle is NULL");
+ }
+ final String displayName = X11Lib.XDisplayString(displayHandle);
+ synchronized(displayXineramaEnabledMap) {
+ final Boolean b = displayXineramaEnabledMap.get(displayName);
+ if(null != b) {
+ return b.booleanValue();
+ }
+ }
+ final boolean res;
if(!XineramaFetched) { // volatile: ok
synchronized(X11Util.class) {
if( !XineramaFetched ) {
@@ -548,22 +597,27 @@ public class X11Util {
}
}
if(0!=XineramaQueryFunc) {
- final boolean res = X11Lib.XineramaIsEnabled(XineramaQueryFunc, display);
+ res = X11Lib.XineramaIsEnabled(XineramaQueryFunc, displayHandle);
+ } else {
if(DEBUG) {
- System.err.println("XineramaIsEnabled: "+res);
+ System.err.println("XineramaIsEnabled: Couldn't bind to Xinerama - lib 0x"+Long.toHexString(XineramaLibHandle)+
+ "query 0x"+Long.toHexString(XineramaQueryFunc));
}
- return res;
- } else if(DEBUG) {
- System.err.println("XineramaIsEnabled: Couldn't bind to Xinerama - lib 0x"+Long.toHexString(XineramaLibHandle)+
- "query 0x"+Long.toHexString(XineramaQueryFunc));
+ res = false;
}
- return false;
+ synchronized(displayXineramaEnabledMap) {
+ if(DEBUG) {
+ System.err.println("XineramaIsEnabled Cache: Display "+displayName+" (0x"+Long.toHexString(displayHandle)+") -> "+res);
+ }
+ displayXineramaEnabledMap.put(displayName, Boolean.valueOf(res));
+ }
+ return res;
}
-
+
private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI
private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
-
- private static native boolean initialize0(boolean firstUIActionOnProcess, boolean debug);
+
+ private static native boolean initialize0(boolean debug);
private static native void shutdown0();
private static native void setX11ErrorHandler0(boolean onoff, boolean quiet);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
index 1de03e8be..6b606df97 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -59,16 +59,17 @@ import jogamp.nativewindow.x11.X11Lib;
import jogamp.nativewindow.x11.X11Util;
public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFactory {
-
+
public static void registerFactory() {
GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, CapabilitiesImmutable.class, new X11AWTGraphicsConfigurationFactory());
- }
+ }
private X11AWTGraphicsConfigurationFactory() {
}
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, final int nativeVisualID) {
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects");
@@ -79,19 +80,19 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, (AWTGraphicsScreen)absScreen, nativeVisualID);
}
-
+
public static AWTGraphicsConfiguration chooseGraphicsConfigurationStatic(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser, AWTGraphicsScreen awtScreen, int nativeVisualID) {
+ CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser, final AWTGraphicsScreen awtScreen, final int nativeVisualID) {
if(DEBUG) {
System.err.println("X11AWTGraphicsConfigurationFactory: got "+awtScreen);
}
-
+
final GraphicsDevice device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice();
-
+
final long displayHandleAWT = X11SunJDKReflection.graphicsDeviceGetDisplay(device);
final long displayHandle;
- boolean owner = false;
+ final boolean owner;
if(0==displayHandleAWT) {
displayHandle = X11Util.openDisplay(null);
owner = true;
@@ -101,8 +102,8 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
} else {
/**
* Using the AWT display handle works fine with NVidia.
- * However we experienced different results w/ AMD drivers,
- * some work, but some behave erratic.
+ * However we experienced different results w/ AMD drivers,
+ * some work, but some behave erratic.
* I.e. hangs in XQueryExtension(..) via X11GraphicsScreen.
*/
final String displayName = X11Lib.XDisplayString(displayHandleAWT);
@@ -112,15 +113,14 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
System.err.println(getThreadName()+" - X11AWTGraphicsConfigurationFactory: AWT dpy "+displayName+" / "+toHexString(displayHandleAWT)+", create X11 display "+toHexString(displayHandle));
}
}
- final ToolkitLock lock = owner ?
- NativeWindowFactory.getDefaultToolkitLock(NativeWindowFactory.TYPE_AWT) : // own non-shared X11 display connection, no X11 lock
- NativeWindowFactory.createDefaultToolkitLock(NativeWindowFactory.TYPE_X11, NativeWindowFactory.TYPE_AWT, displayHandle);
- final X11GraphicsDevice x11Device = new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, lock, owner);
+ // Global JAWT lock required - No X11 resource locking due to private display connection
+ final ToolkitLock lock = NativeWindowFactory.getDefaultToolkitLock(NativeWindowFactory.TYPE_AWT);
+ final X11GraphicsDevice x11Device = new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, lock, owner);
final X11GraphicsScreen x11Screen = new X11GraphicsScreen(x11Device, awtScreen.getIndex());
if(DEBUG) {
System.err.println("X11AWTGraphicsConfigurationFactory: made "+x11Screen);
}
-
+
final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(x11Device, capsChosen);
AbstractGraphicsConfiguration aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen, nativeVisualID);
if (aConfig == null) {
@@ -130,7 +130,7 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
System.err.println("X11AWTGraphicsConfigurationFactory: chosen config: "+aConfig);
// Thread.dumpStack();
}
-
+
//
// Match the X11/GL Visual with AWT:
// - choose a config AWT agnostic and then
@@ -138,12 +138,12 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
//
// The resulting GraphicsConfiguration has to be 'forced' on the AWT native peer,
// ie. returned by GLCanvas's getGraphicsConfiguration() befor call by super.addNotify().
- //
+ //
final GraphicsConfiguration[] configs = device.getConfigurations();
int visualID = aConfig.getVisualID(VIDType.NATIVE);
if(VisualIDHolder.VID_UNDEFINED != visualID) {
for (int i = 0; i < configs.length; i++) {
- GraphicsConfiguration gc = configs[i];
+ final GraphicsConfiguration gc = configs[i];
if (gc != null) {
if (X11SunJDKReflection.graphicsConfigurationGetVisualID(gc) == visualID) {
if(DEBUG) {