From fd06292d4a208cbd613f4bdce7cae12e075e70ec Mon Sep 17 00:00:00 2001
From: Sven Gothel
- * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}.
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given
+ *
* Lifecycle (destruction) of the given surface handle shall be handled by the caller.
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 694a081b8..03fd78ac7 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -60,6 +60,7 @@ import java.util.ArrayList;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.OffscreenLayerOption;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
@@ -1062,9 +1063,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) {
config = (AWTGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen,
+ GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, aScreen);
+ chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
} else {
try {
final ArrayList
+ * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only.
+ *
+ * Pseudo code for finding a suitable factory is:
+ *
+ * This does not need to be called by end users, only implementors of new
* GraphicsConfigurationFactory subclasses.
- *
+ *
+ * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only.
+ * See {@link #getFactory(Class, Class)} for a description of the find algorithm.
- * The default implementation is a
* Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 583fde07f..b16b0c75c 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -153,6 +153,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
@Override
public boolean close() {
+ toolkitLock.dispose();
if(0 != handle) {
handle = 0;
return true;
@@ -162,7 +163,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
@Override
public String toString() {
- return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+"]";
+ return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", "+toolkitLock+"]";
}
/**
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index 40aaa8a25..4f4bb629b 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -33,7 +33,6 @@
package javax.media.nativewindow;
-import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -43,6 +42,7 @@ import java.util.Map;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NativeWindowFactoryImpl;
+import jogamp.nativewindow.ResourceToolkitLock;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
@@ -93,13 +93,6 @@ public abstract class NativeWindowFactory {
private static ToolkitLock jawtUtilJAWTToolkitLock;
- public static final String X11JAWTToolkitLockClassName = "jogamp.nativewindow.jawt.x11.X11JAWTToolkitLock" ;
- public static final String X11ToolkitLockClassName = "jogamp.nativewindow.x11.X11ToolkitLock" ;
-
- private static Class> x11JAWTToolkitLockClass;
- private static Constructor> x11JAWTToolkitLockConstructor;
- private static Class> x11ToolkitLockClass;
- private static Constructor> x11ToolkitLockConstructor;
private static boolean requiresToolkitLock;
private static volatile boolean isJVMShuttingDown = false;
@@ -266,16 +259,6 @@ public abstract class NativeWindowFactory {
// register either our default factory or (if exist) the X11/AWT one -> AWT Component
registerFactory(ReflectionUtil.getClass(ReflectionUtil.AWTNames.ComponentClass, false, cl), factory);
}
-
- if( TYPE_X11 == nativeWindowingTypePure ) {
- // passing through RuntimeException if not exists intended
- x11ToolkitLockClass = ReflectionUtil.getClass(X11ToolkitLockClassName, false, cl);
- x11ToolkitLockConstructor = ReflectionUtil.getConstructor(x11ToolkitLockClass, new Class[] { long.class } );
- if( isAWTAvailable() ) {
- x11JAWTToolkitLockClass = ReflectionUtil.getClass(X11JAWTToolkitLockClassName, false, cl);
- x11JAWTToolkitLockConstructor = ReflectionUtil.getConstructor(x11JAWTToolkitLockClass, new Class[] { long.class } );
- }
- }
if(DEBUG) {
System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock);
@@ -300,6 +283,7 @@ public abstract class NativeWindowFactory {
GraphicsConfigurationFactory.shutdown();
}
shutdownNativeImpl(NativeWindowFactory.class.getClassLoader()); // always re-shutdown
+ // SharedResourceToolkitLock.shutdown(DEBUG); // not used yet
if(DEBUG) {
System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END JVM Shutdown "+isJVMShuttingDown);
}
@@ -358,16 +342,9 @@ public abstract class NativeWindowFactory {
/**
* Provides the default {@link ToolkitLock} for
+ * Toolkit locks are created solely via {@link NativeWindowFactory}.
+ *
+ * One use case is the AWT locking on X11, see {@link NativeWindowFactory#createDefaultToolkitLock(String, long)}.
+ *
+ * Shall be called when instance is no more required.
+ *
+ * A resource handle maybe used within a unique object
+ * and can be synchronized across threads via an instance of ResourceToolkitLock.
+ *
+ * A resource handle maybe used within many objects
+ * and can be synchronized across threads via an unique instance of SharedResourceToolkitLock.
+ *
+ * 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.
+ *
@@ -183,11 +192,12 @@ public abstract class Display {
*
* @param type
* @param name
- * @param fromIndex start index, then increasing until found or end of list *
+ * @param fromIndex start index, then increasing until found or end of list
+ * @paran shared if true, only shared instances are found, otherwise also exclusive
* @return
*/
- public static Display getFirstDisplayOf(String type, String name, int fromIndex) {
- return getDisplayOfImpl(type, name, fromIndex, 1);
+ public static Display getFirstDisplayOf(String type, String name, int fromIndex, boolean shared) {
+ return getDisplayOfImpl(type, name, fromIndex, 1, shared);
}
/**
@@ -195,19 +205,22 @@ public abstract class Display {
* @param type
* @param name
* @param fromIndex start index, then decreasing until found or end of list. -1 is interpreted as size - 1.
+ * @paran shared if true, only shared instances are found, otherwise also exclusive
* @return
*/
- public static Display getLastDisplayOf(String type, String name, int fromIndex) {
- return getDisplayOfImpl(type, name, fromIndex, -1);
+ public static Display getLastDisplayOf(String type, String name, int fromIndex, boolean shared) {
+ return getDisplayOfImpl(type, name, fromIndex, -1, shared);
}
- private static Display getDisplayOfImpl(String type, String name, int fromIndex, int incr) {
+ private static Display getDisplayOfImpl(String type, String name, int fromIndex, int incr, boolean shared) {
synchronized(displayList) {
int i = fromIndex >= 0 ? fromIndex : displayList.size() - 1 ;
while( ( incr > 0 ) ? i < displayList.size() : i >= 0 ) {
Display display = (Display) displayList.get(i);
if( display.getType().equals(type) &&
- display.getName().equals(name) ) {
+ display.getName().equals(name) &&
+ ( !shared || shared && !display.isExclusive() )
+ ) {
return display;
}
i+=incr;
diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java
index abae94ab6..1bf47f4aa 100644
--- a/src/newt/classes/com/jogamp/newt/NewtFactory.java
+++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java
@@ -305,7 +305,7 @@ public class NewtFactory {
* Instantiate a Display entity using the native handle.
*/
public static Display createDisplay(String type, long handle, boolean reuse) {
- return DisplayImpl.create(type, null, handle, false);
+ return DisplayImpl.create(type, null, handle, reuse);
}
public static boolean isScreenCompatible(NativeWindow parent, Screen childScreen) {
diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java
index 26f19ad6b..cfbcc988a 100644
--- a/src/newt/classes/com/jogamp/newt/Screen.java
+++ b/src/newt/classes/com/jogamp/newt/Screen.java
@@ -145,7 +145,7 @@ public abstract class Screen {
public abstract Display getDisplay();
/**
- * @return the screen fully qualified Screen name,
+ * @return The screen fully qualified Screen name,
* which is a key of {@link com.jogamp.newt.Display#getFQName()} + {@link #getIndex()}.
*/
public abstract String getFQName();
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index bca7f6e5b..daeb3e886 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -42,6 +42,7 @@ import com.jogamp.newt.event.NEWTEventConsumer;
import jogamp.newt.event.NEWTEventTask;
import com.jogamp.newt.util.EDTUtil;
import java.util.ArrayList;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
@@ -66,7 +67,7 @@ public abstract class DisplayImpl extends Display {
name = display.validateDisplayName(name, handle);
synchronized(displayList) {
if(reuse) {
- Display display0 = Display.getLastDisplayOf(type, name, -1);
+ Display display0 = Display.getLastDisplayOf(type, name, -1, true /* shared only */);
if(null != display0) {
if(DEBUG) {
System.err.println("Display.create() REUSE: "+display0+" "+getThreadName());
@@ -74,9 +75,9 @@ public abstract class DisplayImpl extends Display {
return display0;
}
}
+ display.exclusive = !reuse;
display.name = name;
display.type=type;
- display.destroyWhenUnused=false;
display.refCount=0;
display.id = serialno++;
display.fqname = getFQName(display.type, display.name, display.id);
@@ -94,7 +95,7 @@ public abstract class DisplayImpl extends Display {
throw new RuntimeException(e);
}
}
-
+
@Override
public boolean equals(Object obj) {
if (obj == null) {
@@ -116,10 +117,12 @@ public abstract class DisplayImpl extends Display {
return true;
}
+ @Override
public int hashCode() {
return hashCode;
}
+ @Override
public synchronized final void createNative()
throws NativeWindowException
{
@@ -148,10 +151,6 @@ public abstract class DisplayImpl extends Display {
}
}
- protected boolean shallRunOnEDT() {
- return true;
- }
-
protected EDTUtil createEDTUtil() {
final EDTUtil def;
if(NewtFactory.useEDT()) {
@@ -179,12 +178,7 @@ public abstract class DisplayImpl extends Display {
if(DEBUG) {
System.err.println("Display.setEDTUtil: "+oldEDTUtil+" -> "+newEDTUtil);
}
- if(null != oldEDTUtil) {
- stopEDT( new Runnable() { public void run() {} } );
- // ready for restart ..
- oldEDTUtil.waitUntilStopped();
- oldEDTUtil.reset();
- }
+ removeEDT( new Runnable() { public void run() {} } );
edtUtil = newEDTUtil;
return oldEDTUtil;
}
@@ -194,16 +188,19 @@ public abstract class DisplayImpl extends Display {
return edtUtil;
}
- private void stopEDT(final Runnable task) {
- if( shallRunOnEDT() && null!=edtUtil ) {
+ private void removeEDT(final Runnable task) {
+ if(null!=edtUtil) {
edtUtil.invokeStop(task);
+ // ready for restart ..
+ edtUtil.waitUntilStopped();
+ edtUtil.reset();
} else {
task.run();
}
}
public void runOnEDTIfAvail(boolean wait, final Runnable task) {
- if( shallRunOnEDT() && null!=edtUtil && !edtUtil.isCurrentThreadEDT()) {
+ if( null!=edtUtil && !edtUtil.isCurrentThreadEDT()) {
edtUtil.invoke(wait, task);
} else {
task.run();
@@ -212,18 +209,17 @@ public abstract class DisplayImpl extends Display {
public boolean validateEDT() {
if(0==refCount && null==aDevice && null != edtUtil && edtUtil.isRunning()) {
- stopEDT( new Runnable() {
+ removeEDT( new Runnable() {
public void run() {
// nop
}
} );
- edtUtil.waitUntilStopped();
- edtUtil.reset();
return true;
}
return false;
}
+ @Override
public synchronized final void destroy() {
if(DEBUG) {
dumpDisplayList("Display.destroy("+getFQName()+") BEGIN");
@@ -239,17 +235,13 @@ public abstract class DisplayImpl extends Display {
}
final AbstractGraphicsDevice f_aDevice = aDevice;
final DisplayImpl f_dpy = this;
- stopEDT( new Runnable() {
+ removeEDT( new Runnable() {
public void run() {
if ( null != f_aDevice ) {
f_dpy.closeNativeImpl();
}
}
} );
- if(null!=edtUtil) {
- edtUtil.waitUntilStopped();
- edtUtil.reset();
- }
aDevice = null;
refCount=0;
if(DEBUG) {
@@ -290,21 +282,30 @@ public abstract class DisplayImpl extends Display {
protected abstract void createNativeImpl();
protected abstract void closeNativeImpl();
+ @Override
public final int getId() {
return id;
}
+ @Override
public final String getType() {
return type;
}
+ @Override
public final String getName() {
return name;
}
+ @Override
public final String getFQName() {
return fqname;
}
+
+ @Override
+ public final boolean isExclusive() {
+ return exclusive;
+ }
public static final String nilString = "nil" ;
@@ -324,9 +325,10 @@ public abstract class DisplayImpl extends Display {
sb.append(name);
sb.append("-");
sb.append(id);
- return sb.toString().intern();
+ return sb.toString();
}
+ @Override
public final long getHandle() {
if(null!=aDevice) {
return aDevice.getHandle();
@@ -334,14 +336,17 @@ public abstract class DisplayImpl extends Display {
return 0;
}
+ @Override
public final AbstractGraphicsDevice getGraphicsDevice() {
return aDevice;
}
+ @Override
public synchronized final boolean isNativeValid() {
return null != aDevice;
}
+ @Override
public boolean isEDTRunning() {
if(null!=edtUtil) {
return edtUtil.isRunning();
@@ -351,7 +356,7 @@ public abstract class DisplayImpl extends Display {
@Override
public String toString() {
- return "NEWT-Display["+getFQName()+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", edtRunning "+isEDTRunning()+", "+aDevice+"]";
+ return "NEWT-Display["+getFQName()+", excl "+exclusive+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", edtRunning "+isEDTRunning()+", "+aDevice+"]";
}
protected abstract void dispatchMessagesNative();
@@ -403,6 +408,7 @@ public abstract class DisplayImpl extends Display {
eventTask.notifyCaller();
}
+ @Override
public void dispatchMessages() {
// System.err.println("Display.dispatchMessages() 0 "+this+" "+getThreadName());
if(0==refCount || // no screens
@@ -475,20 +481,23 @@ public abstract class DisplayImpl extends Display {
public interface DisplayRunnable
- * In case {@link X11Util#HAS_XLOCKDISPLAY_BUG} and {@link X11Util#XINITTHREADS_ALWAYS_ENABLED},
- * we use null locking. Even though this seems not to be rational, it gives most stable results on all platforms.
- *
- * Otherwise we use basic locking via the constructor {@link X11GraphicsDevice#X11GraphicsDevice(long, int, boolean)},
- * since it is possible to share this device via {@link com.jogamp.newt.NewtFactory#createDisplay(String, boolean)}.
- * XVisualInfo * XGetVisualInfo(Display * , long, XVisualInfo * , int * );
*/
private static native java.nio.ByteBuffer XGetVisualInfo1(long arg0, long arg1, java.nio.ByteBuffer arg2, Object arg3, int arg3_byte_offset);
- public static native long DefaultVisualID(long display, int screen);
+ public static native int GetVisualIDFromWindow(long display, long window);
+
+ public static native int DefaultVisualID(long display, int screen);
public static native long CreateDummyWindow(long display, int screen_index, int visualID, int width, int height);
public static native void DestroyDummyWindow(long display, long window);
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index 612a02f14..9a0d2cb99 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -434,7 +434,8 @@ public abstract class GLDrawableFactory {
/**
* Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance.
* windowHandle
's native visualID if set or the given {@link GLCapabilitiesImmutable}.
*
+ For-All devT := getTopDownDeviceTypes(deviceType)
+ For-All capsT := getTopDownCapabilitiesTypes(capabilitiesType)
+ f = factory.get(devT, capsT);
+ if(f) { return f; }
+ end
+ end
+ *
+ * null
.
* NOP
, just setting the handle to null
.
+ * The default implementation {@link ToolkitLock#dispose() dispose} it's {@link ToolkitLock} and sets the handle to null
.
* type
, a singleton instance.
- *
*
- *
*/
public static ToolkitLock getDefaultToolkitLock(String type) {
@@ -390,84 +367,36 @@ public abstract class NativeWindowFactory {
/**
* Creates the default {@link ToolkitLock} for
- *
- *
- *
- * type
and deviceHandle
.
- *
*
- *
*/
public static ToolkitLock createDefaultToolkitLock(String type, long deviceHandle) {
if( requiresToolkitLock() ) {
- if( TYPE_X11 == type ) {
- if( 0== deviceHandle ) {
- throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11");
- }
- return createX11ToolkitLock(deviceHandle);
- }
+ return ResourceToolkitLock.create();
}
return NativeWindowFactoryImpl.getNullToolkitLock();
}
/**
* Creates the default {@link ToolkitLock} for
- *
- *
- *
- * type
and deviceHandle
.
- *
*
- *
*/
public static ToolkitLock createDefaultToolkitLock(String type, String sharedType, long deviceHandle) {
if( requiresToolkitLock() ) {
- if( TYPE_X11 == type ) {
- if( 0== deviceHandle ) {
- throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11");
- }
- if( TYPE_AWT == sharedType && isAWTAvailable() ) {
- return createX11AWTToolkitLock(deviceHandle);
- }
- return createX11ToolkitLock(deviceHandle);
+ if( TYPE_AWT == sharedType && isAWTAvailable() ) {
+ return getAWTToolkitLock();
}
+ return ResourceToolkitLock.create();
}
return NativeWindowFactoryImpl.getNullToolkitLock();
}
-
- protected static ToolkitLock createX11AWTToolkitLock(long deviceHandle) {
- try {
- if(DEBUG) {
- System.err.println("NativeWindowFactory.createX11AWTToolkitLock(0x"+Long.toHexString(deviceHandle)+")");
- // Thread.dumpStack();
- }
- return (ToolkitLock) x11JAWTToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)});
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- protected static ToolkitLock createX11ToolkitLock(long deviceHandle) {
- try {
- return (ToolkitLock) x11ToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)});
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
-
+
/** Returns the appropriate NativeWindowFactory to handle window
objects of the given type. The windowClass might be {@link
NativeWindow NativeWindow}, in which case the client has
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
index 30f9660f0..18b7cf5d9 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java
@@ -33,12 +33,26 @@ import jogamp.nativewindow.Debug;
/**
* Marker for a singleton global recursive blocking lock implementation,
* optionally locking a native windowing toolkit as well.
- *
- *
- *
- *
- *
- *
- *
- * One use case is the AWT locking on X11, see {@link jogamp.nativewindow.jawt.JAWTToolkitLock}.
+ *
+ */
+ public static int shutdown(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(Iterator
- * 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.
- */
-public class X11JAWTToolkitLock implements ToolkitLock {
- long displayHandle;
- RecursiveLock lock;
-
- public X11JAWTToolkitLock(long displayHandle) {
- this.displayHandle = displayHandle;
- if(!X11Util.isNativeLockAvailable()) {
- lock = LockFactory.createRecursiveLock();
- }
- }
-
- 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();
- }
- }
-
- 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();
- }
-}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
index 736718de8..467809284 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
@@ -127,7 +127,8 @@ public class X11JAWTWindow extends JAWTWindow {
}
protected Point getLocationOnScreenNativeImpl(int x, int y) {
- return X11Lib.GetRelativeLocation( getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
+ // surface is locked and hence the device
+ return X11Lib.GetRelativeLocation(getDisplayHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
}
// Variables for lockSurface/unlockSurface
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java
deleted file mode 100644
index 5166ef577..000000000
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11ToolkitLock.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Copyright 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:
- *
- * 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.x11;
-
-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 {@link X11Util#XLockDisplay(long)}.
- *
- * This strategy should not be used in case XInitThreads() is being used,
- * or a higher level toolkit lock is required, ie AWT lock.
- */
-public class X11ToolkitLock implements ToolkitLock {
- long displayHandle;
- RecursiveLock lock;
-
- public X11ToolkitLock(long displayHandle) {
- this.displayHandle = displayHandle;
- if(!X11Util.isNativeLockAvailable()) {
- lock = LockFactory.createRecursiveLock();
- }
- }
-
- public final void lock() {
- if(TRACE_LOCK) { System.err.println("X11ToolkitLock.lock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XLockDisplay(displayHandle);
- } else {
- lock.lock();
- }
- }
-
- public final void unlock() {
- if(TRACE_LOCK) { System.err.println("X11ToolkitLock.unlock() - native: "+(null==lock)); }
- if(null == lock) {
- X11Lib.XUnlockDisplay(displayHandle);
- } else {
- lock.unlock();
- }
- }
-}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index 2ea75c7fb..60f54eb3c 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -42,8 +42,8 @@ import javax.media.nativewindow.NativeWindowFactory;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NWJNILibLoader;
-
import com.jogamp.common.util.LongObjectHashMap;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
/**
* Contains a thread safe X11 utility to retrieve display connections.
@@ -80,25 +80,15 @@ public class X11Util {
*/
public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true);
- /** Value is true
, best 'stable' results if always using XInitThreads(). */
- public static final boolean XINITTHREADS_ALWAYS_ENABLED = true;
-
- /** Value is true
, 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");
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 int setX11ErrorHandlerRecCount = 0;
private static Object setX11ErrorHandlerLock = new Object();
-
/**
* Called by {@link NativeWindowFactory#initSingleton()}
@@ -115,9 +105,7 @@ public class X11Util {
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 boolean isInitOK = initialize0( XERROR_STACKDUMP );
final long dpy = X11Lib.XOpenDisplay(null);
if(0 != dpy) {
@@ -134,9 +122,7 @@ public class X11Util {
}
if(DEBUG) {
- System.err.println("X11Util requiresX11Lock "+requiresX11Lock+
- ", XInitThreads [called "+callXInitThreads+", OK "+isXInitThreadsOK+"]"+
- ", isX11LockAvailable "+isX11LockAvailable+
+ System.err.println("X11Util init OK "+isInitOK+"]"+
", X11 Display(NULL) <"+nullDisplayName+">"+
", XSynchronize Enabled: "+XSYNC_ENABLED);
// Thread.dumpStack();
@@ -199,31 +185,14 @@ public class X11Util {
}
}
}
-
- public static synchronized boolean isNativeLockAvailable() {
- return isX11LockAvailable;
- }
-
- public static synchronized boolean requiresToolkitLock() {
- return requiresX11Lock;
+
+ public static boolean requiresToolkitLock() {
+ return true; // JAWT locking: yes, instead of native X11 locking w use a recursive lock.
}
-
+
public static void setX11ErrorHandler(boolean onoff, 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);
}
}
@@ -492,52 +461,50 @@ 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();
+ 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();
+ 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 (Exception ex) {
+ System.err.println("X11Util: Catched 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(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(long displayHandle) {
+ if( 0 == displayHandle ) {
+ throw new IllegalArgumentException("X11 Display handle is NULL");
}
if(!XineramaFetched) { // volatile: ok
synchronized(X11Util.class) {
@@ -551,9 +518,9 @@ public class X11Util {
}
}
if(0!=XineramaQueryFunc) {
- final boolean res = X11Lib.XineramaIsEnabled(XineramaQueryFunc, display);
+ final boolean res = X11Lib.XineramaIsEnabled(XineramaQueryFunc, displayHandle);
if(DEBUG) {
- System.err.println("XineramaIsEnabled: "+res);
+ System.err.println("XineramaIsEnabled: 0x"+Long.toHexString(displayHandle)+": "+res);
}
return res;
} else if(DEBUG) {
@@ -566,7 +533,7 @@ public class X11Util {
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..b152f0f97 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java
@@ -91,7 +91,7 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac
final long displayHandleAWT = X11SunJDKReflection.graphicsDeviceGetDisplay(device);
final long displayHandle;
- boolean owner = false;
+ final boolean owner;
if(0==displayHandleAWT) {
displayHandle = X11Util.openDisplay(null);
owner = true;
@@ -112,9 +112,8 @@ 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);
+ // 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) {
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index fcba8580c..afdd413eb 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -178,11 +178,14 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
char threadName[80];
char errCodeStr[80];
char reqCodeStr[80];
-
int shallBeDetached = 0;
- JNIEnv *jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv *jniEnv = NULL;
+ if( errorHandlerDebug || errorHandlerThrowException ) {
+ jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ }
(void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
+
snprintf(errCodeStr, sizeof(errCodeStr), "%d", e->request_code);
XGetErrorDatabaseText(dpy, "XRequest", errCodeStr, "Unknown", reqCodeStr, sizeof(reqCodeStr));
XGetErrorText(dpy, e->error_code, errCodeStr, sizeof(errCodeStr));
@@ -191,7 +194,7 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
threadName, e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
(int)e->request_code, (int)e->minor_code, reqCodeStr);
- if( errorHandlerDebug ) {
+ if( errorHandlerDebug && NULL != jniEnv ) {
(*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
}
@@ -246,16 +249,17 @@ static int x11IOErrorHandler(Display *dpy)
{
const char * dpyName = XDisplayName(NULL);
const char * errnoStr = strerror(errno);
- char threadName[80];
int shallBeDetached = 0;
- JNIEnv *jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
-
- (void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
+ JNIEnv *jniEnv = NULL;
- fprintf(stderr, "Nativewindow X11 IOError (Thread %s): Display %p (%s): %s\n", threadName, dpy, dpyName, errnoStr);
+ fprintf(stderr, "Nativewindow X11 IOError: Display %p (%s): %s\n", dpy, dpyName, errnoStr);
(*jniEnv)->CallStaticVoidMethod(jniEnv, X11UtilClazz, dumpStackID);
+ jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
if (NULL != jniEnv) {
+ char threadName[80];
+ (void) NativewindowCommon_GetStaticStringMethod(jniEnv, X11UtilClazz, getCurrentThreadNameID, threadName, sizeof(threadName), "n/a");
+
NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError (Thread %s): Display %p (%s): %s", threadName, dpy, dpyName, errnoStr);
if (shallBeDetached) {
@@ -305,6 +309,7 @@ Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboo
_initClazzAccess(env);
x11IOErrorHandlerEnable(1, env);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 0, 0 /* no dpy, no sync */);
_initialized=1;
if(JNI_TRUE == debug) {
fprintf(stderr, "Info: NativeWindow native init passed\n");
@@ -315,6 +320,7 @@ Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboo
JNIEXPORT void JNICALL
Java_jogamp_nativewindow_x11_X11Util_shutdown0(JNIEnv *env, jclass _unused) {
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0 /* no dpy, no sync */);
x11IOErrorHandlerEnable(0, env);
}
@@ -347,7 +353,7 @@ Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Lja
}
NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 1, 0, 0);
_res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, 0);
count = _ptr3[0];
if (arg3 != NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
@@ -382,7 +388,7 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
} else {
r = 0;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
return r;
}
@@ -396,7 +402,7 @@ Java_jogamp_nativewindow_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused,
}
NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 1, 0, 0);
r = (jint) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) );
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, 0);
return r;
}
@@ -439,7 +445,7 @@ Java_jogamp_nativewindow_x11_X11Lib_XCloseDisplay__J(JNIEnv *env, jclass _unused
}
NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 0, 0);
_res = XCloseDisplay((Display *) (intptr_t) display);
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0);
return _res;
}
@@ -497,7 +503,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
if (visual==NULL)
{
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
NativewindowCommon_throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!");
return 0;
}
@@ -541,7 +547,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateDummyWindow
XSelectInput(dpy, window, 0); // no events
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", window, dpy);
@@ -569,7 +575,7 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyDummyWindow
XUnmapWindow(dpy, w);
XSync(dpy, False);
XDestroyWindow(dpy, w);
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 1);
}
/*
@@ -597,7 +603,7 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_x11_X11Lib_GetRelativeLocatio
res = XTranslateCoordinates(dpy, src_win, dest_win, src_x, src_y, &dest_x, &dest_y, &child);
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0);
DBG_PRINT( "X11: GetRelativeLocation0: %p %d/%d -> %p %d/%d - ok: %d\n",
(void*)src_win, src_x, src_y, (void*)dest_win, dest_x, dest_y, (int)res);
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 1e9a0e9eb..391bccf3d 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -113,16 +113,22 @@ public abstract class Display {
*/
public abstract int removeReference();
+ /**
+ * Return the {@link AbstractGraphicsDevice} used for depending resources lifecycle,
+ * i.e. {@link Screen} and {@link Window}, as well as the event dispatching (EDT). */
public abstract AbstractGraphicsDevice getGraphicsDevice();
/**
- * @return the fully qualified Display name,
- * which is a key of {@link #getType()} + {@link #getName()} + {@link #getId()}
+ * Return the handle of the {@link AbstractGraphicsDevice} as returned by {@link #getGraphicsDevice()}.
*/
- public abstract String getFQName();
-
public abstract long getHandle();
+ /**
+ * @return The fully qualified Display name,
+ * which is a key of {@link #getType()} + {@link #getName()} + {@link #getId()}.
+ */
+ public abstract String getFQName();
+
/**
* @return this display internal serial id
*/
@@ -141,6 +147,9 @@ public abstract class Display {
*/
public abstract String getType();
+ /** Return true if this instance is exclusive, i.e. will not be shared. */
+ public abstract boolean isExclusive();
+
/**
* Sets a new {@link EDTUtil} and returns the previous one.
*
null
.
* diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index b16b0c75c..9288652d9 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -60,7 +60,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice /** * Create an instance with the system default {@link ToolkitLock}. - * gathered via {@link NativeWindowFactory#createDefaultToolkitLock(String, long)}. + * gathered via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}. * @param type * @param handle */ @@ -70,7 +70,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice this.unitID = unitID; this.uniqueID = getUniqueID(type, connection, unitID); this.handle = handle; - this.toolkitLock = NativeWindowFactory.createDefaultToolkitLock(type, handle); + this.toolkitLock = NativeWindowFactory.getDefaultToolkitLock(type, handle); } /** @@ -123,8 +123,10 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } /** - * No lock is performed on the graphics device per default, - * instead the aggregated recursive {@link ToolkitLock#lock()} is invoked. + * {@inheritDoc} + *
+ * Locking is perfomed via delegation to {@link ToolkitLock#lock()}, {@link ToolkitLock#unlock()}. + *
* * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) @@ -134,9 +136,16 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice toolkitLock.lock(); } + @Override + public final void validateLocked() throws RuntimeException { + toolkitLock.validateLocked(); + } + /** - * No lock is performed on the graphics device per default, - * instead the aggregated recursive {@link ToolkitLock#unlock()} is invoked. + * {@inheritDoc} + *+ * Locking is perfomed via delegation to {@link ToolkitLock#lock()}, {@link ToolkitLock#unlock()}. + *
* * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index 4f4bb629b..af8008f0f 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -42,6 +42,7 @@ import java.util.Map; import jogamp.nativewindow.Debug; import jogamp.nativewindow.NativeWindowFactoryImpl; +import jogamp.nativewindow.ToolkitProperties; import jogamp.nativewindow.ResourceToolkitLock; import com.jogamp.common.os.Platform; @@ -87,13 +88,17 @@ public abstract class NativeWindowFactory { private static boolean isAWTAvailable; private static final String JAWTUtilClassName = "jogamp.nativewindow.jawt.JAWTUtil" ; + /** {@link jogamp.nativewindow.x11.X11Util} implements {@link ToolkitProperties}. */ private static final String X11UtilClassName = "jogamp.nativewindow.x11.X11Util"; + /** {@link jogamp.nativewindow.macosx.OSXUtil} implements {@link ToolkitProperties}. */ private static final String OSXUtilClassName = "jogamp.nativewindow.macosx.OSXUtil"; + /** {@link jogamp.nativewindow.windows.GDIUtil} implements {@link ToolkitProperties}. */ private static final String GDIClassName = "jogamp.nativewindow.windows.GDIUtil"; private static ToolkitLock jawtUtilJAWTToolkitLock; private static boolean requiresToolkitLock; + private static boolean requiresGlobalToolkitLock; private static volatile boolean isJVMShuttingDown = false; @@ -156,11 +161,18 @@ public abstract class NativeWindowFactory { if( null != clazzName ) { ReflectionUtil.callStaticMethod(clazzName, "initSingleton", null, null, cl ); - final Boolean res = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "requiresToolkitLock", null, null, cl); - requiresToolkitLock = res.booleanValue(); + final Boolean res1 = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "requiresToolkitLock", null, null, cl); + requiresToolkitLock = res1.booleanValue(); + if(requiresToolkitLock) { + final Boolean res2 = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "requiresGlobalToolkitLock", null, null, cl); + requiresGlobalToolkitLock = res2.booleanValue(); + } else { + requiresGlobalToolkitLock = false; + } } else { requiresToolkitLock = false; - } + requiresGlobalToolkitLock = false; + } } private static void shutdownNativeImpl(final ClassLoader cl) { @@ -261,7 +273,7 @@ public abstract class NativeWindowFactory { } if(DEBUG) { - System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock); + System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock+", requiresGlobalToolkitLock "+requiresGlobalToolkitLock); System.err.println("NativeWindowFactory isAWTAvailable "+isAWTAvailable+", defaultFactory "+factory); } @@ -295,7 +307,12 @@ public abstract class NativeWindowFactory { /** @return true if the underlying toolkit requires locking, otherwise false. */ public static boolean requiresToolkitLock() { return requiresToolkitLock; - } + } + + /** @return true if the underlying toolkit requires global locking, otherwise false. */ + public static boolean requiresGlobalToolkitLock() { + return requiresGlobalToolkitLock; + } /** @return true if not headless, AWT Component and NativeWindow's AWT part available */ public static boolean isAWTAvailable() { return isAWTAvailable; } @@ -331,9 +348,28 @@ public abstract class NativeWindowFactory { return defaultFactory; } + /** + * Returns the AWT {@link ToolkitLock} (JAWT based) if {@link #isAWTAvailable}, otherwise null. + *+ * The JAWT based {@link ToolkitLock} also locks the global lock, + * which matters if the latter is required. + *
+ */ + public static ToolkitLock getAWTToolkitLock() { + return jawtUtilJAWTToolkitLock; + } + + public static ToolkitLock getNullToolkitLock() { + return NativeWindowFactoryImpl.getNullToolkitLock(); + } + + public static ToolkitLock getGlobalToolkitLock() { + return NativeWindowFactoryImpl.getGlobalToolkitLock(); + } + /** - * Provides the system default {@link ToolkitLock}, a singleton instance. - *type
, a singleton instance.
+ * Provides the default {@link ToolkitLock} for type
.
* type
is of {@link #TYPE_AWT} and AWT available,type
and deviceHandle
.
- * type
and deviceHandle
.
+ * Provides the default {@link ToolkitLock} for type
and deviceHandle
.
* type
is of {@link #TYPE_AWT} and AWT available,- * One use case is the AWT locking on X11, see {@link NativeWindowFactory#createDefaultToolkitLock(String, long)}. + * One use case is the AWT locking on X11, see {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}. *
*/ public interface ToolkitLock { + public static final boolean DEBUG = Debug.debug("ToolkitLock"); public static final boolean TRACE_LOCK = Debug.isPropertyDefined("nativewindow.debug.ToolkitLock.TraceLock", true); + /** + * Blocking until the lock is acquired by this Thread or a timeout is reached. + *+ * Timeout is implementation specific, if used at all. + *
+ * + * @throws RuntimeException in case of a timeout + */ public void lock(); + + /** + * Release the lock. + * + * @throws RuntimeException in case the lock is not acquired by this thread. + */ public void unlock(); + /** + * @throws RuntimeException if current thread does not hold the lock + */ + public void validateLocked() throws RuntimeException; + /** * Dispose this instance. *diff --git a/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java new file mode 100644 index 000000000..0c2a1e43f --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/GlobalToolkitLock.java @@ -0,0 +1,75 @@ +/** + * 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 javax.media.nativewindow.ToolkitLock; + +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; + +/** + * Implementing a global recursive {@link javax.media.nativewindow.ToolkitLock}. + *
+ * This is the last resort for unstable driver, e.g. proprietary ATI/X11 12.8 and 12.9, + * where multiple X11 display connections to the same connection name are not treated + * thread safe within the GL/X11 driver. + *
+ */ +public class GlobalToolkitLock implements ToolkitLock { + private static final RecursiveLock globalLock = LockFactory.createRecursiveLock(); + + /** Singleton via {@link NativeWindowFactoryImpl#getGlobalToolkitLock()} */ + protected GlobalToolkitLock() { } + + @Override + public final void lock() { + globalLock.lock(); + if(TRACE_LOCK) { System.err.println("GlobalToolkitLock.lock()"); } + } + + @Override + public final void unlock() { + if(TRACE_LOCK) { System.err.println("GlobalToolkitLock.unlock()"); } + globalLock.unlock(); // implicit lock validation + } + + @Override + public final void validateLocked() throws RuntimeException { + globalLock.validateLocked(); + } + + @Override + public final void dispose() { + // nop + } + + public String toString() { + return "GlobalToolkitLock[obj 0x"+Integer.toHexString(hashCode())+", isOwner "+globalLock.isOwner(Thread.currentThread())+", "+globalLock.toString()+"]"; + } +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java b/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java index 29564da3b..c35cede77 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java +++ b/src/nativewindow/classes/jogamp/nativewindow/NativeWindowFactoryImpl.java @@ -44,9 +44,14 @@ import com.jogamp.common.util.ReflectionUtil.AWTNames; public class NativeWindowFactoryImpl extends NativeWindowFactory { private static final ToolkitLock nullToolkitLock = new NullToolkitLock(); + private static final ToolkitLock globalToolkitLock = new GlobalToolkitLock(); public static ToolkitLock getNullToolkitLock() { - return nullToolkitLock; + return nullToolkitLock; + } + + public static ToolkitLock getGlobalToolkitLock() { + return globalToolkitLock; } // This subclass of NativeWindowFactory handles the case of diff --git a/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java index e59910138..211e15955 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java +++ b/src/nativewindow/classes/jogamp/nativewindow/NullToolkitLock.java @@ -31,15 +31,16 @@ package jogamp.nativewindow; 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 { - + public static final boolean INVALID_LOCKED = Debug.isPropertyDefined("nativewindow.debug.NullToolkitLock.InvalidLocked", true); + /** Singleton via {@link NativeWindowFactoryImpl#getNullToolkitLock()} */ protected NullToolkitLock() { } + @Override public final void lock() { if(TRACE_LOCK) { System.err.println("NullToolkitLock.lock()"); @@ -47,10 +48,20 @@ public class NullToolkitLock implements ToolkitLock { } } + @Override public final void unlock() { if(TRACE_LOCK) { System.err.println("NullToolkitLock.unlock()"); } } + @Override + public final void validateLocked() throws RuntimeException { + /* nop */ + if(INVALID_LOCKED) { + throw new RuntimeException("NullToolkitLock does not lock"); + } + } + + @Override public final void dispose() { // nop } diff --git a/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java index a3b0804fa..5b79de0b8 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java +++ b/src/nativewindow/classes/jogamp/nativewindow/ResourceToolkitLock.java @@ -41,8 +41,6 @@ import com.jogamp.common.util.locks.RecursiveLock; * */ public class ResourceToolkitLock implements ToolkitLock { - public static final boolean DEBUG = Debug.debug("ToolkitLock"); - public static final ResourceToolkitLock create() { return new ResourceToolkitLock(); } @@ -53,17 +51,24 @@ public class ResourceToolkitLock implements ToolkitLock { this.lock = LockFactory.createRecursiveLock(); } - + @Override public final void lock() { - if(TRACE_LOCK) { System.err.println("ResourceToolkitLock.lock()"); } lock.lock(); + if(TRACE_LOCK) { System.err.println("ResourceToolkitLock.lock()"); } } + @Override public final void unlock() { if(TRACE_LOCK) { System.err.println("ResourceToolkitLock.unlock()"); } - lock.unlock(); + lock.unlock(); // implicit lock validation + } + + @Override + public final void validateLocked() throws RuntimeException { + lock.validateLocked(); } + @Override public final void dispose() { // nop } diff --git a/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java index 5d7ae8abb..94d12e6fc 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java +++ b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java @@ -49,7 +49,6 @@ import com.jogamp.common.util.locks.RecursiveLock; * */ public class SharedResourceToolkitLock implements ToolkitLock { - public static final boolean DEBUG = Debug.debug("ToolkitLock"); private static final LongObjectHashMap handle2Lock; static { handle2Lock = new LongObjectHashMap(); @@ -109,16 +108,24 @@ public class SharedResourceToolkitLock implements ToolkitLock { } + @Override public final void lock() { - if(TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.lock()"); } lock.lock(); + if(TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.lock()"); } } + @Override public final void unlock() { if(TRACE_LOCK) { System.err.println("SharedResourceToolkitLock.unlock()"); } lock.unlock(); } + @Override + public final void validateLocked() throws RuntimeException { + lock.validateLocked(); + } + + @Override public final void dispose() { if(0 < refCount) { // volatile OK synchronized(handle2Lock) { diff --git a/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java b/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java new file mode 100644 index 000000000..2062d1f58 --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/ToolkitProperties.java @@ -0,0 +1,51 @@ +package jogamp.nativewindow; + +import javax.media.nativewindow.NativeWindowFactory; + +/** + * Marker interface. + *+ * Implementation requires to provide static methods: + *
+ public static void initSingleton() {} + + public static void shutdown() {} + + public static boolean requiresToolkitLock() {} + + public static boolean requiresGlobalToolkitLock() {} + *+ * Above static methods are invoked by {@link NativeWindowFactory#initSingleton()}, + * or {@link NativeWindowFactory#shutdown()} via reflection. + * + *
+ * If requiresGlobalToolkitLock() == true
, then
+ * requiresToolkitLock() == true
shall be valid as well.
+ *
+ * Called by {@link NativeWindowFactory#shutdown()} + *
+ */ + // void shutdown(); + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + */ + // boolean requiresToolkitLock(); + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + */ + // boolean requiresGlobalToolkitLock(); + +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java index 7c934b154..2dadfb16b 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java @@ -79,6 +79,8 @@ public class JAWTUtil { private static final Method sunToolkitAWTLockMethod; private static final Method sunToolkitAWTUnlockMethod; private static final boolean hasSunToolkitAWTLock; + + private static volatile Thread exclusiveOwnerThread; private static final ToolkitLock jawtToolkitLock; @@ -229,13 +231,23 @@ public class JAWTUtil { } hasSunToolkitAWTLock = _hasSunToolkitAWTLock; // hasSunToolkitAWTLock = false; + exclusiveOwnerThread = null; jawtToolkitLock = new ToolkitLock() { public final void lock() { + NativeWindowFactory.getGlobalToolkitLock().lock(); JAWTUtil.lockToolkit(); + if(TRACE_LOCK) { System.err.println("JAWTToolkitLock.lock()"); } } public final void unlock() { + if(TRACE_LOCK) { System.err.println("JAWTToolkitLock.unlock()"); } JAWTUtil.unlockToolkit(); + NativeWindowFactory.getGlobalToolkitLock().unlock(); + } + @Override + public final void validateLocked() throws RuntimeException { + NativeWindowFactory.getGlobalToolkitLock().validateLocked(); + JAWTUtil.validateLocked(); } public final void dispose() { // nop @@ -312,7 +324,7 @@ public class JAWTUtil { * JAWT's native Lock() function calls SunToolkit.awtLock(), * which just uses AWT's global ReentrantLock.@@ -88,11 +90,15 @@ public class X11Util { private static String nullDisplayName = null; private static volatile boolean isInit = false; private static boolean markAllDisplaysUnclosable = false; // ATI/AMD X11 driver issues + private static boolean requiresGlobalToolkitLock = false; // ATI/AMD X11 driver issues private static 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) { @@ -100,7 +106,7 @@ 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."); @@ -108,6 +114,7 @@ public class X11Util { final boolean isInitOK = initialize0( XERROR_STACKDUMP ); + final boolean hasX11_EXTENSION_ATIFGLRXDRI, hasX11_EXTENSION_ATIFGLEXTENSION; final long dpy = X11Lib.XOpenDisplay(null); if(0 != dpy) { if(XSYNC_ENABLED) { @@ -115,17 +122,29 @@ public class X11Util { } 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; } + requiresGlobalToolkitLock = hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION; + markAllDisplaysUnclosable = ATI_HAS_XCLOSEDISPLAY_BUG && ( hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION ); if(DEBUG) { - System.err.println("X11Util init OK "+isInitOK+"]"+ - ", 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 requiresGlobalToolkitLock "+requiresGlobalToolkitLock()+ + ",\n\t markAllDisplaysUnclosable "+getMarkAllDisplaysUnclosable() + ); // Thread.dumpStack(); } } @@ -147,6 +166,7 @@ public class X11Util { *
* Called by {@link NativeWindowFactory#shutdown()} *
+ * @see ToolkitProperties */ public static void shutdown() { if(isInit) { @@ -189,8 +209,20 @@ public class X11Util { } } - public static boolean requiresToolkitLock() { - return true; // JAWT locking: yes, instead of native X11 locking w use a recursive lock. + /** + * 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. + } + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties + */ + public static final boolean requiresGlobalToolkitLock() { + return requiresGlobalToolkitLock; // JAWT locking: yes, instead of native X11 locking w use a global lock. } public static void setX11ErrorHandler(boolean onoff, boolean quiet) { @@ -206,9 +238,6 @@ public class X11Util { public static boolean getMarkAllDisplaysUnclosable() { return markAllDisplaysUnclosable; } - public static void setMarkAllDisplaysUnclosable(boolean v) { - markAllDisplaysUnclosable = v; - } private X11Util() {} @@ -373,7 +402,7 @@ public class X11Util { name = validateDisplayName(name); boolean reused = false; - synchronized(globalLock) { + synchronized(globalLock) { for(int i=0; iNote: To employ custom GLCapabilities, NewtCanvasSWT shall be used instead.
- * + *+ * Implementation allows use of custom {@link GLCapabilities}. + *
*/ public class GLCanvas extends Canvas implements GLAutoDrawable { private static final boolean DEBUG = Debug.debug("GLCanvas"); @@ -103,11 +107,15 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { private final GLCapabilitiesImmutable capsRequested; private final GLCapabilitiesChooser capsChooser; + private volatile Rectangle clientArea; private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access - private GLContextImpl context; + private volatile GLContextImpl context; /* Native window surface */ - private AbstractGraphicsDevice device; + private final boolean useX11GTK; + private volatile long gdkWindow; // either GDK child window .. + private volatile long x11Window; // .. or X11 child window (for GL rendering) + private final AbstractGraphicsScreen screen; /* Construction parameters stored for GLAutoDrawable accessor methods */ private int additionalCtxCreationFlags = 0; @@ -135,7 +143,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public void run() { if (sendReshape) { - helper.reshape(GLCanvas.this, 0, 0, getWidth(), getHeight()); + helper.reshape(GLCanvas.this, 0, 0, clientArea.width, clientArea.height); sendReshape = false; } helper.display(GLCanvas.this); @@ -143,7 +151,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { }; /* Action to make specified context current prior to running displayAction */ - private final Runnable makeCurrentAndDisplayOnEDTAction = new Runnable() { + private final Runnable makeCurrentAndDisplayOnGLAction = new Runnable() { @Override public void run() { final RecursiveLock _lock = lock; @@ -159,13 +167,14 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { }; /* Swaps buffers, assuming the GLContext is current */ - private final Runnable swapBuffersOnEDTAction = new Runnable() { + private final Runnable swapBuffersOnGLAction = new Runnable() { @Override public void run() { final RecursiveLock _lock = lock; _lock.lock(); try { - if(null != drawable && !GLCanvas.this.isDisposed() ) { + final boolean drawableOK = null != drawable && drawable.isRealized(); + if( drawableOK && !GLCanvas.this.isDisposed() ) { drawable.swapBuffers(); } } finally { @@ -212,10 +221,14 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { drawable.setRealized(false); drawable = null; } - if (null != device) { - device.close(); - device = null; + if( 0 != x11Window) { + SWTAccessor.destroyX11Window(screen.getDevice(), x11Window); + x11Window = 0; + } else if( 0 != gdkWindow) { + SWTAccessor.destroyGDKWindow(gdkWindow); + gdkWindow = 0; } + screen.getDevice().close(); if (animatorPaused) { animator.resume(); @@ -249,11 +262,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { } }; - /** - * Storage for the client area rectangle so that it may be accessed from outside of the SWT thread. - */ - private volatile Rectangle clientArea; - /** * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser, GLContext)} * on the SWT thread. @@ -293,72 +301,80 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { * @param style * Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the * Canvas constructor, so OpenGL handles the background. - * @param caps + * @param capsReqUser * Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the * graphics device determined by the parent Composite are used. Note that the GLCapabilities that are * actually used may differ based on the capabilities of the graphics device. - * @param chooser + * @param capsChooser * Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the * requested GLCapabilities, and the available capabilities of the graphics device. * @param shareWith * Optional GLContext to share state (textures, vbos, shaders, etc.) with. */ - public GLCanvas(final Composite parent, final int style, GLCapabilitiesImmutable caps, - final GLCapabilitiesChooser chooser, final GLContext shareWith) { + public GLCanvas(final Composite parent, final int style, GLCapabilitiesImmutable capsReqUser, + final GLCapabilitiesChooser capsChooser, final GLContext shareWith) { /* NO_BACKGROUND required to avoid clearing bg in native SWT widget (we do this in the GL display) */ super(parent, style | SWT.NO_BACKGROUND); GLProfile.initSingleton(); // ensure JOGL is completly initialized SWTAccessor.setRealized(this, true); - + clientArea = GLCanvas.this.getClientArea(); /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). * Note: SWT is owner of the native handle, hence closing operation will be a NOP. */ - device = SWTAccessor.getDevice(this); + final AbstractGraphicsDevice swtDevice = SWTAccessor.getDevice(this); + + useX11GTK = SWTAccessor.useX11GTK(); + if(useX11GTK) { + // Decoupled X11 Device/Screen allowing X11 display lock-free off-thread rendering + final long x11DeviceHandle = X11Util.openDisplay(swtDevice.getConnection()); + if( 0 == x11DeviceHandle ) { + throw new RuntimeException("Error creating display(EDT): "+swtDevice.getConnection()); + } + final AbstractGraphicsDevice x11Device = new X11GraphicsDevice(x11DeviceHandle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */); + screen = SWTAccessor.getScreen(x11Device, -1 /* default */); + } else { + screen = SWTAccessor.getScreen(swtDevice, -1 /* default */); + } /* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */ - if(null == caps) { - caps = new GLCapabilities(GLProfile.getDefault(device)); + if(null == capsReqUser) { + capsReqUser = new GLCapabilities(GLProfile.getDefault(screen.getDevice())); } - this.capsRequested = caps; - this.capsChooser = chooser; + + this.capsRequested = capsReqUser; + this.capsChooser = capsChooser; this.shareWith = shareWith; // post create .. when ready + gdkWindow = 0; + x11Window = 0; drawable = null; context = null; - /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */ - /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */ - addPaintListener(new PaintListener() { - @Override - public void paintControl(final PaintEvent arg0) { - if ( !helper.isAnimatorAnimatingOnOtherThread() ) { - display(); // checks: null != drawable - } - } - }); - - addControlListener(new ControlListener() { - @Override - public void controlMoved(ControlEvent e) { - } - - @Override - public void controlResized(final ControlEvent arg0) { - updateSizeCheck(); - } - }); - - addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - GLCanvas.this.dispose(); - } - }); + final Listener listener = new Listener () { + @Override + public void handleEvent (Event event) { + switch (event.type) { + case SWT.Paint: + displayIfNoAnimatorNoCheck(); + break; + case SWT.Resize: + updateSizeCheck(); + break; + case SWT.Dispose: + GLCanvas.this.dispose(); + break; + } + } + }; + addListener (SWT.Resize, listener); + addListener (SWT.Paint, listener); + addListener (SWT.Dispose, listener); } + private final UpstreamSurfaceHook swtCanvasUpStreamHook = new UpstreamSurfaceHook() { @Override public final void create(ProxySurface s) { /* nop */ } @@ -390,11 +406,13 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { ) { clientArea = nClientArea; // write back new value - GLDrawableImpl _drawable = drawable; - if( null != _drawable ) { - if(DEBUG) { - System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); - } + final GLDrawableImpl _drawable = drawable; + final boolean drawableOK = null != _drawable && _drawable.isRealized(); + if(DEBUG) { + final long dh = drawableOK ? _drawable.getHandle() : 0; + System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - drawableHandle 0x"+Long.toHexString(dh)); + } + if( drawableOK ) { if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { final RecursiveLock _lock = lock; _lock.lock(); @@ -407,66 +425,154 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { } finally { _lock.unlock(); } - } - sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock - } + } + } + if(0 != x11Window) { + SWTAccessor.resizeX11Window(screen.getDevice(), clientArea, x11Window); + } else if(0 != gdkWindow) { + SWTAccessor.resizeGDKWindow(clientArea, gdkWindow); + } + sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock } } - @Override - public void display() { - if( null != drawable || validateDrawableAndContext() ) { - runInGLThread(makeCurrentAndDisplayOnEDTAction); - } + private boolean isValidAndVisibleOnEDTActionResult; + private final Runnable isValidAndVisibleOnEDTAction = new Runnable() { + @Override + public void run() { + isValidAndVisibleOnEDTActionResult = !GLCanvas.this.isDisposed() && GLCanvas.this.isVisible(); + } }; + + private final boolean isValidAndVisibleOnEDT() { + synchronized(isValidAndVisibleOnEDTAction) { + runOnEDTIfAvail(true, isValidAndVisibleOnEDTAction); + return isValidAndVisibleOnEDTActionResult; + } } - - /** assumes drawable == null ! */ - protected final boolean validateDrawableAndContext() { - if( isDisposed() || !isVisible() ) { + /** assumes drawable == null || !drawable.isRealized() ! Checks of !isDispose() and isVisible() */ + protected final boolean validateDrawableAndContextWithCheck() { + if( !isValidAndVisibleOnEDT() ) { return false; } + return validateDrawableAndContextPostCheck(); + } + + /** assumes drawable == null || !drawable.isRealized() ! No check of !isDispose() and isVisible() */ + protected final boolean validateDrawableAndContextPostCheck() { final Rectangle nClientArea = clientArea; if(0 >= nClientArea.width || 0 >= nClientArea.height) { return false; } + final boolean res; final RecursiveLock _lock = lock; _lock.lock(); try { - final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile()); - - /* Native handle for the control, used to associate with GLContext */ - final long nativeWindowHandle = SWTAccessor.getWindowHandle(this); - - /* Create a NativeWindow proxy for the SWT canvas */ - ProxySurface proxySurface = null; - try { - proxySurface = glFactory.createProxySurface(device, 0 /* screenIdx */, nativeWindowHandle, - capsRequested, capsChooser, swtCanvasUpStreamHook); - } catch (GLException gle) { - // not ready yet .. - if(DEBUG) { System.err.println(gle.getMessage()); } + if(null == drawable) { + createDrawableAndContext(); } - - if(null != proxySurface) { - /* Associate a GL surface with the proxy */ - drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface); + if(null != drawable) { drawable.setRealized(true); - - context = (GLContextImpl) drawable.createContext(shareWith); + res = drawable.isRealized(); + } else { + res = false; } } finally { _lock.unlock(); + } + + if(res) { + sendReshape = true; + if(DEBUG) { + System.err.println("SWT GLCanvas realized! "+this+", "+drawable); + // Thread.dumpStack(); + } } - final boolean res = null != drawable; - if(DEBUG && res) { - System.err.println("SWT GLCanvas realized! "+this+", "+drawable); - Thread.dumpStack(); - } - return res; + return res; + } + + private final void createDrawableAndContext() { + final AbstractGraphicsDevice device = screen.getDevice(); + device.open(); + + final long nativeWindowHandle; + if( useX11GTK ) { + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(device, capsRequested); + final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration( + capsRequested, capsRequested, capsChooser, screen, VisualIDHolder.VID_UNDEFINED); + if(DEBUG) { + System.err.println("SWT.GLCanvas.X11 factory: "+factory+", chosen config: "+cfg); + } + if (null == cfg) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + final int visualID = cfg.getVisualID(VIDType.NATIVE); + if( VisualIDHolder.VID_UNDEFINED != visualID ) { + // gdkWindow = SWTAccessor.createCompatibleGDKChildWindow(this, visualID, clientArea.width, clientArea.height); + // nativeWindowHandle = SWTAccessor.gdk_window_get_xwindow(gdkWindow); + x11Window = SWTAccessor.createCompatibleX11ChildWindow(screen, this, visualID, clientArea.width, clientArea.height); + nativeWindowHandle = x11Window; + } else { + throw new GLException("Could not choose valid visualID: 0x"+Integer.toHexString(visualID)+", "+this); + } + } else { + nativeWindowHandle = SWTAccessor.getWindowHandle(this); + } + final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile()); + + // Create a NativeWindow proxy for the SWT canvas + ProxySurface proxySurface = glFactory.createProxySurface(device, screen.getIndex(), nativeWindowHandle, + capsRequested, capsChooser, swtCanvasUpStreamHook); + // Associate a GL surface with the proxy + drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface); + context = (GLContextImpl) drawable.createContext(shareWith); + context.setContextCreationFlags(additionalCtxCreationFlags); + } + + @Override + public void update() { + // don't paint background etc .. nop avoids flickering + // super.update(); + } + + /** + @Override + public boolean forceFocus() { + final boolean r = super.forceFocus(); + if(r && 0 != gdkWindow) { + SWTGTKUtil.focusGDKWindow(gdkWindow); + } + return r; + } */ + + @Override + public void dispose() { + runInGLThread(disposeOnEDTGLAction); + super.dispose(); + } + + private final void displayIfNoAnimatorNoCheck() { + if ( !helper.isAnimatorAnimatingOnOtherThread() ) { + final boolean drawableOK = null != drawable && drawable.isRealized(); + if( drawableOK || validateDrawableAndContextPostCheck() ) { + runInGLThread(makeCurrentAndDisplayOnGLAction); + } + } } + // + // GL[Auto]Drawable + // + + @Override + public void display() { + final boolean drawableOK = null != drawable && drawable.isRealized(); + if( drawableOK || validateDrawableAndContextWithCheck() ) { + runInGLThread(makeCurrentAndDisplayOnGLAction); + } + } + @Override public final Object getUpstreamWidget() { return this; @@ -692,18 +798,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public void swapBuffers() throws GLException { - runInGLThread(swapBuffersOnEDTAction); - } - - @Override - public void update() { - // don't paint background etc .. nop avoids flickering - } - - @Override - public void dispose() { - runInGLThread(disposeOnEDTGLAction); - super.dispose(); + runInGLThread(swapBuffersOnGLAction); } /** @@ -746,7 +841,32 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { } */ action.run(); } + + private void runOnEDTIfAvail(boolean wait, final Runnable action) { + final Display d = isDisposed() ? null : getDisplay(); + if( null == d || d.isDisposed() || d.getThread() == Thread.currentThread() ) { + action.run(); + } else if(wait) { + d.syncExec(action); + } else { + d.asyncExec(action); + } + } + + @Override + public String toString() { + final GLDrawable _drawable = drawable; + final int dw = (null!=_drawable) ? _drawable.getWidth() : -1; + final int dh = (null!=_drawable) ? _drawable.getHeight() : -1; + return "SWT-GLCanvas[Realized "+isRealized()+ + ",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+ + ",\n\tFactory "+getFactory()+ + ",\n\thandle 0x"+Long.toHexString(getHandle())+ + ",\n\tDrawable size "+dw+"x"+dh+ + ",\n\tSWT size "+getWidth()+"x"+getHeight()+"]"; + } + public static void main(final String[] args) { System.err.println(VersionUtil.getPlatformInfo()); System.err.println(GlueGenVersion.getInstance()); diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java index e208cfb28..eba26c7d3 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java @@ -34,6 +34,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import org.eclipse.swt.graphics.GCData; +import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Control; import javax.media.nativewindow.AbstractGraphicsScreen; @@ -59,12 +60,22 @@ public class SWTAccessor { private static final Field swt_control_handle; private static final boolean swt_uses_long_handles; + private static Object swt_osx_init = new Object(); + private static Field swt_osx_control_view = null; + private static Field swt_osx_view_id = null; + + private static final String nwt; + private static final boolean isOSX; + private static final boolean isWindows; + private static final boolean isX11; + private static final boolean isX11GTK; + // X11/GTK, Windows/GDI, .. private static final String str_handle = "handle"; // OSX/Cocoa - private static final String str_view = "view"; // OSX - private static final String str_id = "id"; // OSX + private static final String str_osx_view = "view"; // OSX + private static final String str_osx_id = "id"; // OSX // static final String str_NSView = "org.eclipse.swt.internal.cocoa.NSView"; private static final Method swt_control_internal_new_GC; @@ -73,9 +84,10 @@ public class SWTAccessor { private static final String str_internal_dispose_GC = "internal_dispose_GC"; private static final String str_OS_gtk_class = "org.eclipse.swt.internal.gtk.OS"; - private static final Class> OS_gtk_class; + public static final Class> OS_gtk_class; private static final String str_OS_gtk_version = "GTK_VERSION"; - private static final VersionNumber OS_gtk_version; + public static final VersionNumber OS_gtk_version; + private static final Method OS_gtk_widget_realize; private static final Method OS_gtk_widget_unrealize; // optional (removed in SWT 4.3) private static final Method OS_GTK_WIDGET_WINDOW; @@ -85,6 +97,8 @@ public class SWTAccessor { private static final Method OS_gdk_window_get_display; private static final Method OS_gdk_x11_drawable_get_xid; private static final Method OS_gdk_x11_window_get_xid; + private static final Method OS_gdk_window_set_back_pixmap; + private static final String str_gtk_widget_realize = "gtk_widget_realize"; private static final String str_gtk_widget_unrealize = "gtk_widget_unrealize"; private static final String str_GTK_WIDGET_WINDOW = "GTK_WIDGET_WINDOW"; @@ -94,6 +108,7 @@ public class SWTAccessor { private static final String str_gdk_window_get_display = "gdk_window_get_display"; private static final String str_gdk_x11_drawable_get_xid = "gdk_x11_drawable_get_xid"; private static final String str_gdk_x11_window_get_xid = "gdk_x11_window_get_xid"; + private static final String str_gdk_window_set_back_pixmap = "gdk_window_set_back_pixmap"; private static final VersionNumber GTK_VERSION_2_14_0 = new VersionNumber(2, 14, 0); private static final VersionNumber GTK_VERSION_2_24_0 = new VersionNumber(2, 24, 0); @@ -108,23 +123,25 @@ public class SWTAccessor { } static { - Field f = null; - AccessController.doPrivileged(new PrivilegedAction+ * Disclaimer: This code is merely tested and subject to change. + *
+ */ +public class SWTNewtEventFactory { + + protected static final IntIntHashMap eventTypeSWT2NEWT; + + static { + IntIntHashMap map = new IntIntHashMap(); + map.setKeyNotFoundValue(0xFFFFFFFF); + + // map.put(SWT.MouseXXX, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED); + map.put(SWT.MouseDown, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED); + map.put(SWT.MouseUp, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED); + map.put(SWT.MouseMove, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED); + map.put(SWT.MouseEnter, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED); + map.put(SWT.MouseExit, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED); + // map.put(SWT.MouseXXX, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED); + map.put(SWT.MouseVerticalWheel, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED); + + map.put(SWT.KeyDown, com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED); + map.put(SWT.KeyUp, com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED); + // map.put(SWT.KeyXXX, com.jogamp.newt.event.KeyEvent.EVENT_KEY_TYPED); + + eventTypeSWT2NEWT = map; + } + + public static final int swtModifiers2Newt(int awtMods, boolean mouseHint) { + int newtMods = 0; + if ((awtMods & SWT.SHIFT) != 0) newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK; + if ((awtMods & SWT.CTRL) != 0) newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK; + if ((awtMods & SWT.ALT) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK; + return newtMods; + } + + public static final com.jogamp.newt.event.InputEvent createInputEvent(org.eclipse.swt.widgets.Event event, Object source) { + com.jogamp.newt.event.InputEvent res = createMouseEvent(event, source); + if(null == res) { + res = createKeyEvent(event, source); + } + return res; + } + + public static final com.jogamp.newt.event.MouseEvent createMouseEvent(org.eclipse.swt.widgets.Event event, Object source) { + switch(event.type) { + case SWT.MouseDown: + case SWT.MouseUp: + case SWT.MouseMove: + case SWT.MouseEnter: + case SWT.MouseExit: + case SWT.MouseVerticalWheel: + break; + default: + return null; + } + int type = eventTypeSWT2NEWT.get(event.type); + if(0xFFFFFFFF != type) { + int rotation = 0; + if (SWT.MouseVerticalWheel == event.type) { + // SWT/NEWT rotation is reversed - AWT +1 is down, NEWT +1 is up. + // rotation = -1 * (int) event.rotation; + rotation = (int) event.rotation; + } + + int mods = swtModifiers2Newt(event.stateMask, true); + + if( source instanceof com.jogamp.newt.Window) { + final com.jogamp.newt.Window newtSource = (com.jogamp.newt.Window)source; + if(newtSource.isPointerConfined()) { + mods |= InputEvent.CONFINED_MASK; + } + if(!newtSource.isPointerVisible()) { + mods |= InputEvent.INVISIBLE_MASK; + } + } + + return new com.jogamp.newt.event.MouseEvent( + type, (null==source)?(Object)event.data:source, (0xFFFFFFFFL & (long)event.time), + mods, event.x, event.y, event.count, event.button, rotation); + } + return null; // no mapping .. + } + + public static final com.jogamp.newt.event.KeyEvent createKeyEvent(org.eclipse.swt.widgets.Event event, Object source) { + switch(event.type) { + case SWT.KeyDown: + case SWT.KeyUp: + break; + default: + return null; + } + int type = eventTypeSWT2NEWT.get(event.type); + if(0xFFFFFFFF != type) { + return new com.jogamp.newt.event.KeyEvent( + type, (null==source)?(Object)event.data:source, (0xFFFFFFFFL & (long)event.time), + swtModifiers2Newt(event.stateMask, false), + event.keyCode, event.character); + } + return null; // no mapping .. + } + + // + // + // + + int dragButtonDown = 0; + + public SWTNewtEventFactory() { + resetButtonsDown(); + } + + final void resetButtonsDown() { + dragButtonDown = 0; + } + + public final boolean dispatchMouseEvent(org.eclipse.swt.widgets.Event event, Object source, com.jogamp.newt.event.MouseListener l) { + com.jogamp.newt.event.MouseEvent res = createMouseEvent(event, source); + if(null != res) { + if(null != l) { + switch(event.type) { + case SWT.MouseDown: + dragButtonDown = event.button; + l.mousePressed(res); break; + case SWT.MouseUp: + dragButtonDown = 0; + l.mouseReleased(res); + { + final com.jogamp.newt.event.MouseEvent res2 = new com.jogamp.newt.event.MouseEvent( + com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED, + res.getSource(), + res.getWhen(), res.getModifiers(), + res.getX(), res.getY(), res.getClickCount(), + res.getButton(), res.getWheelRotation() ); + l.mouseClicked(res2); + } + break; + case SWT.MouseMove: + if( 0 < dragButtonDown ) { + final com.jogamp.newt.event.MouseEvent res2 = new com.jogamp.newt.event.MouseEvent( + com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED, + res.getSource(), + res.getWhen(), res.getModifiers(), + res.getX(), res.getY(), res.getClickCount(), + dragButtonDown, res.getWheelRotation() ); + l.mouseDragged( res2 ); + } else { + l.mouseMoved(res); + } + break; + case SWT.MouseEnter: + l.mouseEntered(res); + break; + case SWT.MouseExit: + resetButtonsDown(); + l.mouseExited(res); + break; + case SWT.MouseVerticalWheel: + l.mouseWheelMoved(res); + break; + } + } + return true; + } + return false; + } + + public final boolean dispatchKeyEvent(org.eclipse.swt.widgets.Event event, Object source, com.jogamp.newt.event.KeyListener l) { + com.jogamp.newt.event.KeyEvent res = createKeyEvent(event, source); + if(null != res) { + if(null != l) { + switch(event.type) { + case SWT.KeyDown: + l.keyPressed(res); + break; + case SWT.KeyUp: + l.keyReleased(res); + l.keyTyped(res); + break; + } + } + return true; + } + return false; + } + + public final void attachDispatchListener(final org.eclipse.swt.widgets.Control ctrl, final Object source, + final com.jogamp.newt.event.MouseListener ml, + final com.jogamp.newt.event.KeyListener kl) { + final Listener listener = new Listener () { + @Override + public void handleEvent (Event event) { + if( dispatchMouseEvent( event, source, ml ) ) { + return; + } + if( dispatchKeyEvent( event, source, kl ) ) { + return; + } + } }; + ctrl.addListener(SWT.MouseDown, listener); + ctrl.addListener(SWT.MouseUp, listener); + ctrl.addListener(SWT.MouseMove, listener); + ctrl.addListener(SWT.MouseEnter, listener); + ctrl.addListener(SWT.MouseExit, listener); + ctrl.addListener(SWT.MouseVerticalWheel, listener); + ctrl.addListener(SWT.KeyDown, listener); + ctrl.addListener(SWT.KeyUp, listener); + } +} + diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java index e9fe9b401..a3023538f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java @@ -60,8 +60,8 @@ public class GearsES2 implements GLEventListener { private int swapInterval = 0; private boolean pmvUseBackingArray = true; // the default for PMVMatrix now, since it's faster // private MouseListener gearsMouse = new TraceMouseAdapter(new GearsMouseAdapter()); - private MouseListener gearsMouse = new GearsMouseAdapter(); - private KeyListener gearsKeys = new GearsKeyAdapter(); + public MouseListener gearsMouse = new GearsMouseAdapter(); + public KeyListener gearsKeys = new GearsKeyAdapter(); private int prevMouseX, prevMouseY; private boolean doRotate = true; @@ -352,6 +352,10 @@ public class GearsES2 implements GLEventListener { window = (Window) source; width=window.getWidth(); height=window.getHeight(); + } else if (source instanceof GLAutoDrawable) { + GLAutoDrawable glad = (GLAutoDrawable) source; + width = glad.getWidth(); + height = glad.getHeight(); } else if (GLProfile.isAWTAvailable() && source instanceof java.awt.Component) { java.awt.Component comp = (java.awt.Component) source; width=comp.getWidth(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java index a0874e609..1f3bf3156 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTBug628ResizeDeadlock.java @@ -366,8 +366,9 @@ public class TestNewtCanvasSWTBug628ResizeDeadlock extends UITestCase { try { while( !shallStop && !dsc.display.isDisposed() ) { - if( !dsc.display.readAndDispatch() ) { - dsc.display.sleep(); + if( !dsc.display.readAndDispatch() && !shallStop ) { + // blocks on linux .. dsc.display.sleep(); + Thread.sleep(10); } } } catch (Exception e0) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java index 0a47b96eb..97b3ab243 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTBug643AsyncExec.java @@ -45,12 +45,13 @@ import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities ; import javax.media.opengl.GLProfile; +import jogamp.newt.swt.SWTEDTUtil; +import jogamp.newt.swt.event.SWTNewtEventFactory; import junit.framework.Assert; import com.jogamp.nativewindow.swt.SWTAccessor; import com.jogamp.newt.opengl.GLWindow ; import com.jogamp.newt.swt.NewtCanvasSWT ; -import com.jogamp.newt.swt.SWTEDTUtil; import com.jogamp.opengl.swt.GLCanvas; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; @@ -121,15 +122,15 @@ public class TestSWTBug643AsyncExec extends UITestCase { final Runnable swtAsyncAction = new Runnable() { public void run() { - ++swtN ; - System.err.println("[SWT A-i shallStop "+shallStop+"]: Counter[loc "+swtN+", glob: "+incrSWTCount()+"]"); + ++swtN ; incrSWTCount(); + System.err.println("[SWT A-i shallStop "+shallStop+"]: Counter[loc "+swtN+", glob: "+getSWTCount()+"]"); } }; final Runnable newtAsyncAction = new Runnable() { public void run() { - ++newtN ; - System.err.println("[NEWT A-i shallStop "+shallStop+"]: Counter[loc "+newtN+", glob: "+incrNEWTCount()+"]"); + ++newtN ; incrNEWTCount(); + System.err.println("[NEWT A-i shallStop "+shallStop+"]: Counter[loc "+newtN+", glob: "+getNEWTCount()+"]"); } }; public void run() @@ -219,9 +220,13 @@ public class TestSWTBug643AsyncExec extends UITestCase { final GLAutoDrawable glad; if( useJOGLGLCanvas ) { - glad = GLCanvas.create(dsc.composite, 0, caps, null, null); - glad.addGLEventListener( new GearsES2() ) ; - newtDisplay = null; + final GearsES2 demo = new GearsES2(); + final GLCanvas glc = GLCanvas.create(dsc.composite, 0, caps, null, null); + final SWTNewtEventFactory swtNewtEventFactory = new SWTNewtEventFactory(); + swtNewtEventFactory.attachDispatchListener(glc, glc, demo.gearsMouse, demo.gearsKeys); + glc.addGLEventListener( demo ) ; + glad = glc; + newtDisplay = null; } else if( useNewtCanvasSWT ) { final GLWindow glWindow = GLWindow.create( caps ) ; glWindow.addGLEventListener( new GearsES2() ) ; @@ -287,8 +292,9 @@ public class TestSWTBug643AsyncExec extends UITestCase { try { final Display d = dsc.display; while( !shallStop && !d.isDisposed() ) { - if( !d.readAndDispatch() ) { - dsc.display.sleep(); + if( !d.readAndDispatch() && !shallStop ) { + // blocks on linux .. dsc.display.sleep(); + Thread.sleep(10); } } } catch (Exception e0) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java index a5d2c8012..1822d2eaf 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java @@ -50,6 +50,7 @@ import org.junit.Test; import com.jogamp.nativewindow.swt.SWTAccessor; import com.jogamp.opengl.swt.GLCanvas; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.GLReadBufferUtil; @@ -58,10 +59,9 @@ import com.jogamp.opengl.util.texture.TextureIO; /** * Tests that a basic SWT app can open without crashing under different GL profiles. *- * Uses JOGL's new SWT GLCanvas. - *
- *- * Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used. + * Uses JOGL's new SWT GLCanvas, + * which allows utilizing custom GLCapability settings, + * independent from the already instantiated SWT visual. *
*
* Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/
@@ -188,6 +188,14 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase {
runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2() );
}
+ @Test
+ public void test_MultisampleAndAlpha() throws InterruptedException {
+ GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2());
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(2);
+ runTestAGL( caps, new MultisampleDemoES2(true) );
+ }
+
static int atoi(String a) {
int i=0;
try {
--
cgit v1.2.3
From b738983638703bb721ee4c9820c8ef43e2252e73 Mon Sep 17 00:00:00 2001
From: Sven Gothel
- * If the old or new context was current on this thread, it is being released before switching the drawable.
+ * The current context will be dis-associated from this auto-drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) setGLDrawable(null, true);} first.
+ *
+ * The new context will be associated with this auto-drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
+ *
+ * If the old or new context was current on this thread, it is being released before switching the association.
* The new context will be made current afterwards, if it was current before.
* However the user shall take extra care that no other thread
* attempts to make this context current.
*
- * Be aware that the old context is still bound to the drawable,
- * and that one context can only be bound to one drawable at one time!
- *
* In case you do not intend to use the old context anymore, i.e.
- * not assigning it to another drawable, it shall be
- * destroyed before setting the new context, i.e.:
+ * not assigning it to another drawable, it shall be
+ * destroyed, i.e.:
* drawable
yet,
+ * may be
might be an inner GLDrawable instance if using a delegation pattern,
- * or this GLAutoDrawable instance.
+ * Associate the new context, null
for lazy initialization
* @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
* @param ownDevice pass true
if {@link AbstractGraphicsDevice#close()} shall be issued,
* otherwise pass false
. Closing the device is required in case
@@ -78,9 +81,6 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAuto
if(null == drawable) {
throw new IllegalArgumentException("null drawable");
}
- if(null == context) {
- throw new IllegalArgumentException("null context");
- }
if(!drawable.isRealized()) {
throw new IllegalArgumentException("drawable not realized");
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
index cc81e4820..c03e4bfa4 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
@@ -27,17 +27,14 @@
*/
package com.jogamp.opengl.util;
-import java.util.ArrayList;
-import java.util.List;
-
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLRunnable;
import jogamp.opengl.Debug;
+import jogamp.opengl.GLEventListenerState;
/**
* Providing utility functions dealing w/ {@link GLDrawable}s, {@link GLAutoDrawable} and their {@link GLEventListener}.
@@ -83,7 +80,7 @@ public class GLDrawableUtil {
dest.addGLEventListener(listener);
if(preserveInitState && initialized) {
dest.setGLEventListenerInitState(listener, true);
- dest.invoke(false, new ReshapeGLEventListener(listener));
+ dest.invoke(false, new GLEventListenerState.ReshapeGLEventListener(listener));
} // else .. !init state is default
}
@@ -121,108 +118,13 @@ public class GLDrawableUtil {
* @param b
*/
public static final void swapGLContextAndAllGLEventListener(GLAutoDrawable a, GLAutoDrawable b) {
- final ListnewtCtx
, to this auto-drawable.
*
- GLContext oldCtx = glad.getContext();
+ GLContext oldCtx = glad.setContext(newCtx);
if(null != oldCtx) {
oldCtx.destroy();
}
- glad.setContext(newCtx);
*
- * This is required, since a context must have a valid drawable at all times
- * and this API shall not restrict the user in any way.
*
null
+ * @param newCtx the new context, maybe null
for dis-association.
+ * @return the previous GLContext, maybe null
*
* @see GLContext#setGLDrawable(GLDrawable, boolean)
* @see GLContext#setGLReadDrawable(GLDrawable)
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 455f2d70d..4817add4d 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -217,15 +217,20 @@ public abstract class GLContext {
/**
* Sets the read/write drawable for framebuffer operations.
* + * If the arguments reflect the current state of this context + * this method is a no-operation and returns the old and current {@link GLDrawable}. + *
+ ** If the context was current on this thread, it is being released before switching the drawable * and made current afterwards. However the user shall take extra care that not other thread * attempts to make this context current. Otherwise a race condition may happen. *
- * @param readWrite the read/write drawable for framebuffer operations. - * @param setWriteOnly iftrue
and if the current read-drawable differs
- * from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}),
- * only change the write-drawable. Otherwise set both drawables.
- * @return the replaced read/write drawable
+ * @param readWrite The read/write drawable for framebuffer operations, maybe null
to remove association.
+ * @param setWriteOnly Only change the write-drawable, if setWriteOnly
is true
and
+ * if the {@link #getGLReadDrawable() read-drawable} differs
+ * from the {@link #getGLDrawable() write-drawable}.
+ * Otherwise set both drawables, read and write.
+ * @return The previous read/write drawable
*
* @throws GLException in case null
is being passed or
* this context is made current on another thread.
@@ -239,6 +244,12 @@ public abstract class GLContext {
/**
* Returns the write-drawable this context uses for framebuffer operations.
+ * + * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)}, + * it equals to the write-drawable (default). + *
+ * @see #setGLDrawable(GLDrawable, boolean) + * @see #setGLReadDrawable(GLDrawable) */ public abstract GLDrawable getGLDrawable(); @@ -259,7 +270,7 @@ public abstract class GLContext { * * @param read the read-drawable for read framebuffer operations. * If null is passed, the default write drawable will be set. - * @return the replaced read-drawable + * @return the previous read-drawable * * @throws GLException in case a read drawable is not supported or * this context is made current on another thread. diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index eadd59559..c20197e72 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -74,8 +74,12 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking /** - * @param drawable upstream {@link GLDrawableImpl} instance, may be null for lazy initialization - * @param context upstream {@link GLContextImpl} instance, may be null for lazy initialization + * @param drawable upstream {@link GLDrawableImpl} instance, + * may benull
for lazy initialization
+ * @param context upstream {@link GLContextImpl} instance,
+ * may not have been made current (created) yet,
+ * may not be associated w/ drawable yet,
+ * may be null
for lazy initialization
* @param ownsDevice pass true
if {@link AbstractGraphicsDevice#close()} shall be issued,
* otherwise pass false
. Closing the device is required in case
* the drawable is created w/ it's own new instance, e.g. offscreen drawables,
@@ -85,6 +89,9 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
this.drawable = drawable;
this.context = context;
this.ownsDevice = ownsDevice;
+ if(null != context && null != drawable) {
+ context.setGLDrawable(drawable, false);
+ }
resetFPSCounter();
}
@@ -326,7 +333,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
final GLContext oldCtx = context;
final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
+ if(newCtxCurrent) { // implies null != newCtx
context.makeCurrent();
}
return oldCtx;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index f2c2cfada..2a2b6a8fd 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -203,8 +203,8 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly) {
- if(null==readWrite) {
- throw new GLException("Null read/write drawable not allowed");
+ if( drawable == readWrite && ( setWriteOnly || drawableRead == readWrite ) ) {
+ return drawable; // no change.
}
final boolean lockHeld = lock.isOwner(Thread.currentThread());
if(lockHeld) {
@@ -212,16 +212,20 @@ public abstract class GLContextImpl extends GLContext {
} else if(lock.isLockedByOtherThread()) { // still could glitch ..
throw new GLException("GLContext current by other thread ("+lock.getOwner()+"), operation not allowed.");
}
- if(!setWriteOnly || drawableRead==drawable) { // if !setWriteOnly || !explicitReadDrawable
+ if( !setWriteOnly || drawableRead == drawable ) { // if !setWriteOnly || !explicitReadDrawable
drawableRead = (GLDrawableImpl) readWrite;
}
final GLDrawableImpl old = drawable;
- old.associateContext(this, false);
- drawableRetargeted = null != drawable;
+ if( null != old ) {
+ old.associateContext(this, false);
+ }
+ drawableRetargeted |= null != drawable && readWrite != drawable;
drawable = (GLDrawableImpl) readWrite ;
- drawable.associateContext(this, true);
- if(lockHeld) {
- makeCurrent();
+ if( null != drawable ) {
+ drawable.associateContext(this, true);
+ if( lockHeld ) {
+ makeCurrent();
+ }
}
return old;
}
@@ -334,7 +338,7 @@ public abstract class GLContextImpl extends GLContext {
", surf "+toHexString(drawable.getHandle())+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
if (contextHandle != 0) {
- int lockRes = drawable.lockSurface();
+ final int lockRes = drawable.lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
// this would be odd ..
throw new GLException("Surface not ready to lock: "+drawable);
@@ -408,7 +412,7 @@ public abstract class GLContextImpl extends GLContext {
throw new GLException("Destination OpenGL context has not been created");
}
- int lockRes = drawable.lockSurface();
+ final int lockRes = drawable.lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
// this would be odd ..
throw new GLException("Surface not ready to lock");
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index f8c58ee34..5d113ff83 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -131,30 +131,36 @@ public class GLDrawableHelper {
}
/**
- * Associate a new context to the drawable and also propagates the context/drawable switch by
- * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
- *
- * If the old or new context was current on this thread, it is being released before switching the drawable.
+ * Switch {@link GLContext} / {@link GLDrawable} association.
+ *
+ * Dis-associate oldCtx
from drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) oldCtx.setGLDrawable(null, true);}.
*
*
- * Be aware that the old context is still bound to the drawable,
- * and that one context can only bound to one drawable at one time!
+ * Re-associate newCtx
with drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
+ *
+ *
+ * If the old or new context was current on this thread, it is being released before switching the drawable.
*
*
* No locking is being performed on the drawable, caller is required to take care of it.
*
*
* @param drawable the drawable which context is changed
- * @param oldCtx the old context
- * @param newCtx the new context
+ * @param oldCtx the old context, maybe null
.
+ * @param newCtx the new context, maybe null
for dis-association.
* @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)}
* @return true if the new context was current, otherwise false
*
* @see GLAutoDrawable#setContext(GLContext)
*/
public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) {
- if( null != oldCtx && oldCtx.isCurrent() ) {
- oldCtx.release();
+ if( null != oldCtx ) {
+ if( oldCtx.isCurrent() ) {
+ oldCtx.release();
+ }
+ oldCtx.setGLDrawable(null, true); // dis-associate old pair
}
final boolean newCtxCurrent;
if(null!=newCtx) {
@@ -163,8 +169,8 @@ public class GLDrawableHelper {
newCtx.release();
}
newCtx.setContextCreationFlags(newCtxCreationFlags);
- newCtx.setGLDrawable(drawable, true); // propagate context/drawable switch
- } else {
+ newCtx.setGLDrawable(drawable, true); // re-associate new pair
+ } else {
newCtxCurrent = false;
}
return newCtxCurrent;
@@ -203,6 +209,7 @@ public class GLDrawableHelper {
}
context.getGL().glFinish();
context.release();
+ context.setGLDrawable(null, true); // dis-associate
}
if(null != proxySurface) {
diff --git a/src/jogl/classes/jogamp/opengl/GLEventListenerState.java b/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
new file mode 100644
index 000000000..dea2bc85b
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
@@ -0,0 +1,267 @@
+/**
+ * Copyright 2013 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.opengl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLRunnable;
+
+import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+
+/**
+ * GLEventListenerState is holding {@link GLAutoDrawable} components crucial
+ * to relocating all its {@link GLEventListener} w/ their operating {@link GLContext}, etc.
+ * The components are:
+ *
+ * - {@link AbstractGraphicsScreen}
+ * - {@link GLCapabilitiesImmutable}
+ * - {@link GLContext} operating all {@link GLEventListener}
+ * - All {@link GLEventListener}
+ * - All {@link GLEventListener}'s init state
+ * - {@link GLAnimatorControl}
+ *
+ *
+ * A GLEventListenerState instance can be created while components are {@link #moveFrom(GLAutoDrawable) moved from} a {@link GLAutoDrawable}
+ * to the new instance, which gains {@link #isOwner() ownership} of the moved components.
+ *
+ *
+ * A GLEventListenerState instance's components can be {@link #moveTo(GLAutoDrawable) moved to} a {@link GLAutoDrawable},
+ * while loosing {@link #isOwner() ownership} of the moved components.
+ *
+ *
+ */
+public class GLEventListenerState {
+ private GLEventListenerState(AbstractGraphicsScreen screen, GLCapabilitiesImmutable caps, GLContext context, int count, GLAnimatorControl anim) {
+ this.screen = screen;
+ this.caps = caps;
+ this.context = context;
+ this.listeners = new GLEventListener[count];
+ this.listenersInit = new boolean[count];
+ this.anim = anim;
+ this.owner = true;
+ }
+ /**
+ * Returns true
, if this instance is the current owner of the components,
+ * otherwise false
.
+ *
+ * Ownership is lost if {@link #moveTo(GLAutoDrawable)} is being called successfully
+ * and all components are transferred to the new {@link GLAutoDrawable}.
+ *
+ */
+ public final boolean isOwner() { return owner; }
+
+ public final int listenerCount() { return listeners.length; }
+
+ public final AbstractGraphicsScreen screen;
+ public final GLCapabilitiesImmutable caps;
+ public final GLContext context;
+ public final GLEventListener[] listeners;
+ public final boolean[] listenersInit;
+ public final GLAnimatorControl anim;
+
+ private boolean owner;
+
+ /**
+ * Last resort to destroy and loose ownership
+ */
+ public void destroy() {
+ if( owner ) {
+ final int aSz = listenerCount();
+ for(int i=0; i
+ * Note that all components are removed from the {@link GLAutoDrawable},
+ * i.e. the {@link GLContext}, all {@link GLEventListener}.
+ *
+ *
+ * If the {@link GLAutoDrawable} was added to a {@link GLAnimatorControl}, it is removed
+ * and the {@link GLAnimatorControl} added to the GLEventListenerState.
+ *
+ *
+ * The returned GLEventListenerState instance is the {@link #isOwner() owner of the components}.
+ *
+ *
+ * @param a {@link GLAutoDrawable} source to move components from
+ * @return new GLEventListenerState instance {@link #isOwner() owning} moved components.
+ *
+ * @see #moveTo(GLAutoDrawable)
+ */
+ public static GLEventListenerState moveFrom(GLAutoDrawable a) {
+ final int aSz = a.getGLEventListenerCount();
+
+ // Create new AbstractGraphicsScreen w/ cloned AbstractGraphicsDevice for future GLAutoDrawable
+ // allowing this AbstractGraphicsDevice to loose ownership -> not closing display/device!
+ final AbstractGraphicsConfiguration aCfg1 = a.getNativeSurface().getGraphicsConfiguration();
+ final GLCapabilitiesImmutable caps1 = (GLCapabilitiesImmutable) aCfg1.getChosenCapabilities();
+ final AbstractGraphicsScreen aScreen1 = aCfg1.getScreen();
+ final AbstractGraphicsDevice aDevice1 = aScreen1.getDevice();
+ final AbstractGraphicsDevice aDevice2 = (AbstractGraphicsDevice) aDevice1.clone();
+ final AbstractGraphicsScreen aScreen2 = NativeWindowFactory.createScreen( NativeWindowFactory.getNativeWindowType(false), aDevice2, aScreen1.getIndex() );
+
+ final GLAnimatorControl aAnim = a.getAnimator();
+ if( null != aAnim ) {
+ aAnim.remove(a); // also handles ECT
+ }
+
+ final GLEventListenerState glls = new GLEventListenerState(aScreen2, caps1, a.getContext(), aSz, aAnim);
+
+ //
+ // remove and cache all GLEventListener and their init-state
+ //
+ for(int i=0; i
+ * If the previous {@link GLAutoDrawable} was removed from a {@link GLAnimatorControl} by previous {@link #moveFrom(GLAutoDrawable)},
+ * the given {@link GLAutoDrawable} is added to the cached {@link GLAnimatorControl}.
+ * This operation is skipped, if the given {@link GLAutoDrawable} is already added to a {@link GLAnimatorControl} instance.
+ *
+ *
+ * Note: After this operation, the GLEventListenerState reference should be released.
+ *
+ *
+ * @param a {@link GLAutoDrawable} destination to move GLEventListenerState components to
+ *
+ * @throws GLException if the {@link GLAutoDrawable}'s configuration is incompatible, i.e. different {@link GLCapabilitiesImmutable}.
+ *
+ * @see #moveFrom(GLAutoDrawable)
+ * @see #isOwner()
+ */
+ public final void moveTo(GLAutoDrawable a) {
+ final List aGLCmds = new ArrayList();
+ final int aSz = listenerCount();
+
+ final MutableGraphicsConfiguration aCfg = (MutableGraphicsConfiguration) a.getNativeSurface().getGraphicsConfiguration();
+ final GLCapabilitiesImmutable aCaps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities();
+ if( caps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) != aCaps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) ) {
+ throw new GLException("XXX: Incompatible - Prev Holder: "+caps+", New Holder "+caps);
+ }
+ final GLContext prevContext = a.getContext();
+ if( null != prevContext) {
+ prevContext.destroy();
+ }
+ final AbstractGraphicsScreen preScreen = aCfg.getScreen();
+ aCfg.setScreen( screen );
+ preScreen.getDevice().close();
+ a.setContext( context );
+ owner = false;
+
+ //
+ // Trigger GL-Viewport reset and reshape of all initialized GLEventListeners
+ //
+ aGLCmds.add(setViewport);
+ for(int i=0; i= 0 is specific screen
* @return
- * @throws UnsupportedOperationException
*/
- public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) throws UnsupportedOperationException {
- if( isX11 ) {
- X11GraphicsDevice x11Device = (X11GraphicsDevice)device;
- if(0 > screen) {
- screen = x11Device.getDefaultScreen();
- }
- return new X11GraphicsScreen(x11Device, screen);
- }
- if(0 > screen) {
- screen = 0; // FIXME: Needs native API utilization
- }
- if( isWindows || isOSX ) {
- return new DefaultGraphicsScreen(device, screen);
- }
- throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
+ public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) {
+ return NativeWindowFactory.createScreen(nwt, device, screen);
}
public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) {
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
index 0f28ca67c..da3b31de4 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
@@ -45,7 +45,7 @@ import javax.media.nativewindow.ToolkitLock;
*/
public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
- final boolean handleOwner;
+ /* final */ boolean handleOwner;
final boolean isXineramaEnabled;
/** Constructs a new X11GraphicsDevice corresponding to the given connection and default
@@ -153,5 +153,13 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
}
return super.close();
}
+
+ @Override
+ public boolean isHandleOwner() {
+ return handleOwner;
+ }
+ @Override
+ public void clearHandleOwner() {
+ handleOwner = false;
+ }
}
-
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
index ebdaf2fbb..4e45113d4 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
@@ -42,8 +42,9 @@ package javax.media.nativewindow;
/** A marker interface describing a graphics configuration, visual, or
pixel format in a toolkit-independent manner. */
-
public interface AbstractGraphicsConfiguration extends VisualIDHolder, Cloneable {
+ public Object clone();
+
/**
* Return the screen this graphics configuration is valid for
*/
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
index 8ecd5242d..585cd1f09 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
@@ -45,7 +45,6 @@ import jogamp.nativewindow.Debug;
/** A interface describing a graphics device in a
toolkit-independent manner.
*/
-
public interface AbstractGraphicsDevice extends Cloneable {
public static final boolean DEBUG = Debug.debug("GraphicsDevice");
@@ -58,6 +57,8 @@ public interface AbstractGraphicsDevice extends Cloneable {
/** Default unit id for the 1st device: 0 */
public static int DEFAULT_UNIT = 0;
+ public Object clone();
+
/**
* Returns the type of the underlying subsystem, ie
* NativeWindowFactory.TYPE_KD, NativeWindowFactory.TYPE_X11, ..
@@ -143,10 +144,17 @@ public interface AbstractGraphicsDevice extends Cloneable {
*
* Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
* or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
- * issue the native close operation or skip it depending on the handles's ownership.
+ * issue the native close operation or skip it depending on the {@link #isHandleOwner() handles's ownership}.
*
*
* @return true if the handle was not null
and closing was successful, otherwise false.
*/
public boolean close();
+
+ /**
+ * @return true
if instance owns the handle to issue {@link #close()}, otherwise false
.
+ */
+ public boolean isHandleOwner();
+
+ public void clearHandleOwner();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
index eb2cc9120..acb98073b 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
@@ -44,6 +44,8 @@ package javax.media.nativewindow;
*/
public interface AbstractGraphicsScreen extends Cloneable {
+ public Object clone();
+
/**
* Return the device this graphics configuration is valid for
*/
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
index a33c3792a..6b23172e1 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
@@ -93,25 +93,26 @@ public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphics
/**
* Set the capabilities to a new value.
*
+ *
* The use case for setting the Capabilities at a later time is
- * a change of the graphics device in a multi-screen environment.
- *
+ * a change or re-validation of capabilities.
+ *
* @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
*/
protected void setChosenCapabilities(CapabilitiesImmutable capsChosen) {
- capabilitiesChosen = capsChosen;
+ this.capabilitiesChosen = capsChosen;
}
/**
* Set a new screen.
*
+ *
* the use case for setting a new screen at a later time is
- * a change of the graphics device in a multi-screen environment.
- *
- * A copy of the passed object is being used.
+ * a change of the graphics device in a multi-screen environment.
+ *
*/
- final protected void setScreen(DefaultGraphicsScreen screen) {
- this.screen = (AbstractGraphicsScreen) screen.clone();
+ protected void setScreen(AbstractGraphicsScreen screen) {
+ this.screen = screen;
}
@Override
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 9288652d9..b3ae4628c 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -37,10 +37,10 @@ import jogamp.nativewindow.NativeWindowFactoryImpl;
public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice {
private static final String separator = "_";
- private String type;
- protected String connection;
- protected int unitID;
- protected String uniqueID;
+ private final String type;
+ protected final String connection;
+ protected final int unitID;
+ protected final String uniqueID;
protected long handle;
protected ToolkitLock toolkitLock;
@@ -170,9 +170,18 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
return false;
}
+ @Override
+ public boolean isHandleOwner() {
+ return false;
+ }
+
+ @Override
+ public void clearHandleOwner() {
+ }
+
@Override
public String toString() {
- return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", "+toolkitLock+"]";
+ return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", owner "+isHandleOwner()+", "+toolkitLock+"]";
}
/**
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
index f50bd0e14..9fa58c7a3 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
@@ -33,8 +33,8 @@
package javax.media.nativewindow;
public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen {
- AbstractGraphicsDevice device;
- private int idx;
+ private final AbstractGraphicsDevice device;
+ private final int idx;
public DefaultGraphicsScreen(AbstractGraphicsDevice device, int idx) {
this.device = device;
@@ -57,7 +57,7 @@ public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen
public AbstractGraphicsDevice getDevice() {
return device;
}
-
+
public int getIndex() {
return idx;
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index d7f28a986..07702c762 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -48,6 +48,10 @@ import jogamp.nativewindow.ResourceToolkitLock;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
+import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
/** Provides a pluggable mechanism for arbitrary window toolkits to
adapt their components to the {@link NativeWindow} interface,
@@ -428,6 +432,29 @@ public abstract class NativeWindowFactory {
return NativeWindowFactoryImpl.getNullToolkitLock();
}
+ /**
+ * @param device
+ * @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen
+ * @return newly created AbstractGraphicsScreen of given native type
+ */
+ public static AbstractGraphicsScreen createScreen(String type, AbstractGraphicsDevice device, int screen) {
+ if( TYPE_X11 == type ) {
+ final X11GraphicsDevice x11Device = (X11GraphicsDevice)device;
+ if(0 > screen) {
+ screen = x11Device.getDefaultScreen();
+ }
+ return new X11GraphicsScreen(x11Device, screen);
+ }
+ if(0 > screen) {
+ screen = 0; // FIXME: Needs native API utilization
+ }
+ if( TYPE_AWT == type ) {
+ final AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) device;
+ return new AWTGraphicsScreen(awtDevice);
+ }
+ return new DefaultGraphicsScreen(device, screen);
+ }
+
/** Returns the appropriate NativeWindowFactory to handle window
objects of the given type. The windowClass might be {@link
NativeWindow NativeWindow}, in which case the client has
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index a8d45f288..017c52df2 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -180,7 +180,7 @@ static int errorHandlerThrowException = 0;
static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
{
- if(!errorHandlerQuiet) {
+ if( !errorHandlerQuiet || errorHandlerDebug ) {
const char * errnoStr = strerror(errno);
char errCodeStr[80];
char reqCodeStr[80];
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index 96d0f6e3b..7fccb6622 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -458,24 +458,22 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
} else {
t0 = 0;
}
-
- /* if (nativeWindowCreated && null != context) {
- throw new GLException("InternalError: Native Windows has been just created, but context wasn't destroyed (is not null)");
- } */
- if (null == context && visible && 0 != window.getWindowHandle() && 0 ctx1/draw2, ctx2/draw1.
+ */
+public class TestGLContextDrawableSwitch01NEWT extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ glp = GLProfile.getGL2ES2();
+ caps = new GLCapabilities(glp);
+ width = 256;
+ height = 256;
+ }
+
+ private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
+ final Window window = NewtFactory.createWindow(caps);
+ Assert.assertNotNull(window);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable drawable = factory.createGLDrawable(window);
+ Assert.assertNotNull(drawable);
+
+ drawable.setRealized(true);
+ Assert.assertTrue(drawable.isRealized());
+
+ final GLContext context = drawable.createContext(null);
+ Assert.assertNotNull(context);
+
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock();
+ window.destroy(); // destroys the actual window
+ }
+ };
+
+ // add basic window interaction
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) {
+ glad.windowRepaintOp();
+ }
+ @Override
+ public void windowResized(WindowEvent e) {
+ glad.windowResizedOp(window.getWidth(), window.getHeight());
+ }
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ glad.windowDestroyNotifyOp();
+ }
+ });
+ window.addWindowListener(wl);
+
+ return glad;
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2WindowSingleContext() throws InterruptedException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
+ GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+
+ // create single context using glad1 and assign it to glad1,
+ // destroy the prev. context afterwards.
+ {
+ final GLContext newCtx = glad1.createContext(null);
+ Assert.assertNotNull(newCtx);
+ final GLContext oldCtx = glad1.setContext(newCtx);
+ Assert.assertNotNull(oldCtx);
+ oldCtx.destroy();
+ final int res = newCtx.makeCurrent();
+ Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
+ newCtx.release();
+ }
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ GearsES2 gears = new GearsES2(1);
+ glad1.addGLEventListener(gears);
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Animator animator = new Animator();
+ animator.add(glad1);
+ animator.add(glad2);
+ animator.start();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+
+ // switch context _and_ the demo synchronously
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2);
+
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ glad1.destroy();
+ glad2.destroy();
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowOneDemo() throws InterruptedException {
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GearsES2 gears = new GearsES2(1);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ GLWindow glWindow1 = GLWindow.create(caps);
+ glWindow1.setTitle("win1");
+ glWindow1.setSize(width, height);
+ glWindow1.setPosition(64, 64);
+ glWindow1.addGLEventListener(0, gears);
+ glWindow1.addGLEventListener(snapshotGLEventListener);
+ glWindow1.addWindowListener(quitAdapter);
+
+ GLWindow glWindow2 = GLWindow.create(caps);
+ glWindow2.setTitle("win2");
+ glWindow2.setSize(width+100, height+100);
+ glWindow2.setPosition(2*64+width, 64);
+ glWindow2.addWindowListener(quitAdapter);
+
+ Animator animator = new Animator();
+ animator.add(glWindow1);
+ animator.add(glWindow2);
+ animator.start();
+
+ glWindow1.setVisible(true);
+ glWindow2.setVisible(true);
+
+ snapshotGLEventListener.setMakeSnapshot();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+ System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+
+ // switch context _and_ the demo synchronously
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
+
+ System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+
+ snapshotGLEventListener.setMakeSnapshot();
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ glWindow1.destroy();
+ glWindow2.destroy();
+
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowEachWithOwnDemo() throws InterruptedException {
+ final GearsES2 gears = new GearsES2(1);
+ final RedSquareES2 rsquare = new RedSquareES2(1);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ final SnapshotGLEventListener snapshotGLEventListener1 = new SnapshotGLEventListener();
+ final SnapshotGLEventListener snapshotGLEventListener2 = new SnapshotGLEventListener();
+
+ GLWindow glWindow1 = GLWindow.create(caps);
+ glWindow1.setTitle("win1");
+ glWindow1.setSize(width, height);
+ glWindow1.setPosition(64, 64);
+ glWindow1.addGLEventListener(0, gears);
+ glWindow1.addGLEventListener(snapshotGLEventListener1);
+ glWindow1.addWindowListener(quitAdapter);
+
+ GLWindow glWindow2 = GLWindow.create(caps);
+ glWindow2.setTitle("win2");
+ glWindow2.setSize(width+100, height+100);
+ glWindow2.setPosition(2*64+width, 64);
+ glWindow2.addGLEventListener(0, rsquare);
+ glWindow2.addGLEventListener(snapshotGLEventListener2);
+ glWindow2.addWindowListener(quitAdapter);
+
+ Animator animator = new Animator();
+ animator.add(glWindow1);
+ animator.add(glWindow2);
+ animator.start();
+
+ glWindow1.setVisible(true);
+ glWindow2.setVisible(true);
+
+ snapshotGLEventListener1.setMakeSnapshot();
+ snapshotGLEventListener2.setMakeSnapshot();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+ System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
+ System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+ snapshotGLEventListener1.setMakeSnapshot();
+ snapshotGLEventListener2.setMakeSnapshot();
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ // System.err.println("pre -del-w1: w1: "+glWindow1);
+ // System.err.println("pre -del-w1: w2: "+glWindow2);
+ glWindow1.destroy();
+ // System.err.println("post-del-w1: w1: "+glWindow1);
+ // System.err.println("post-del-w1: w2: "+glWindow2);
+ glWindow2.destroy();
+
+ }
+
+ // default timing for 2 switches
+ static long duration = 2200; // ms
+ static long period = 1000; // ms
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ *
+ */
+public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ glp = GLProfile.getGL2ES2();
+ caps = new GLCapabilities(glp);
+ width = 256;
+ height = 256;
+ }
+
+ private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
+ final Window window = NewtFactory.createWindow(caps);
+ Assert.assertNotNull(window);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable drawable = factory.createGLDrawable(window);
+ Assert.assertNotNull(drawable);
+
+ drawable.setRealized(true);
+ Assert.assertTrue(drawable.isRealized());
+
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock();
+ window.destroy(); // destroys the actual window
+ }
+ };
+
+ // add basic window interaction
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) {
+ glad.windowRepaintOp();
+ }
+ @Override
+ public void windowResized(WindowEvent e) {
+ glad.windowResizedOp(window.getWidth(), window.getHeight());
+ }
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ glad.windowDestroyNotifyOp();
+ }
+ });
+ window.addWindowListener(wl);
+
+ return glad;
+ }
+
+ @Test(timeout=30000)
+ public void test01() throws InterruptedException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ final GLEventListenerCounter glelCounter = new GLEventListenerCounter();
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final long t0 = System.currentTimeMillis();
+ final GLEventListenerState glls1;
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ final GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
+ final GLContext context1 = glad1.createContext(null);
+ glad1.setContext(context1);
+ animator.add(glad1);
+
+ glad1.addGLEventListener(glelCounter);
+ glad1.addGLEventListener(new GearsES2(1));
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/2 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ // - dis-associate context from glad1
+ // - destroy glad1
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(context1, glad1.getContext());
+ Assert.assertEquals(3, glad1.getGLEventListenerCount());
+ Assert.assertEquals(context1.getGLReadDrawable(), glad1.getDelegatedDrawable());
+ Assert.assertEquals(context1.getGLDrawable(), glad1.getDelegatedDrawable());
+
+ glls1 = GLEventListenerState.moveFrom(glad1);
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(context1, glls1.context);
+ Assert.assertNull(context1.getGLReadDrawable());
+ Assert.assertNull(context1.getGLDrawable());
+ Assert.assertEquals(3, glls1.listenerCount());
+ Assert.assertEquals(true, glls1.isOwner());
+ Assert.assertEquals(null, glad1.getContext());
+ Assert.assertEquals(0, glad1.getGLEventListenerCount());
+
+ glad1.destroy();
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ final GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Assert.assertEquals(null, glad2.getContext());
+ Assert.assertEquals(0, glad2.getGLEventListenerCount());
+
+ glls1.moveTo(glad2);
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(glls1.context, glad2.getContext());
+ Assert.assertEquals(3, glad2.getGLEventListenerCount());
+ Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(false, glls1.isOwner());
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/1 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ glad2.destroy();
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(1, glelCounter.disposeCount);
+ }
+ animator.stop();
+ }
+
+ @Test(timeout=30000)
+ public void test02() throws InterruptedException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final long t0 = System.currentTimeMillis();
+ final GLEventListenerState glls1;
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ final GLWindow glad1 = GLWindow.create(caps);
+ glad1.setSize(width, height);
+ glad1.setPosition(64, 64);
+ glad1.addWindowListener(quitAdapter);
+ glad1.setVisible(true);
+ animator.add(glad1);
+
+ glad1.addGLEventListener(glelTracker);
+ glad1.addGLEventListener(new GearsES2(1));
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/2 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ // - dis-associate context from glad1
+ // - destroy glad1
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(3, glad1.getGLEventListenerCount());
+ Assert.assertEquals(glad1.getContext().getGLReadDrawable(), glad1.getDelegatedDrawable());
+ Assert.assertEquals(glad1.getContext().getGLDrawable(), glad1.getDelegatedDrawable());
+
+ final GLContext context1 = glad1.getContext();
+ glls1 = GLEventListenerState.moveFrom(glad1);
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(context1, glls1.context);
+ Assert.assertNull(context1.getGLReadDrawable());
+ Assert.assertNull(context1.getGLDrawable());
+ Assert.assertEquals(3, glls1.listenerCount());
+ Assert.assertEquals(true, glls1.isOwner());
+ Assert.assertEquals(null, glad1.getContext());
+ Assert.assertEquals(0, glad1.getGLEventListenerCount());
+
+ glad1.destroy();
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ final GLWindow glad2 = GLWindow.create(caps);
+ glad2.setSize(width+100, height+100);
+ glad2.setPosition(2*64+width, 64);
+ glad2.addWindowListener(quitAdapter);
+ glad2.setVisible(true);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Assert.assertNotNull(glad2.getContext());
+ Assert.assertEquals(0, glad2.getGLEventListenerCount());
+
+ glls1.moveTo(glad2);
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(glls1.context, glad2.getContext());
+ Assert.assertEquals(3, glad2.getGLEventListenerCount());
+ Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(false, glls1.isOwner());
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/1 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ glad2.destroy();
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(1, glelTracker.disposeCount);
+ }
+ animator.stop();
+ }
+
+ // default timing for 2 switches
+ static long duration = 2200; // ms
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
-
- // switch context _and_ the demo synchronously
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2);
-
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- glad1.destroy();
- glad2.destroy();
- }
-
- @Test(timeout=30000)
- public void testSwitch2GLWindowOneDemo() throws InterruptedException {
- GearsES2 gears = new GearsES2(1);
- final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLWindow glWindow1 = GLWindow.create(caps);
- glWindow1.setTitle("win1");
- glWindow1.setSize(width, height);
- glWindow1.setPosition(64, 64);
- glWindow1.addGLEventListener(0, gears);
- glWindow1.addWindowListener(quitAdapter);
-
- GLWindow glWindow2 = GLWindow.create(caps);
- glWindow2.setTitle("win2");
- glWindow2.setSize(width+100, height+100);
- glWindow2.setPosition(2*64+width, 64);
- glWindow2.addWindowListener(quitAdapter);
-
- Animator animator = new Animator();
- animator.add(glWindow1);
- animator.add(glWindow2);
- animator.start();
-
- glWindow1.setVisible(true);
- glWindow2.setVisible(true);
-
- int s = 0;
- long t0 = System.currentTimeMillis();
- long t1 = t0;
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
- if( ( t1 - t0 ) / period > s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
-
- // switch context _and_ the demo synchronously
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
-
- System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- glWindow1.destroy();
- glWindow2.destroy();
-
- }
-
- @Test(timeout=30000)
- public void testSwitch2GLWindowEachWithOwnDemo() throws InterruptedException {
- GearsES2 gears = new GearsES2(1);
- RedSquareES2 rsquare = new RedSquareES2(1);
- final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLWindow glWindow1 = GLWindow.create(caps);
- glWindow1.setTitle("win1");
- glWindow1.setSize(width, height);
- glWindow1.setPosition(64, 64);
- glWindow1.addGLEventListener(0, gears);
- glWindow1.addWindowListener(quitAdapter);
-
- GLWindow glWindow2 = GLWindow.create(caps);
- glWindow2.setTitle("win2");
- glWindow2.setSize(width+100, height+100);
- glWindow2.setPosition(2*64+width, 64);
- glWindow2.addGLEventListener(0, rsquare);
- glWindow2.addWindowListener(quitAdapter);
-
- Animator animator = new Animator();
- animator.add(glWindow1);
- animator.add(glWindow2);
- animator.start();
-
- glWindow1.setVisible(true);
- glWindow2.setVisible(true);
-
- int s = 0;
- long t0 = System.currentTimeMillis();
- long t1 = t0;
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
- if( ( t1 - t0 ) / period > s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
- System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- // System.err.println("pre -del-w1: w1: "+glWindow1);
- // System.err.println("pre -del-w1: w2: "+glWindow2);
- glWindow1.destroy();
- // System.err.println("post-del-w1: w1: "+glWindow1);
- // System.err.println("post-del-w1: w2: "+glWindow2);
- glWindow2.destroy();
-
- }
-
- // default timing for 2 switches
- static long duration = 2200; // ms
- static long period = 1000; // ms
-
- public static void main(String args[]) throws IOException {
- for(int i=0; i
Date: Mon, 18 Mar 2013 08:16:25 +0100
Subject: NativeWindow OSXUtil RunOnMainThread: Use daemon attachment and do
not detach; Add RunLater0(..)
---
src/nativewindow/native/NativewindowCommon.c | 9 +++-
src/nativewindow/native/NativewindowCommon.h | 2 +-
src/nativewindow/native/macosx/OSXmisc.m | 65 ++++++++++++++++++----------
src/nativewindow/native/x11/Xmisc.c | 4 +-
4 files changed, 53 insertions(+), 27 deletions(-)
(limited to 'src/nativewindow/native/x11')
diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c
index d2fdd5d69..e909c0494 100644
--- a/src/nativewindow/native/NativewindowCommon.c
+++ b/src/nativewindow/native/NativewindowCommon.c
@@ -74,7 +74,7 @@ jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
return strChars;
}
-JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached) {
+JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) {
JNIEnv* curEnv = NULL;
JNIEnv* newEnv = NULL;
int envRes;
@@ -83,7 +83,12 @@ JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int *
envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
if( JNI_EDETACHED == envRes ) {
// detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) {
+ if( asDaemon ) {
+ envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL);
+ } else {
+ envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL);
+ }
+ if( JNI_OK != envRes ) {
fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
return NULL;
}
diff --git a/src/nativewindow/native/NativewindowCommon.h b/src/nativewindow/native/NativewindowCommon.h
index 73b890c4f..a2975f3fd 100644
--- a/src/nativewindow/native/NativewindowCommon.h
+++ b/src/nativewindow/native/NativewindowCommon.h
@@ -13,6 +13,6 @@ jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...);
void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
-JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached);
+JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached);
#endif
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index 81dcfa959..5d292d76e 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -689,7 +689,7 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns
- (void) jRun
{
int shallBeDetached = 0;
- JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached);
DBG_PRINT2("MainRunnable.1 env: %d\n", (int)(NULL!=env));
if(NULL!=env) {
DBG_PRINT2("MainRunnable.1.0\n");
@@ -699,7 +699,8 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns
if (shallBeDetached) {
DBG_PRINT2("MainRunnable.1.3\n");
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ // Keep attached on main thread !
+ // (*jvmHandle)->DetachCurrentThread(jvmHandle);
}
}
DBG_PRINT2("MainRunnable.X\n");
@@ -733,21 +734,12 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns
@end
-
-/*
- * Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: RunOnMainThread0
- * Signature: (ZLjava/lang/Runnable;)V
- */
-JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0
- (JNIEnv *env, jclass unused, jobject runnable)
+static void RunOnThread (JNIEnv *env, jobject runnable, BOOL onMain, jint delayInMS)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
- DBG_PRINT2( "RunOnMainThread0: isMainThread %d, NSApp %d, NSApp-isRunning %d\n",
- (int)([NSThread isMainThread]), (int)(NULL!=NSApp), (int)([NSApp isRunning]));
+ DBG_PRINT2( "RunOnThread0: isMainThread %d, NSApp %d, NSApp-isRunning %d, onMain %d, delay %dms\n",
+ (int)([NSThread isMainThread]), (int)(NULL!=NSApp), (int)([NSApp isRunning]), (int)onMain, (int)delayInMS);
- if ( NO == [NSThread isMainThread] ) {
+ if ( !onMain || NO == [NSThread isMainThread] ) {
jobject runnableObj = (*env)->NewGlobalRef(env, runnable);
JavaVM *jvmHandle = NULL;
@@ -759,27 +751,56 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0
jvmVersion = (*env)->GetVersion(env);
}
- DBG_PRINT2( "RunOnMainThread0.1.0\n");
+ DBG_PRINT2( "RunOnThread.1.0\n");
MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj jvmHandle: jvmHandle jvmVersion: jvmVersion];
- [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO];
- DBG_PRINT2( "RunOnMainThread0.1.1\n");
+ if( onMain ) {
+ [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO];
+ } else {
+ NSTimeInterval delay = (double)delayInMS/1000.0;
+ [mr performSelector:@selector(jRun) withObject:nil afterDelay:delay];
+ }
+ DBG_PRINT2( "RunOnThread.1.1\n");
[mr release];
- DBG_PRINT2( "RunOnMainThread0.1.2\n");
+ DBG_PRINT2( "RunOnThread.1.2\n");
} else {
- DBG_PRINT2( "RunOnMainThread0.2\n");
+ DBG_PRINT2( "RunOnThread.2\n");
(*env)->CallVoidMethod(env, runnable, runnableRunID);
}
- DBG_PRINT2( "RunOnMainThread0.X\n");
+ DBG_PRINT2( "RunOnThread.X\n");
+}
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: RunOnMainThread0
+ * Signature: (ZLjava/lang/Runnable;)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunOnMainThread0
+ (JNIEnv *env, jclass unused, jobject runnable)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ RunOnThread (env, runnable, YES, 0);
[pool release];
}
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
- * Method: RunOnMainThread0
+ * Method: RunLater0
+ * Signature: (ZLjava/lang/Runnable;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_RunLater0
+ (JNIEnv *env, jclass unused, jobject runnable, jint delay)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ RunOnThread (env, runnable, NO, delay);
+ [pool release];
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: IsMainThread0
* Signature: (V)V
*/
JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_IsMainThread0
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 017c52df2..77e6ea978 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -197,7 +197,7 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
fflush(stderr);
if( NULL != jvmHandle && ( errorHandlerDebug || errorHandlerThrowException ) ) {
- jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached);
if(NULL == jniEnv) {
fprintf(stderr, "Nativewindow X11 Error: null JNIEnv");
fflush(stderr);
@@ -262,7 +262,7 @@ static int x11IOErrorHandler(Display *dpy)
fflush(stderr);
if( NULL != jvmHandle ) {
- jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached);
if (NULL != jniEnv) {
NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr);
if (shallBeDetached) {
--
cgit v1.2.3
From 8b70108d6fd04b2ab97cbd1b6729361b5ce98a6b Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Wed, 24 Apr 2013 18:48:14 +0200
Subject: X11 Error Handler: Start quiet; Init: quite = !debug; Internal calls:
Pass through errorHandlerQuiet state.
---
src/nativewindow/native/x11/Xmisc.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
(limited to 'src/nativewindow/native/x11')
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 77e6ea978..69f0c0746 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -174,7 +174,7 @@ static void setupJVMVars(JNIEnv * env) {
}
static XErrorHandler origErrorHandler = NULL ;
-static int errorHandlerQuiet = 0 ;
+static int errorHandlerQuiet = 1 ;
static int errorHandlerDebug = 0 ;
static int errorHandlerThrowException = 0;
@@ -300,7 +300,7 @@ Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboo
_initClazzAccess(env);
x11IOErrorHandlerEnable(1, env);
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 1, 0, 0 /* no dpy, force, no sync */);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, 1, debug ? 0 : 1, 0 /* no dpy, force, no sync */);
_initialized=1;
if(JNI_TRUE == debug) {
fprintf(stderr, "Info: NativeWindow native init passed\n");
@@ -311,7 +311,7 @@ Java_jogamp_nativewindow_x11_X11Util_initialize0(JNIEnv *env, jclass clazz, jboo
JNIEXPORT void JNICALL
Java_jogamp_nativewindow_x11_X11Util_shutdown0(JNIEnv *env, jclass _unused) {
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0, 0 /* no dpy, no sync */);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, errorHandlerQuiet, 0 /* no dpy, no sync */);
x11IOErrorHandlerEnable(0, env);
}
@@ -342,9 +342,9 @@ Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Lja
if (arg3 != NULL) {
_ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset);
}
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 1, errorHandlerQuiet, 0);
_res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
- // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, errorHandlerQuiet, 0);
count = _ptr3[0];
if (arg3 != NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
@@ -371,7 +371,7 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
return;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, 0, 1);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 1);
memset(&xwa, 0, sizeof(XWindowAttributes));
XGetWindowAttributes(dpy, w, &xwa);
if(NULL != xwa.visual) {
@@ -379,7 +379,7 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
} else {
r = 0;
}
- // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
return r;
}
@@ -391,9 +391,9 @@ Java_jogamp_nativewindow_x11_X11Lib_DefaultVisualID(JNIEnv *env, jclass _unused,
if(0==display) {
NativewindowCommon_FatalError(env, "invalid display connection..");
}
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 1, errorHandlerQuiet, 0);
r = (jint) XVisualIDFromVisual( DefaultVisual( (Display*) (intptr_t) display, screen ) );
- // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) display, 0, 0, errorHandlerQuiet, 0);
return r;
}
@@ -434,9 +434,9 @@ Java_jogamp_nativewindow_x11_X11Lib_XCloseDisplay__J(JNIEnv *env, jclass _unused
if(0==display) {
NativewindowCommon_FatalError(env, "invalid display connection..");
}
- NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 1, errorHandlerQuiet, 0);
_res = XCloseDisplay((Display *) (intptr_t) display);
- // NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 0, 0, errorHandlerQuiet, 0);
return _res;
}
@@ -519,7 +519,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateWindow
return 0;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
scrn = ScreenOfDisplay(dpy, scrn_idx);
if(0==windowParent) {
@@ -542,7 +542,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateWindow
if (visual==NULL)
{
- // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
NativewindowCommon_throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!");
return 0;
}
@@ -606,7 +606,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_x11_X11Lib_CreateWindow
XSelectInput(dpy, window, 0); // no events
}
- // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", window, dpy);
@@ -630,12 +630,12 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyWindow
return;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
XSelectInput(dpy, w, 0);
XUnmapWindow(dpy, w);
XSync(dpy, False);
XDestroyWindow(dpy, w);
- // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0, 1);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
}
JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_SetWindowPosSize
@@ -683,11 +683,11 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_x11_X11Lib_GetRelativeLocatio
if( 0 == jdest_win ) { dest_win = root; }
if( 0 == jsrc_win ) { src_win = root; }
- NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, 0, 0);
+ NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
res = XTranslateCoordinates(dpy, src_win, dest_win, src_x, src_y, &dest_x, &dest_y, &child);
- // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, 0, 0);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 0);
DBG_PRINT( "X11: GetRelativeLocation0: %p %d/%d -> %p %d/%d - ok: %d\n",
(void*)src_win, src_x, src_y, (void*)dest_win, dest_x, dest_y, (int)res);
--
cgit v1.2.3
From aed9662552503b0a2fa67bcddbb7063b16d003d5 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Wed, 12 Jun 2013 11:58:55 +0200
Subject: Fix Bug 750: Leaked X11 ColorMap for each created X11 Window in
NativeWindow (dummy) and NEWT
Free the colormap at WindowDestroy, which we have created at WindowCreate w/ AllocNone.
Due to the fact we used 'AllocNone' the leak is minimal though ..
---
src/nativewindow/native/x11/Xmisc.c | 7 +++++++
src/newt/native/X11Window.c | 7 +++++++
2 files changed, 14 insertions(+)
(limited to 'src/nativewindow/native/x11')
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 69f0c0746..31620d752 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -624,6 +624,7 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyWindow
{
Display * dpy = (Display *)(intptr_t)display;
Window w = (Window) window;
+ XWindowAttributes xwa;
if(NULL==dpy) {
NativewindowCommon_throwNewRuntimeException(env, "invalid display connection..");
@@ -631,10 +632,16 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_x11_X11Lib_DestroyWindow
}
NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 0);
+ XSync(dpy, False);
+ memset(&xwa, 0, sizeof(XWindowAttributes));
+ XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction
XSelectInput(dpy, w, 0);
XUnmapWindow(dpy, w);
XSync(dpy, False);
XDestroyWindow(dpy, w);
+ if( None != xwa.colormap ) {
+ XFreeColormap(dpy, xwa.colormap);
+ }
// NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 0, errorHandlerQuiet, 1);
}
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 6c5a127b6..e567781cf 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -676,6 +676,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
Display * dpy = (Display *) (intptr_t) display;
Window w = (Window)window;
jobject jwindow;
+ XWindowAttributes xwa;
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
@@ -694,13 +695,19 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
}
XSync(dpy, False);
+ memset(&xwa, 0, sizeof(XWindowAttributes));
+ XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction
XSelectInput(dpy, w, 0);
XUnmapWindow(dpy, w);
+ XSync(dpy, False);
// Drain all events related to this window ..
Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
XDestroyWindow(dpy, w);
+ if( None != xwa.colormap ) {
+ XFreeColormap(dpy, xwa.colormap);
+ }
XSync(dpy, True); // discard all events now, no more handler
(*env)->DeleteGlobalRef(env, jwindow);
--
cgit v1.2.3
From 613e33ee8ffc1f2b9c5db1e1b5bb5253a159ed6d Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Mon, 4 Nov 2013 15:07:14 +0100
Subject: Bug 888 - Validate CPU Runtime Performance:
X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(..)
X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(..) ran over all FB configs and for each it grabbed
native config values separately. Fetching them in bulk mode saves around 7% of this function's cost.
Also reuse XRenderPictFormat instance for 'XRenderDirectFormat XRenderFindVisualFormat(..)' call,
saving a few NIO creation cycles w/ StructAccessor.
Biggest savior is X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationFBConfig()'s
fast path w/o chooser and usable 1st FBConfig. Here we only issue 'GLXFBConfig2GLCapabilities(..)'
on the first valid entry.
Test w/ 50 X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationFBConfig() invocations:
- pre change: 1.708 ms
- post change: 650 ms
Time is no spent almost solely on native glXChooseFBConfig (546ms).
---
make/config/jogl/glx-CustomCCode.c | 25 ++++
make/config/jogl/glx-CustomJavaCode.java | 22 ++++
make/config/nativewindow/x11-CustomJavaCode.java | 15 +++
.../x11/glx/X11GLXGraphicsConfiguration.java | 144 +++++++++++++++------
.../glx/X11GLXGraphicsConfigurationFactory.java | 46 ++++---
src/nativewindow/native/x11/Xmisc.c | 15 +++
6 files changed, 206 insertions(+), 61 deletions(-)
(limited to 'src/nativewindow/native/x11')
diff --git a/make/config/jogl/glx-CustomCCode.c b/make/config/jogl/glx-CustomCCode.c
index 71dc68b08..5c73dfea6 100644
--- a/make/config/jogl/glx-CustomCCode.c
+++ b/make/config/jogl/glx-CustomCCode.c
@@ -59,6 +59,31 @@ static void _initClazzAccess(JNIEnv *env) {
}
}
+/* Java->C glue code:
+ * Java package: jogamp.opengl.x11.glx.GLX
+ * Java method: int glXGetFBConfigAttributes(long dpy, long config, IntBuffer attributes, IntBuffer values)
+ */
+JNIEXPORT jint JNICALL
+Java_jogamp_opengl_x11_glx_GLX_dispatch_1glXGetFBConfigAttributes(JNIEnv *env, jclass _unused, jlong dpy, jlong config, jint attributeCount, jobject attributes, jint attributes_byte_offset, jobject values, jint values_byte_offset, jlong procAddress) {
+ typedef int (APIENTRY*_local_PFNGLXGETFBCONFIGATTRIBPROC)(Display * dpy, GLXFBConfig config, int attribute, int * value);
+ _local_PFNGLXGETFBCONFIGATTRIBPROC ptr_glXGetFBConfigAttrib = (_local_PFNGLXGETFBCONFIGATTRIBPROC) (intptr_t) procAddress;
+ assert(ptr_glXGetFBConfigAttrib != NULL);
+
+ int err = 0;
+ if ( attributeCount > 0 && NULL != attributes ) {
+ int i;
+ int * attributes_ptr = (int *) (((char*) (*env)->GetDirectBufferAddress(env, attributes)) + attributes_byte_offset);
+ int * values_ptr = (int *) (((char*) (*env)->GetDirectBufferAddress(env, values)) + values_byte_offset);
+ for(i=0; 0 == err && iC glue code:
* Java package: jogamp.opengl.x11.glx.GLX
* Java method: XVisualInfo glXGetVisualFromFBConfig(long dpy, long config)
diff --git a/make/config/jogl/glx-CustomJavaCode.java b/make/config/jogl/glx-CustomJavaCode.java
index f3e743930..4cce05dda 100644
--- a/make/config/jogl/glx-CustomJavaCode.java
+++ b/make/config/jogl/glx-CustomJavaCode.java
@@ -1,4 +1,26 @@
+ /**
+ * Returns the GLX error value, i.e. 0 for no error. In case of an error values.get(values.getPosition()) contains the attributes index causing the error.
+ *
+ * Entry point to C language function: int glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config, int attribute, int * value);
Part of GLX_VERSION_1_3
+ *
+ */
+ public static int glXGetFBConfigAttributes(long dpy, long config, IntBuffer attributes, IntBuffer values) {
+ if( attributes == null || values == null ) {
+ throw new RuntimeException("arrays buffers are null");
+ }
+ if( !Buffers.isDirect(attributes) || !Buffers.isDirect(values) ) {
+ throw new RuntimeException("arrays buffers are not direct");
+ }
+ if( attributes.remaining() > values.remaining() ) {
+ throw new RuntimeException("not enough values "+values+" for attributes "+attributes);
+ }
+ final long __addr = glxProcAddressTable._addressof_glXGetFBConfigAttrib;
+ return dispatch_glXGetFBConfigAttributes(dpy, config, attributes.remaining(), attributes, Buffers.getDirectBufferByteOffset(attributes),
+ values, Buffers.getDirectBufferByteOffset(values), __addr);
+ }
+ private static native int dispatch_glXGetFBConfigAttributes(long dpy, long config, int attributeCount, Object attributes, int attributes_byte_offset, Object values, int valuesOffset, long procAddr);
+
/** Interface to C language function:
- Alias for:
XVisualInfo * glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config);
*/
public static XVisualInfo glXGetVisualFromFBConfig(long dpy, long config)
{
diff --git a/make/config/nativewindow/x11-CustomJavaCode.java b/make/config/nativewindow/x11-CustomJavaCode.java
index 4240c5e2f..d1e011184 100644
--- a/make/config/nativewindow/x11-CustomJavaCode.java
+++ b/make/config/nativewindow/x11-CustomJavaCode.java
@@ -1,4 +1,19 @@
+ /** Interface to C language function:
XRenderPictFormat * XRenderFindVisualFormat(Display * dpy, const Visual * visual);
*/
+ public static boolean XRenderFindVisualFormat(long dpy, long visual, XRenderPictFormat dest) {
+ if( dest == null ) {
+ throw new RuntimeException("dest is null");
+ }
+ final ByteBuffer destBuffer = dest.getBuffer();
+ if( !Buffers.isDirect(destBuffer) ) {
+ throw new RuntimeException("dest buffer is not direct");
+ }
+ return XRenderFindVisualFormat1(dpy, visual, destBuffer);
+ }
+ /** Entry point to C language function: XVisualInfo * XGetVisualInfo(Display * , long, XVisualInfo * , int * );
*/
+ private static native boolean XRenderFindVisualFormat1(long dpy, long visual, ByteBuffer xRenderPictFormat);
+
+
/** Interface to C language function:
XVisualInfo * XGetVisualInfo(Display * , long, XVisualInfo * , int * );
*/
public static XVisualInfo[] XGetVisualInfo(long arg0, long arg1, XVisualInfo arg2, int[] arg3, int arg3_offset)
{
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
index 4d1ed3985..ee3e1a3d7 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
@@ -34,6 +34,8 @@
package jogamp.opengl.x11.glx;
import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.List;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
@@ -61,7 +63,7 @@ import com.jogamp.nativewindow.x11.X11GraphicsScreen;
public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implements Cloneable {
public static final int MAX_ATTRIBS = 128;
- private GLCapabilitiesChooser chooser;
+ private final GLCapabilitiesChooser chooser;
X11GLXGraphicsConfiguration(X11GraphicsScreen screen,
X11GLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
@@ -274,15 +276,47 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
return renderPictFmt.getDirect();
}
+ static XRenderDirectFormat XVisual2XRenderMask(long dpy, long visual, XRenderPictFormat dest) {
+ if( !X11Lib.XRenderFindVisualFormat(dpy, visual, dest) ) {
+ return null;
+ } else {
+ return dest.getDirect();
+ }
+ }
+
+ static X11GLCapabilities GLXFBConfig2GLCapabilities(final X11GraphicsDevice device, final GLProfile glp, final long fbcfg,
+ final int winattrmask, final boolean isMultisampleAvailable) {
+ final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
+ final XRenderPictFormat xRenderPictFormat= XRenderPictFormat.create();
+ return GLXFBConfig2GLCapabilities(device, glp, fbcfg, winattrmask, isMultisampleAvailable, tmp, xRenderPictFormat);
+ }
- static X11GLCapabilities GLXFBConfig2GLCapabilities(X11GraphicsDevice device, GLProfile glp, long fbcfg,
- int winattrmask, boolean isMultisampleAvailable) {
+ static List GLXFBConfig2GLCapabilities(final X11GraphicsDevice device, final GLProfile glp, final PointerBuffer fbcfgsL,
+ final int winattrmask, final boolean isMultisampleAvailable, boolean onlyFirstValid) {
+ final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
+ final XRenderPictFormat xRenderPictFormat= XRenderPictFormat.create();
+ final List result = new ArrayList();
+ for (int i = 0; i < fbcfgsL.limit(); i++) {
+ final long fbcfg = fbcfgsL.get(i);
+ final GLCapabilitiesImmutable c = GLXFBConfig2GLCapabilities(device, glp, fbcfg, winattrmask, isMultisampleAvailable, tmp, xRenderPictFormat);
+ if( null != c ) {
+ result.add(c);
+ if( onlyFirstValid ) {
+ break;
+ }
+ }
+ }
+ return result;
+ }
+ static X11GLCapabilities GLXFBConfig2GLCapabilities(final X11GraphicsDevice device, final GLProfile glp, final long fbcfg,
+ final int winattrmask, final boolean isMultisampleAvailable,
+ final IntBuffer tmp, final XRenderPictFormat xRenderPictFormat) {
+ final long display = device.getHandle();
final int allDrawableTypeBits = FBCfgDrawableTypeBits(device, fbcfg);
int drawableTypeBits = winattrmask & allDrawableTypeBits;
- final long display = device.getHandle();
- int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg);
- XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg);
+ final int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg);
+ final XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg);
if(null == visualInfo) {
if(DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: Null XVisualInfo for FBConfigID 0x" + Integer.toHexString(fbcfgid));
@@ -290,51 +324,87 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
// onscreen must have an XVisualInfo
drawableTypeBits &= ~(GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.FBO_BIT);
}
-
if( 0 == drawableTypeBits ) {
- return null;
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: zero drawablebits: winattrmask: "+toHexString(winattrmask)+", offscreen "+(null == visualInfo));
+ }
+ return null;
}
- final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
if(GLX.GLX_BAD_ATTRIBUTE == GLX.glXGetFBConfigAttrib(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp)) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: FBConfig invalid (1): fbcfg: "+toHexString(fbcfg));
+ }
return null;
}
if( 0 == ( GLX.GLX_RGBA_BIT & tmp.get(0) ) ) {
- return null; // no RGBA -> color index not supported
+ // no RGBA -> color index not supported
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities: FBConfig not RGBA (2): fbcfg: "+toHexString(fbcfg));
+ }
+ return null;
}
- final X11GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp);
- if (isMultisampleAvailable) {
- res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp) != 0);
- res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp));
- }
+ final X11GLCapabilities caps = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp);
+
final XRenderDirectFormat xrmask = ( null != visualInfo ) ?
- XVisual2XRenderMask( display, visualInfo.getVisual() ) :
+ XVisual2XRenderMask( display, visualInfo.getVisual(), xRenderPictFormat) :
null ;
+
+ final int _attributes[] = {
+ GLX.GLX_SAMPLE_BUFFERS,
+ GLX.GLX_SAMPLES,
+ GLX.GLX_DOUBLEBUFFER,
+ GLX.GLX_STEREO,
+ GLX.GLX_CONFIG_CAVEAT,
+ GLX.GLX_RED_SIZE,
+ GLX.GLX_GREEN_SIZE,
+ GLX.GLX_BLUE_SIZE,
+ GLX.GLX_ALPHA_SIZE,
+ GLX.GLX_ACCUM_RED_SIZE,
+ GLX.GLX_ACCUM_GREEN_SIZE,
+ GLX.GLX_ACCUM_BLUE_SIZE,
+ GLX.GLX_ACCUM_ALPHA_SIZE,
+ GLX.GLX_DEPTH_SIZE,
+ GLX.GLX_STENCIL_SIZE
+ };
+ final int offset = isMultisampleAvailable ? 0 : 2;
+ final IntBuffer attributes = Buffers.newDirectIntBuffer(_attributes);
+ attributes.position(offset);
+ final IntBuffer values = Buffers.newDirectIntBuffer(attributes.remaining());
+ final int err = GLX.glXGetFBConfigAttributes(display, fbcfg, attributes, values);
+ if (0 != err) {
+ throw new GLException("glXGetFBConfig("+toHexString(attributes.get(offset+values.get(0)))+") failed: error code " + glXGetFBConfigErrorCode(err));
+ }
+ int j=0;
+ if (isMultisampleAvailable) {
+ caps.setSampleBuffers(values.get(j++) != 0);
+ caps.setNumSamples (values.get(j++));
+ }
final int alphaMask = ( null != xrmask ) ? xrmask.getAlphaMask() : 0;
- res.setBackgroundOpaque( 0 >= alphaMask );
- if( !res.isBackgroundOpaque() ) {
- res.setTransparentRedValue(xrmask.getRedMask());
- res.setTransparentGreenValue(xrmask.getGreenMask());
- res.setTransparentBlueValue(xrmask.getBlueMask());
- res.setTransparentAlphaValue(alphaMask);
+ caps.setBackgroundOpaque( 0 >= alphaMask );
+ if( !caps.isBackgroundOpaque() ) {
+ caps.setTransparentRedValue(xrmask.getRedMask());
+ caps.setTransparentGreenValue(xrmask.getGreenMask());
+ caps.setTransparentBlueValue(xrmask.getBlueMask());
+ caps.setTransparentAlphaValue(alphaMask);
}
// ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples)
- res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp) != 0);
- res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp) != 0);
- res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp) != GLX.GLX_SLOW_CONFIG);
- res.setRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_RED_SIZE, tmp));
- res.setGreenBits (glXGetFBConfig(display, fbcfg, GLX.GLX_GREEN_SIZE, tmp));
- res.setBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_BLUE_SIZE, tmp));
- res.setAlphaBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ALPHA_SIZE, tmp));
- res.setAccumRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_RED_SIZE, tmp));
- res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp));
- res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp));
- res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp));
- res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp));
- res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp));
-
- return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
+ caps.setDoubleBuffered(values.get(j++) != 0);
+ caps.setStereo (values.get(j++) != 0);
+ caps.setHardwareAccelerated(values.get(j++) != GLX.GLX_SLOW_CONFIG);
+ caps.setRedBits (values.get(j++));
+ caps.setGreenBits (values.get(j++));
+ caps.setBlueBits (values.get(j++));
+ caps.setAlphaBits (values.get(j++));
+ caps.setAccumRedBits (values.get(j++));
+ caps.setAccumGreenBits(values.get(j++));
+ caps.setAccumBlueBits (values.get(j++));
+ caps.setAccumAlphaBits(values.get(j++));
+ caps.setDepthBits (values.get(j++));
+ caps.setStencilBits (values.get(j++));
+
+ return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, caps);
}
private static String glXGetFBConfigErrorCode(int err) {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
index 6050dabbb..5c84597d5 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
@@ -287,24 +287,23 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
final IntBuffer attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, true, isMultisampleAvailable, display, screen);
final IntBuffer count = Buffers.newDirectIntBuffer(1);
count.put(0, -1);
- List availableCaps = new ArrayList();
final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen);
+ List availableCaps;
// 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice,
// skipped if xvisualID is given
+ final boolean hasGLXChosenCaps;
if( VisualIDHolder.VID_UNDEFINED == xvisualID ) {
fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, count);
+ hasGLXChosenCaps = fbcfgsL != null && fbcfgsL.limit()>0;
+ } else {
+ hasGLXChosenCaps = false;
}
- if (fbcfgsL != null && fbcfgsL.limit()>0) {
- for (int i = 0; i < fbcfgsL.limit(); i++) {
- final GLCapabilitiesImmutable caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glProfile, fbcfgsL.get(i), winattrmask, isMultisampleAvailable);
- if( null != caps ) {
- availableCaps.add(caps);
- } else if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (1): ("+x11Screen+","+capsChosen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
- }
- }
+ final boolean useRecommendedIndex = hasGLXChosenCaps && capsChosen.isBackgroundOpaque(); // only use recommended idx if not translucent
+ final boolean skipCapsChooser = null == chooser && useRecommendedIndex; // fast path: skip choosing if using recommended idx and null chooser is used
+ if (hasGLXChosenCaps) {
+ availableCaps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glProfile, fbcfgsL, winattrmask, isMultisampleAvailable, skipCapsChooser /* onlyFirstValid */);
if(availableCaps.size() > 0) {
- recommendedIndex = capsChosen.isBackgroundOpaque() ? 0 : -1; // only use recommended idx if not translucent
+ recommendedIndex = useRecommendedIndex ? 0 : -1;
if (DEBUG) {
System.err.println("glXChooseFBConfig recommended fbcfg " + toHexString(fbcfgsL.get(0)) + ", idx " + recommendedIndex);
System.err.println("user caps " + capsChosen);
@@ -314,6 +313,8 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
System.err.println("glXChooseFBConfig no caps for recommended fbcfg " + toHexString(fbcfgsL.get(0)));
System.err.println("user caps " + capsChosen);
}
+ } else {
+ availableCaps = new ArrayList();
}
// 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available
@@ -328,15 +329,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
return null;
}
-
- for (int i = 0; i < fbcfgsL.limit(); i++) {
- final GLCapabilitiesImmutable caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glProfile, fbcfgsL.get(i), winattrmask, isMultisampleAvailable);
- if( null != caps ) {
- availableCaps.add(caps);
- } else if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
- }
- }
+ availableCaps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glProfile, fbcfgsL, winattrmask, isMultisampleAvailable, false /* onlyOneValid */);
}
if(DEBUG) {
@@ -346,9 +339,9 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
}
- if( VisualIDHolder.VID_UNDEFINED != xvisualID ) {
+ if( VisualIDHolder.VID_UNDEFINED != xvisualID ) { // implies !hasGLXChosenCaps
for(int i=0; i chosenIndex ) {
if (DEBUG) {
System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: failed, return null");
@@ -445,7 +443,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
if( VisualIDHolder.VID_UNDEFINED != xvisualID ) {
for(int i=0; i
+#include
+
// #define VERBOSE_ON 1
#ifdef VERBOSE_ON
@@ -320,6 +322,19 @@ Java_jogamp_nativewindow_x11_X11Util_setX11ErrorHandler0(JNIEnv *env, jclass _un
NativewindowCommon_x11ErrorHandlerEnable(env, NULL, 1, onoff ? 1 : 0, quiet ? 1 : 0, 0 /* no dpy, force, no sync */);
}
+/* Java->C glue code:
+ * Java package: jogamp.nativewindow.x11.X11Lib
+ * Java method: boolean XRenderFindVisualFormat(long dpy, long visual, XRenderPictFormat dest)
+ */
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_x11_X11Lib_XRenderFindVisualFormat1(JNIEnv *env, jclass _unused, jlong dpy, jlong visual, jobject xRenderPictFormat) {
+ XRenderPictFormat * dest = (XRenderPictFormat *) (*env)->GetDirectBufferAddress(env, xRenderPictFormat);
+ XRenderPictFormat * src = XRenderFindVisualFormat((Display *) (intptr_t) dpy, (Visual *) (intptr_t) visual);
+ if (NULL == src) return JNI_FALSE;
+ memcpy(dest, src, sizeof(XRenderPictFormat));
+ return JNI_TRUE;
+}
+
/* Java->C glue code:
* Java package: jogamp.nativewindow.x11.X11Lib
* Java method: XVisualInfo XGetVisualInfo(long arg0, long arg1, XVisualInfo arg2, java.nio.IntBuffer arg3)
--
cgit v1.2.3
From 1d426dd08797a3164e0a7cdf6007d3e750650265 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Tue, 5 Nov 2013 16:53:18 +0100
Subject: JNI Code: Call DeleteLocalRef(..) manually.
---
src/jogl/native/libav/ffmpeg_impl_template.c | 1 +
src/nativewindow/native/x11/Xmisc.c | 1 +
2 files changed, 2 insertions(+)
(limited to 'src/nativewindow/native/x11')
diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c
index 34a2baeb7..24fddd2c0 100644
--- a/src/jogl/native/libav/ffmpeg_impl_template.c
+++ b/src/jogl/native/libav/ffmpeg_impl_template.c
@@ -1275,6 +1275,7 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0)
pNIOBufferCurrent->nioRef = (*env)->NewGlobalRef(env, jSampleData);
pNIOBufferCurrent->origPtr = data_ptr;
pNIOBufferCurrent->size = data_size;
+ (*env)->DeleteLocalRef(env, jSampleData);
if(pAV->verbose) {
fprintf(stderr, "A NIO: Alloc ptr %p / ref %p, %d bytes\n",
pNIOBufferCurrent->origPtr, pNIOBufferCurrent->nioRef, pNIOBufferCurrent->size);
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 2bf740233..442d0ceef 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -368,6 +368,7 @@ Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Lja
jbyteSource = (*env)->NewDirectByteBuffer(env, _res, count * sizeof(XVisualInfo));
jbyteCopy = (*env)->CallStaticObjectMethod(env, clazzBuffers, cstrBuffers, jbyteSource);
+ (*env)->DeleteLocalRef(env, jbyteSource);
XFree(_res);
--
cgit v1.2.3
From c153a453299ef12bdb635dc11574a21bba74f04c Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Sun, 17 Nov 2013 05:31:22 +0100
Subject: Fix GLIBC > 2.4 dependency regression of commit
613e33ee8ffc1f2b9c5db1e1b5bb5253a159ed6d
Commit 613e33ee8ffc1f2b9c5db1e1b5bb5253a159ed6d introduced 'memcpy' usage in Xmisc.c which could create a GLIBC > 2.4 dependency.
Include GlueGen's glibc-compat-symbols.h to remove such dependency.
---
src/nativewindow/native/x11/Xmisc.c | 3 +++
1 file changed, 3 insertions(+)
(limited to 'src/nativewindow/native/x11')
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 442d0ceef..2c0e4e22b 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -35,6 +35,9 @@
#include
+/** Remove memcpy GLIBC > 2.4 dependencies */
+#include
+
// #define VERBOSE_ON 1
#ifdef VERBOSE_ON
--
cgit v1.2.3
From 380528f59c4a37429f4fa5f8ac7aa3076d0eaa11 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Sun, 17 Nov 2013 17:28:10 +0100
Subject: Nativewindow/NEWT: Fix C Return Statement
---
src/nativewindow/native/x11/Xmisc.c | 2 +-
src/newt/native/X11RandR11.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
(limited to 'src/nativewindow/native/x11')
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 2c0e4e22b..7b9dc344b 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -387,7 +387,7 @@ Java_jogamp_nativewindow_x11_X11Lib_GetVisualIDFromWindow(JNIEnv *env, jclass _u
if(NULL==dpy) {
NativewindowCommon_throwNewRuntimeException(env, "invalid display connection..");
- return;
+ return 0;
}
NativewindowCommon_x11ErrorHandlerEnable(env, dpy, 0, 1, errorHandlerQuiet, 1);
diff --git a/src/newt/native/X11RandR11.c b/src/newt/native/X11RandR11.c
index 53d01a6fe..38d61289b 100644
--- a/src/newt/native/X11RandR11.c
+++ b/src/newt/native/X11RandR11.c
@@ -335,7 +335,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenM
int rot;
do {
if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
- return;
+ return JNI_FALSE; // not done
}
XNextEvent(dpy, &evt);
@@ -366,5 +366,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenM
XSync(dpy, False);
+ return done ? JNI_TRUE : JNI_FALSE;
}
--
cgit v1.2.3
From 5ef83c2b8576ccd764ffc4953eea506bd96277c3 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Sat, 11 Jan 2014 00:04:18 +0100
Subject: X11: Harden usage of 'XGetWindowProperty(..)' and 'XGetVisualInfo' -
Add missing XFree(..) calls and argument checks.
---
src/nativewindow/native/x11/Xmisc.c | 36 ++++++++++----------
src/newt/native/X11Window.c | 66 +++++++++++++++++++++----------------
2 files changed, 55 insertions(+), 47 deletions(-)
(limited to 'src/nativewindow/native/x11')
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 7b9dc344b..5e6909f6e 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -219,7 +219,6 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
(int)e->request_code, (int)e->minor_code, reqCodeStr);
}
-
if (shallBeDetached) {
(*jvmHandle)->DetachCurrentThread(jvmHandle);
}
@@ -347,25 +346,24 @@ JNIEXPORT jobject JNICALL
Java_jogamp_nativewindow_x11_X11Lib_XGetVisualInfo1__JJLjava_nio_ByteBuffer_2Ljava_lang_Object_2I(JNIEnv *env, jclass _unused, jlong arg0, jlong arg1, jobject arg2, jobject arg3, jint arg3_byte_offset) {
XVisualInfo * _ptr2 = NULL;
int * _ptr3 = NULL;
- XVisualInfo * _res;
- int count;
- jobject jbyteSource;
- jobject jbyteCopy;
- if(0==arg0) {
- NativewindowCommon_FatalError(env, "invalid display connection..");
- }
- if (arg2 != NULL) {
- _ptr2 = (XVisualInfo *) (((char*) (*env)->GetDirectBufferAddress(env, arg2)) + 0);
- }
- if (arg3 != NULL) {
- _ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset);
+ XVisualInfo * _res = NULL;
+ int count = 0;
+ jobject jbyteSource = NULL;
+ jobject jbyteCopy = NULL;
+ if( 0 == arg0 || 0 == arg2 || 0 == arg3 ) {
+ NativewindowCommon_FatalError(env, "invalid display connection, vinfo_template or nitems_return");
+ return NULL;
}
- NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 1, errorHandlerQuiet, 0);
- _res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
- // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, errorHandlerQuiet, 0);
- count = _ptr3[0];
- if (arg3 != NULL) {
- (*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
+ _ptr2 = (XVisualInfo *) (((char*) (*env)->GetDirectBufferAddress(env, arg2)) + 0);
+ if( NULL != _ptr2 ) {
+ _ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset);
+ if( NULL != _ptr3 ) {
+ NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 1, errorHandlerQuiet, 0);
+ _res = XGetVisualInfo((Display *) (intptr_t) arg0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3);
+ // NativewindowCommon_x11ErrorHandlerEnable(env, (Display *) (intptr_t) arg0, 0, 0, errorHandlerQuiet, 0);
+ count = _ptr3[0];
+ (*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0);
+ }
}
if (_res == NULL) return NULL;
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 54b85c243..2cc66c78d 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -98,11 +98,11 @@ static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlon
}
jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) {
- Atom actual_type;
- int actual_format;
+ Atom actual_type = 0;
+ int actual_format = 0;
int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ;
unsigned char * jogl_java_object_data_pp = NULL;
- jobject jwindow;
+ jobject jwindow = 0;
{
unsigned long nitems= 0;
@@ -122,7 +122,9 @@ jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong ja
}
if(actual_type!=(Atom)javaObjectAtom || nitems= PROP_MWM_HINTS_ELEMENTS) {
// unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status
unsigned long *hints = (unsigned long *) wm_data;
decor = ( 0 != (hints[0] & MWM_HINTS_DECORATIONS) ) && ( 0 != hints[2] );
}
+ if( NULL != wm_data ) {
+ XFree(wm_data);
+ }
}
#endif
@@ -319,27 +326,30 @@ static int NewtWindows_getSupportedStackingEWMHFlags(Display *dpy, Window w) {
Atom _NET_WM_ALLOWED_ACTIONS = XInternAtom( dpy, "_NET_WM_ALLOWED_ACTIONS", False );
Atom _NET_WM_ACTION_FULLSCREEN = XInternAtom( dpy, "_NET_WM_ACTION_FULLSCREEN", False );
Atom _NET_WM_ACTION_ABOVE = XInternAtom( dpy, "_NET_WM_ACTION_ABOVE", False );
- Atom * actions;
- Atom type;
- unsigned long action_len, remain;
- int res = 0, form, i;
+ Atom * actions = NULL;
+ Atom type = 0;
+ unsigned long action_len = 0, remain = 0;
+ int res = 0, form = 0, i = 0;
Status s;
if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, AnyPropertyType,
&type, &form, &action_len, &remain, (unsigned char**)&actions)) ) {
- for(i=0; i
Date: Sat, 11 Jan 2014 02:11:47 +0100
Subject: [Jogl|Nativewindow|Newt]Common: Align all
*Common_GetJNIEnv()/_ReleaseJNIEnv() Methods and Usage / Check arguments ..
Since we still don't use inter-module native code sharing, align the JNIEnv get/release methods and usage.
Most beneficary here is OSX and the GLDebugMessageHandle,
both managed the JVM handle on their own - removed now.
Also ensuring that *Common_init(..) is called for all modules on all platforms.
---
src/jogl/native/GLContext.c | 2 +-
src/jogl/native/GLDebugMessageHandler.c | 95 ++++---------
src/jogl/native/JoglCommon.c | 97 ++++++-------
src/jogl/native/JoglCommon.h | 55 ++++++--
src/jogl/native/libav/ffmpeg_impl_template.c | 4 +-
.../macosx/MacOSXWindowSystemInterface-calayer.m | 1 +
.../jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c | 5 +-
src/nativewindow/native/NativewindowCommon.c | 110 ++++++++++-----
src/nativewindow/native/NativewindowCommon.h | 61 ++++++++-
src/nativewindow/native/macosx/OSXmisc.m | 34 ++---
src/nativewindow/native/win32/GDImisc.c | 2 +-
src/nativewindow/native/x11/Xmisc.c | 126 +++++++----------
src/newt/native/MacWindow.m | 13 +-
src/newt/native/NewtCommon.c | 96 +++++++++----
src/newt/native/NewtCommon.h | 26 ++--
src/newt/native/NewtMacWindow.h | 10 --
src/newt/native/NewtMacWindow.m | 152 ++++++---------------
17 files changed, 431 insertions(+), 458 deletions(-)
(limited to 'src/nativewindow/native/x11')
diff --git a/src/jogl/native/GLContext.c b/src/jogl/native/GLContext.c
index f10d0e421..9be9f82af 100644
--- a/src/jogl/native/GLContext.c
+++ b/src/jogl/native/GLContext.c
@@ -19,7 +19,7 @@ Java_jogamp_opengl_GLContextImpl_glGetStringInt(JNIEnv *env, jclass _unused, jin
assert(ptr_glGetString != NULL);
_res = (* ptr_glGetString) ((unsigned int) name);
if (NULL == _res) return NULL;
- return (*env)->NewStringUTF(env, _res);
+ return (*env)->NewStringUTF(env, (const char *)_res);
}
/*
diff --git a/src/jogl/native/GLDebugMessageHandler.c b/src/jogl/native/GLDebugMessageHandler.c
index 2e9d6033a..0aa7a01e7 100644
--- a/src/jogl/native/GLDebugMessageHandler.c
+++ b/src/jogl/native/GLDebugMessageHandler.c
@@ -49,8 +49,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_opengl_GLDebugMessageHandler_initIDs0
}
typedef struct {
- JavaVM *vm;
- int version;
jobject obj;
int extType;
} DebugHandlerType;
@@ -60,39 +58,21 @@ typedef struct {
static void GLDebugMessageARBCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar *message, GLvoid *userParam) {
DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) userParam;
- JavaVM *vm = handle->vm;
- int version = handle->version;
jobject obj = handle->obj;
- JNIEnv *curEnv = NULL;
- JNIEnv *newEnv = NULL;
- int envRes ;
- DBG_PRINT("GLDebugMessageARBCallback: 00 - %s, vm %p, version 0x%X, jobject %p, extType %d\n",
- message, handle->vm, handle->version, (void*)handle->obj, handle->extType);
-
- // retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*vm)->GetEnv(vm, (void **) &curEnv, version) ;
- DBG_PRINT("GLDebugMessageARBCallback: 01 - JVM Env: curEnv %p, res 0x%X\n", curEnv, envRes);
- if( JNI_EDETACHED == envRes ) {
- // detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*vm)->AttachCurrentThread(vm, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "GLDebugMessageARBCallback: can't attach thread: %d\n", envRes);
- return;
- }
- curEnv = newEnv;
- DBG_PRINT("GLDebugMessageARBCallback: 02 - attached .. \n");
- } else if( JNI_OK != envRes ) {
- // oops ..
- fprintf(stderr, "GLDebugMessageARBCallback: can't GetEnv: %d\n", envRes);
+ JNIEnv *env = NULL;
+ int shallBeDetached ;
+ DBG_PRINT("GLDebugMessageARBCallback: 00 - %s, jobject %p, extType %d\n", message, (void*)handle->obj, handle->extType);
+
+ env = JoglCommon_GetJNIEnv (1 /* asDaemon */, &shallBeDetached);
+ if( NULL == env ) {
+ DBG_PRINT("GLDebugMessageARBCallback: Null JNIEnv\n");
return;
}
- (*curEnv)->CallVoidMethod(curEnv, obj, glDebugMessageARB,
+ (*env)->CallVoidMethod(env, obj, glDebugMessageARB,
(jint) source, (jint) type, (jint) id, (jint) severity,
- (*curEnv)->NewStringUTF(curEnv, message));
- if( NULL != newEnv ) {
- // detached attached thread
- (*vm)->DetachCurrentThread(vm);
- DBG_PRINT("GLDebugMessageARBCallback: 04 - detached .. \n");
- }
+ (*env)->NewStringUTF(env, message));
+ // detaching thread not required - daemon
+ // JoglCommon_ReleaseJNIEnv(shallBeDetached);
DBG_PRINT("GLDebugMessageARBCallback: 0X\n");
/**
* On Java 32bit on 64bit Windows and w/ GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB disables,
@@ -104,39 +84,21 @@ static void GLDebugMessageARBCallback(GLenum source, GLenum type, GLuint id, GLe
static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severity,
GLsizei length, const GLchar *message, GLvoid *userParam) {
DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) userParam;
- JavaVM *vm = handle->vm;
- int version = handle->version;
jobject obj = handle->obj;
- JNIEnv *curEnv = NULL;
- JNIEnv *newEnv = NULL;
- int envRes ;
- DBG_PRINT("GLDebugMessageAMDCallback: 00 - %s, vm %p, version 0x%X, jobject %p, extType %d\n",
- message, handle->vm, handle->version, (void*)handle->obj, handle->extType);
-
- // retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*vm)->GetEnv(vm, (void **) &curEnv, version) ;
- DBG_PRINT("GLDebugMessageAMDCallback: 01 - JVM Env: curEnv %p, res 0x%X\n", curEnv, envRes);
- if( JNI_EDETACHED == envRes ) {
- // detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*vm)->AttachCurrentThread(vm, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "GLDebugMessageAMDCallback: can't attach thread: %d\n", envRes);
- return;
- }
- curEnv = newEnv;
- DBG_PRINT("GLDebugMessageAMDCallback: 02 - attached .. \n");
- } else if( JNI_OK != envRes ) {
- // oops ..
- fprintf(stderr, "GLDebugMessageAMDCallback: can't GetEnv: %d\n", envRes);
+ JNIEnv *env = NULL;
+ int shallBeDetached ;
+ DBG_PRINT("GLDebugMessageAMDCallback: 00 - %s, jobject %p, extType %d\n", message, (void*)handle->obj, handle->extType);
+
+ env = JoglCommon_GetJNIEnv (1 /* asDaemon */, &shallBeDetached);
+ if( NULL == env ) {
+ DBG_PRINT("GLDebugMessageARBCallback: Null JNIEnv\n");
return;
}
- (*curEnv)->CallVoidMethod(curEnv, obj, glDebugMessageAMD,
+ (*env)->CallVoidMethod(env, obj, glDebugMessageAMD,
(jint) id, (jint) category, (jint) severity,
- (*curEnv)->NewStringUTF(curEnv, message));
- if( NULL != newEnv ) {
- // detached attached thread
- (*vm)->DetachCurrentThread(vm);
- DBG_PRINT("GLDebugMessageAMDCallback: 04 - detached .. \n");
- }
+ (*env)->NewStringUTF(env, message));
+ // detached attached thread not required - daemon
+ // JoglCommon_ReleaseJNIEnv(shallBeDetached);
DBG_PRINT("GLDebugMessageAMDCallback: 0X\n");
/**
* On Java 32bit on 64bit Windows,
@@ -153,18 +115,10 @@ static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severit
JNIEXPORT jlong JNICALL Java_jogamp_opengl_GLDebugMessageHandler_register0
(JNIEnv *env, jobject obj, jlong procAddress, jint extType)
{
- JavaVM *vm;
DebugHandlerType * handle = malloc(sizeof(DebugHandlerType));
- if(0 != (*env)->GetJavaVM(env, &vm)) {
- vm = NULL;
- JoglCommon_throwNewRuntimeException(env, "GetJavaVM failed");
- }
- handle->vm = vm;
- handle->version = (*env)->GetVersion(env);
handle->obj = (*env)->NewGlobalRef(env, obj);
handle->extType = extType;
- DBG_PRINT("GLDebugMessageHandler.register0: vm %p, version 0x%X, jobject %p, extType %d\n",
- handle->vm, handle->version, (void*)handle->obj, handle->extType);
+ DBG_PRINT("GLDebugMessageHandler.register0: jobject %p, extType %d\n", (void*)handle->obj, handle->extType);
if(jogamp_opengl_GLDebugMessageHandler_EXT_ARB == extType) {
_local_PFNGLDEBUGMESSAGECALLBACKARBPROC ptr_glDebugMessageCallbackARB;
@@ -191,8 +145,7 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_GLDebugMessageHandler_unregister0
{
DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) jhandle;
- DBG_PRINT("GLDebugMessageHandler.unregister0: vm %p, version 0x%X, jobject %p, extType %d\n",
- handle->vm, handle->version, (void*)handle->obj, handle->extType);
+ DBG_PRINT("GLDebugMessageHandler.unregister0: jobject %p, extType %d\n", (void*)handle->obj, handle->extType);
if(JNI_FALSE == (*env)->IsSameObject(env, obj, handle->obj)) {
JoglCommon_throwNewRuntimeException(env, "wrong handle (obj doesn't match)");
diff --git a/src/jogl/native/JoglCommon.c b/src/jogl/native/JoglCommon.c
index 4170b13ec..e9984ada2 100644
--- a/src/jogl/native/JoglCommon.c
+++ b/src/jogl/native/JoglCommon.c
@@ -11,42 +11,38 @@ static JavaVM *_jvmHandle = NULL;
static int _jvmVersion = 0;
void JoglCommon_init(JNIEnv *env) {
- if(NULL==runtimeExceptionClz) {
+ if(NULL==_jvmHandle) {
+ if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+ JoglCommon_FatalError(env, "JOGL: Can't fetch JavaVM handle");
+ } else {
+ _jvmVersion = (*env)->GetVersion(env);
+ }
jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
if(NULL==c) {
- JoglCommon_FatalError(env, "JOGL: can't find %s", ClazzNameRuntimeException);
+ JoglCommon_FatalError(env, "JOGL: Can't find %s", ClazzNameRuntimeException);
}
runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
if(NULL==runtimeExceptionClz) {
- JoglCommon_FatalError(env, "JOGL: can't use %s", ClazzNameRuntimeException);
+ JoglCommon_FatalError(env, "JOGL: Can't use %s", ClazzNameRuntimeException);
}
}
- if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
- JoglCommon_FatalError(env, "JOGL: can't fetch JavaVM handle");
- } else {
- _jvmVersion = (*env)->GetVersion(env);
- }
}
void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
- int shallBeDetached = 0;
-
- if(NULL == env) {
- env = JoglCommon_GetJNIEnv (&shallBeDetached);
- }
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
- fprintf(stderr, "%s\n", buffer);
- if(NULL != env) {
- (*env)->FatalError(env, buffer);
- JoglCommon_ReleaseJNIEnv (shallBeDetached);
+ fprintf(stderr, "%s\n", buffer);
+ if(NULL != env) {
+ (*env)->FatalError(env, buffer);
+ }
}
}
@@ -54,48 +50,42 @@ void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
- int shallBeDetached = 0;
- if(NULL == env) {
- env = JoglCommon_GetJNIEnv (&shallBeDetached);
+ if(NULL==_jvmHandle) {
+ JoglCommon_FatalError(env, "JOGL: NULL JVM handle, call JoglCommon_init 1st\n");
+ return;
}
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
- if(NULL != env) {
- (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
- JoglCommon_ReleaseJNIEnv (shallBeDetached);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
+ }
}
}
-JavaVM *JoglCommon_GetJVMHandle() {
- return _jvmHandle;
-}
-
-int JoglCommon_GetJVMVersion() {
- return _jvmVersion;
-}
-
jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
{
jchar* strChars = NULL;
- strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
- if (strChars != NULL) {
- (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ if( NULL != env && 0 != str ) {
+ strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
+ if (strChars != NULL) {
+ (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ }
}
return strChars;
}
-JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached)
-{
+JNIEnv* JoglCommon_GetJNIEnv (int asDaemon, int * shallBeDetached) {
JNIEnv* curEnv = NULL;
JNIEnv* newEnv = NULL;
int envRes;
- if(NULL == _jvmHandle) {
- fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st");
+ if(NULL==_jvmHandle) {
+ fprintf(stderr, "JOGL GetJNIEnv: NULL JVM handle, call JoglCommon_init 1st\n");
return NULL;
}
@@ -103,18 +93,23 @@ JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached)
envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ;
if( JNI_EDETACHED == envRes ) {
// detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
+ if( asDaemon ) {
+ envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL);
+ } else {
+ envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL);
+ }
+ if( JNI_OK != envRes ) {
+ fprintf(stderr, "JOGL GetJNIEnv: Can't attach thread: %d\n", envRes);
return NULL;
}
curEnv = newEnv;
} else if( JNI_OK != envRes ) {
// oops ..
- fprintf(stderr, "can't GetEnv: %d\n", envRes);
+ fprintf(stderr, "JOGL GetJNIEnv: Can't GetEnv: %d\n", envRes);
return NULL;
}
if (curEnv==NULL) {
- fprintf(stderr, "env is NULL\n");
+ fprintf(stderr, "JOGL GetJNIEnv: env is NULL\n");
return NULL;
}
*shallBeDetached = NULL != newEnv;
@@ -123,10 +118,8 @@ JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached)
void JoglCommon_ReleaseJNIEnv (int shallBeDetached) {
if(NULL == _jvmHandle) {
- fprintf(stderr, "JOGL: No JavaVM handle registered, call JoglCommon_init(..) 1st");
- }
-
- if(shallBeDetached) {
+ fprintf(stderr, "JOGL ReleaseJNIEnv: No JavaVM handle registered, call JoglCommon_init(..) 1st");
+ } else if(shallBeDetached) {
(*_jvmHandle)->DetachCurrentThread(_jvmHandle);
}
}
diff --git a/src/jogl/native/JoglCommon.h b/src/jogl/native/JoglCommon.h
index 023b4be03..2aeaf7d1d 100644
--- a/src/jogl/native/JoglCommon.h
+++ b/src/jogl/native/JoglCommon.h
@@ -1,3 +1,30 @@
+/**
+ * Copyright 2011 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.
+ */
#ifndef JOGL_COMMON_H
#define JOGL_COMMON_H 1
@@ -7,29 +34,25 @@
void JoglCommon_init(JNIEnv *env);
-/** Set by JoglCommon_init */
-JavaVM *JoglCommon_GetJVMHandle();
-
-/** Set by JoglCommon_init */
-int JoglCommon_GetJVMVersion();
-
jchar* JoglCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str);
-/** env may be NULL, in which case JoglCommon_GetJNIEnv() is being used. */
void JoglCommon_FatalError(JNIEnv *env, const char* msg, ...);
-
-/** env may be NULL, in which case JoglCommon_GetJNIEnv() is being used. */
void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
/**
*
- * 1) Store jvmHandle and jvmVersion is done by 'JoglCommon_init(JNIEnv*)'
- * and internally used by 'JoglCommon_GetJNIEnv(..)' and 'JoglCommon_ReleaseJNIEnv(..)'.
+ * 1) Init static jvmHandle, jvmVersion and clazz references
+ * from an early initialization call w/ valid 'JNIEnv * env'
+
+ JoglCommon_init(env);
+
*
* 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv
*
+
+ int asDaemon = 0;
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(&shallBeDetached);
+ JNIEnv* env = JoglCommon_GetJNIEnv(asDaemon, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("drawRect: null JNIEnv\n");
return;
@@ -41,11 +64,13 @@ void JoglCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
.. your JNIEnv code here ..
*
- * 4) Detach thread from JVM, if required
+ * 4) Detach thread from JVM if required, i.e. not attached as daemon!
+ * Not recommended for recurring _daemon_ threads (performance)
*
- JoglCommon_ReleaseJNIEnv (shallBeDetached);
+ JoglCommon_ReleaseJNIEnv(shallBeDetached);
*/
-JNIEnv* JoglCommon_GetJNIEnv (int * shallBeDetached);
+JNIEnv* JoglCommon_GetJNIEnv (int asDaemon, int * shallBeDetached);
+
void JoglCommon_ReleaseJNIEnv (int shallBeDetached);
#endif
diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c
index 44acfe46a..e86b2a542 100644
--- a/src/jogl/native/libav/ffmpeg_impl_template.c
+++ b/src/jogl/native/libav/ffmpeg_impl_template.c
@@ -1499,7 +1499,7 @@ JNIEXPORT jint JNICALL FF_FUNC(seek0)
int64_t pts1 = (int64_t) (pos1 * (int64_t) time_base.den)
/ (1000 * (int64_t) time_base.num);
if(pAV->verbose) {
- fprintf(stderr, "SEEK: vid %d, aid %d, pos0 %d, pos1 %d, pts: %"PRId64" -> %"PRId64"\n", pAV->vid, pAV->aid, pos0, pos1, pts0, pts1);
+ fprintf(stderr, "SEEK: vid %d, aid %d, pos0 %"PRId64", pos1 %d, pts: %"PRId64" -> %"PRId64"\n", pAV->vid, pAV->aid, pos0, pos1, pts0, pts1);
}
int flags = 0;
if(pos1 < pos0) {
@@ -1508,7 +1508,7 @@ JNIEXPORT jint JNICALL FF_FUNC(seek0)
int res = -2;
if(HAS_FUNC(sp_av_seek_frame)) {
if(pAV->verbose) {
- fprintf(stderr, "SEEK.0: pre : s %d / %"PRId64" -> t %d / %"PRId64"\n", pos0, pts0, pos1, pts1);
+ fprintf(stderr, "SEEK.0: pre : s %"PRId64" / %"PRId64" -> t %d / %"PRId64"\n", pos0, pts0, pos1, pts1);
}
sp_av_seek_frame(pAV->pFormatCtx, streamID, pts1, flags);
} else if(HAS_FUNC(sp_avformat_seek_file)) {
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
index 75917d2dc..7ce8c58cf 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
@@ -578,6 +578,7 @@ static const GLfloat gl_verts[] = {
quirks, dedicatedFramePosSet, dedicatedFrameSizeSet, dedicatedLayoutSet, self, texWidth, texHeight,
lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height,
dFrame.origin.x, dFrame.origin.y, dFrame.size.width, dFrame.size.height);
+ (void)lRect; // silence
if( dedicatedFrameSet ) {
[super setFrame: dedicatedFrame];
diff --git a/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c b/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c
index ec68a24aa..3166306ba 100644
--- a/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c
+++ b/src/jogl/native/openmax/jogamp_opengl_util_av_impl_OMXGLMediaPlayer.c
@@ -67,7 +67,7 @@ void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pAV)
return;
}
int shallBeDetached = 0;
- JNIEnv * env = JoglCommon_GetJNIEnv (&shallBeDetached);
+ JNIEnv * env = JoglCommon_GetJNIEnv (1 /* daemon */, &shallBeDetached);
if(NULL!=env) {
(*env)->CallVoidMethod(env, (jobject)pAV->jni_instance, jni_mid_updateAttributes,
pAV->width, pAV->height,
@@ -75,7 +75,8 @@ void OMXInstance_UpdateJavaAttributes(OMXToolBasicAV_t *pAV)
pAV->framerate, (uint32_t)(pAV->length*pAV->framerate), pAV->length,
(*env)->NewStringUTF(env, pAV->videoCodec),
(*env)->NewStringUTF(env, pAV->audioCodec) );
- JoglCommon_ReleaseJNIEnv (shallBeDetached);
+ // detaching thread not required - daemon
+ // JoglCommon_ReleaseJNIEnv(shallBeDetached);
}
}
diff --git a/src/nativewindow/native/NativewindowCommon.c b/src/nativewindow/native/NativewindowCommon.c
index ec7ee7728..e65f87272 100644
--- a/src/nativewindow/native/NativewindowCommon.c
+++ b/src/nativewindow/native/NativewindowCommon.c
@@ -8,41 +8,24 @@
static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
static jclass runtimeExceptionClz=NULL;
-void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...)
-{
- char buffer[512];
- va_list ap;
-
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
-
- fprintf(stderr, "%s\n", buffer);
- (*env)->FatalError(env, buffer);
-}
-
-void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
-{
- char buffer[512];
- va_list ap;
-
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
-
- (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
-}
+static JavaVM *_jvmHandle = NULL;
+static int _jvmVersion = 0;
int NativewindowCommon_init(JNIEnv *env) {
- if(NULL==runtimeExceptionClz) {
+ if(NULL==_jvmHandle) {
+ if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+ NativewindowCommon_FatalError(env, "Nativewindow: Can't fetch JavaVM handle");
+ } else {
+ _jvmVersion = (*env)->GetVersion(env);
+ }
jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
if(NULL==c) {
- NativewindowCommon_FatalError(env, "Nativewindow: can't find %s", ClazzNameRuntimeException);
+ NativewindowCommon_FatalError(env, "Nativewindow: Can't find %s", ClazzNameRuntimeException);
}
runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
if(NULL==runtimeExceptionClz) {
- NativewindowCommon_FatalError(env, "Nativewindow: can't use %s", ClazzNameRuntimeException);
+ NativewindowCommon_FatalError(env, "Nativewindow: Can't use %s", ClazzNameRuntimeException);
}
#ifdef STDERR_TO_FILE
FILE * old_stderr = stderr;
@@ -54,6 +37,44 @@ int NativewindowCommon_init(JNIEnv *env) {
return 0;
}
+void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...)
+{
+ char buffer[512];
+ va_list ap;
+
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
+
+ fprintf(stderr, "%s\n", buffer);
+ if(NULL != env) {
+ (*env)->FatalError(env, buffer);
+ }
+ }
+}
+
+void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
+{
+ char buffer[512];
+ va_list ap;
+
+ if(NULL==_jvmHandle) {
+ NativewindowCommon_FatalError(env, "Nativewindow: NULL JVM handle, call NativewindowCommon_init 1st\n");
+ return;
+ }
+
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
+
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
+ }
+ }
+}
+
const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText) {
if(NULL != jniEnv && NULL != clazz && NULL != jGetStrID) {
jstring jstr = (jstring) (*jniEnv)->CallStaticObjectMethod(jniEnv, clazz, jGetStrID);
@@ -75,45 +96,60 @@ const char * NativewindowCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass cla
jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
{
jchar* strChars = NULL;
- strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
- if (strChars != NULL) {
- (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ if( NULL != env && 0 != str ) {
+ strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
+ if (strChars != NULL) {
+ (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ }
}
return strChars;
}
-JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) {
+JNIEnv* NativewindowCommon_GetJNIEnv (int asDaemon, int * shallBeDetached) {
JNIEnv* curEnv = NULL;
JNIEnv* newEnv = NULL;
int envRes;
+ if(NULL==_jvmHandle) {
+ fprintf(stderr, "Nativewindow GetJNIEnv: NULL JVM handle, call NativewindowCommon_init 1st\n");
+ return NULL;
+ }
+
// retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
+ envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ;
if( JNI_EDETACHED == envRes ) {
// detached thread - attach to JVM
if( asDaemon ) {
- envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL);
+ envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL);
} else {
- envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL);
+ envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL);
}
if( JNI_OK != envRes ) {
- fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
+ fprintf(stderr, "Nativewindow GetJNIEnv: Can't attach thread: %d\n", envRes);
return NULL;
}
curEnv = newEnv;
} else if( JNI_OK != envRes ) {
// oops ..
- fprintf(stderr, "can't GetEnv: %d\n", envRes);
+ fprintf(stderr, "Nativewindow GetJNIEnv: Can't GetEnv: %d\n", envRes);
return NULL;
}
if (curEnv==NULL) {
- fprintf(stderr, "env is NULL\n");
+ fprintf(stderr, "Nativewindow GetJNIEnv: env is NULL\n");
return NULL;
}
*shallBeDetached = NULL != newEnv;
return curEnv;
}
+void NativewindowCommon_ReleaseJNIEnv (int shallBeDetached) {
+ if(NULL == _jvmHandle) {
+ fprintf(stderr, "Nativewindow ReleaseJNIEnv: No JavaVM handle registered, call NativewindowCommon_init(..) 1st");
+ } else if(shallBeDetached) {
+ (*_jvmHandle)->DetachCurrentThread(_jvmHandle);
+ }
+}
+
int64_t NativewindowCommon_CurrentTimeMillis() {
struct timeval tv;
gettimeofday(&tv,NULL);
diff --git a/src/nativewindow/native/NativewindowCommon.h b/src/nativewindow/native/NativewindowCommon.h
index a23fad9fd..f19552e33 100644
--- a/src/nativewindow/native/NativewindowCommon.h
+++ b/src/nativewindow/native/NativewindowCommon.h
@@ -1,3 +1,30 @@
+/**
+ * Copyright 2011 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.
+ */
#ifndef NATIVEWINDOW_COMMON_H
#define NATIVEWINDOW_COMMON_H 1
@@ -14,7 +41,39 @@ jchar* NativewindowCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
void NativewindowCommon_FatalError(JNIEnv *env, const char* msg, ...);
void NativewindowCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
-JNIEnv* NativewindowCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached);
+/**
+ *
+ * 1) Init static jvmHandle, jvmVersion and clazz references
+ * from an early initialization call w/ valid 'JNIEnv * env'
+
+ NativewindowCommon_init(env);
+
+ *
+ * 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv
+ *
+
+ int asDaemon = 0;
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("drawRect: null JNIEnv\n");
+ return;
+ }
+
+ *
+ * 3) Use JNIEnv ..
+ *
+ .. your JNIEnv code here ..
+
+ *
+ * 4) Detach thread from JVM if required, i.e. not attached as daemon!
+ * Not recommended for recurring _daemon_ threads (performance)
+ *
+ NewtCommon_ReleaseJNIEnv(shallBeDetached);
+ */
+JNIEnv* NativewindowCommon_GetJNIEnv (int asDaemon, int * shallBeDetached);
+
+void NativewindowCommon_ReleaseJNIEnv (int shallBeDetached);
int64_t NativewindowCommon_CurrentTimeMillis();
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index 6a7952eaf..4887cc3cf 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -75,11 +75,9 @@ static const char * const ClazzNameInsetsCstrSignature = "(IIII)V";
static jclass insetsClz = NULL;
static jmethodID insetsCstr = NULL;
-static int _initialized=0;
-
JNIEXPORT jboolean JNICALL
Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
- if(0==_initialized) {
+ if( NativewindowCommon_init(env) ) {
jclass c;
c = (*env)->FindClass(env, ClazzNamePoint);
if(NULL==c) {
@@ -119,7 +117,6 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
if(NULL==runnableRunID) {
NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.run()V", ClazzNameRunnable);
}
- _initialized=1;
}
return JNI_TRUE;
}
@@ -775,12 +772,10 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns
@interface MainRunnable : NSObject
{
- JavaVM *jvmHandle;
- int jvmVersion;
jobject runnableObj;
}
-- (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers;
+- (id) initWithRunnable: (jobject)runnable;
- (void) jRun;
#ifdef DBG_LIFECYCLE
@@ -794,10 +789,8 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns
@implementation MainRunnable
-- (id) initWithRunnable: (jobject)runnable jvmHandle: (JavaVM*)jvm jvmVersion: (int)jvmVers
+- (id) initWithRunnable: (jobject)runnable
{
- jvmHandle = jvm;
- jvmVersion = jvmVers;
runnableObj = runnable;
return [super init];
}
@@ -805,7 +798,7 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns
- (void) jRun
{
int shallBeDetached = 0;
- JNIEnv* env = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached);
+ JNIEnv* env = NativewindowCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
DBG_PRINT2("MainRunnable.1 env: %d\n", (int)(NULL!=env));
if(NULL!=env) {
DBG_PRINT2("MainRunnable.1.0\n");
@@ -813,11 +806,9 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_Uns
DBG_PRINT2("MainRunnable.1.1\n");
(*env)->DeleteGlobalRef(env, runnableObj);
- if (shallBeDetached) {
- DBG_PRINT2("MainRunnable.1.3\n");
- // Keep attached on main thread !
- // (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ DBG_PRINT2("MainRunnable.1.3\n");
+ // detaching thread not required - daemon
+ // NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
}
DBG_PRINT2("MainRunnable.X\n");
}
@@ -861,17 +852,8 @@ static void RunOnThread (JNIEnv *env, jobject runnable, BOOL onMain, jint delayI
if ( forkOnMain ) {
jobject runnableObj = (*env)->NewGlobalRef(env, runnable);
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
-
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- } else {
- jvmVersion = (*env)->GetVersion(env);
- }
-
DBG_PRINT2( "RunOnThread.1.0\n");
- MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj jvmHandle: jvmHandle jvmVersion: jvmVersion];
+ MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj];
if( onMain ) {
[mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO];
diff --git a/src/nativewindow/native/win32/GDImisc.c b/src/nativewindow/native/win32/GDImisc.c
index e28f68e7d..bec1d4922 100644
--- a/src/nativewindow/native/win32/GDImisc.c
+++ b/src/nativewindow/native/win32/GDImisc.c
@@ -487,7 +487,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_DestroyWindo
JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_windows_GDIUtil_initIDs0
(JNIEnv *env, jclass gdiClazz)
{
- if(NativewindowCommon_init(env)) {
+ if( NativewindowCommon_init(env) ) {
jclass c = (*env)->FindClass(env, ClazzNamePoint);
if(NULL==c) {
NativewindowCommon_FatalError(env, "FatalError jogamp_nativewindow_windows_GDIUtil: can't find %s", ClazzNamePoint);
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index 5e6909f6e..247dc1311 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -113,68 +113,56 @@ static jmethodID pointCstr = NULL;
static void _initClazzAccess(JNIEnv *env) {
jclass c;
- if(!NativewindowCommon_init(env)) return;
-
- getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11UtilClazz, "getCurrentThreadName", "()Ljava/lang/String;");
- if(NULL==getCurrentThreadNameID) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method getCurrentThreadName");
- }
- dumpStackID = (*env)->GetStaticMethodID(env, X11UtilClazz, "dumpStack", "()V");
- if(NULL==dumpStackID) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method dumpStack");
- }
-
- c = (*env)->FindClass(env, ClazzNameBuffers);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers);
- }
- clazzBuffers = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==clazzBuffers) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameBuffers);
- }
- c = (*env)->FindClass(env, ClazzNameByteBuffer);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameByteBuffer);
- }
- clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameByteBuffer);
- }
-
- cstrBuffers = (*env)->GetStaticMethodID(env, clazzBuffers,
- ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
- if(NULL==cstrBuffers) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't create %s.%s %s",
- ClazzNameBuffers, ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
- }
+ if( NativewindowCommon_init(env) ) {
+ getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11UtilClazz, "getCurrentThreadName", "()Ljava/lang/String;");
+ if(NULL==getCurrentThreadNameID) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method getCurrentThreadName");
+ }
+ dumpStackID = (*env)->GetStaticMethodID(env, X11UtilClazz, "dumpStack", "()V");
+ if(NULL==dumpStackID) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't get method dumpStack");
+ }
- c = (*env)->FindClass(env, ClazzNamePoint);
- if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNamePoint);
- }
- pointClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==pointClz) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNamePoint);
- }
- pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
- if(NULL==pointCstr) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't fetch %s.%s %s",
- ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
- }
-}
+ c = (*env)->FindClass(env, ClazzNameBuffers);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameBuffers);
+ }
+ clazzBuffers = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==clazzBuffers) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameBuffers);
+ }
+ c = (*env)->FindClass(env, ClazzNameByteBuffer);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNameByteBuffer);
+ }
+ clazzByteBuffer = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNameByteBuffer);
+ }
-static JavaVM *jvmHandle = NULL;
-static int jvmVersion = 0;
+ cstrBuffers = (*env)->GetStaticMethodID(env, clazzBuffers,
+ ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
+ if(NULL==cstrBuffers) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't create %s.%s %s",
+ ClazzNameBuffers, ClazzNameBuffersStaticCstrName, ClazzNameBuffersStaticCstrSignature);
+ }
-static void setupJVMVars(JNIEnv * env) {
- if( NULL != env && NULL == jvmHandle ) {
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
+ c = (*env)->FindClass(env, ClazzNamePoint);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't find %s", ClazzNamePoint);
+ }
+ pointClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==pointClz) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't use %s", ClazzNamePoint);
+ }
+ pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ if(NULL==pointCstr) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_x11_X11Lib: can't fetch %s.%s %s",
+ ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
}
- jvmVersion = (*env)->GetVersion(env);
}
}
@@ -201,8 +189,8 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
(int)e->request_code, (int)e->minor_code, reqCodeStr);
fflush(stderr);
- if( NULL != jvmHandle && ( errorHandlerDebug || errorHandlerThrowException ) ) {
- jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached);
+ if( errorHandlerDebug || errorHandlerThrowException ) {
+ jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached);
if(NULL == jniEnv) {
fprintf(stderr, "Nativewindow X11 Error: null JNIEnv");
fflush(stderr);
@@ -219,9 +207,7 @@ static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
(int)e->request_code, (int)e->minor_code, reqCodeStr);
}
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
}
}
@@ -233,7 +219,6 @@ static void NativewindowCommon_x11ErrorHandlerEnable(JNIEnv * env, Display *dpy,
if(onoff) {
if(force || NULL==origErrorHandler) {
XErrorHandler prevErrorHandler;
- setupJVMVars(env);
prevErrorHandler = XSetErrorHandler(x11ErrorHandler);
if(x11ErrorHandler != prevErrorHandler) { // if forced don't overwrite w/ orig w/ our handler
origErrorHandler = prevErrorHandler;
@@ -265,14 +250,10 @@ static int x11IOErrorHandler(Display *dpy)
fprintf(stderr, "Nativewindow X11 IOError: Display %p (%s): %s\n", dpy, dpyName, errnoStr);
fflush(stderr);
- if( NULL != jvmHandle ) {
- jniEnv = NativewindowCommon_GetJNIEnv(jvmHandle, jvmVersion, 0 /* asDaemon */, &shallBeDetached);
- if (NULL != jniEnv) {
- NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
- }
+ jniEnv = NativewindowCommon_GetJNIEnv(0 /* asDaemon */, &shallBeDetached);
+ if (NULL != jniEnv) {
+ NativewindowCommon_FatalError(jniEnv, "Nativewindow X11 IOError: Display %p (%s): %s", dpy, dpyName, errnoStr);
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
}
if(NULL!=origIOErrorHandler) {
origIOErrorHandler(dpy);
@@ -283,7 +264,6 @@ static int x11IOErrorHandler(Display *dpy)
static void x11IOErrorHandlerEnable(int onoff, JNIEnv * env) {
if(onoff) {
if(NULL==origIOErrorHandler) {
- setupJVMVars(env);
origIOErrorHandler = XSetIOErrorHandler(x11IOErrorHandler);
}
} else {
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index c6fd805a5..130b2e3e3 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -113,18 +113,6 @@ static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtVi
DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject);
jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject);
[view setJavaWindowObject: globJavaWindowObject];
- {
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
-
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- } else {
- jvmVersion = (*env)->GetVersion(env);
- }
- [view setJVMHandle: jvmHandle];
- [view setJVMVersion: jvmVersion];
- }
}
DBG_PRINT( "setJavaWindowObject.X: View %p\n", view);
}
@@ -979,6 +967,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0
BOOL isNewtWin = [mWin isKindOfClass:[NewtMacWindow class]];
NSWindow *pWin = [mWin parentWindow];
DBG_PRINT( "windowClose.0 - %p [isNSWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin);
+ (void)isNSWin; // silence
if( !isNewtWin ) {
NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
return;
diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c
index c294b6e0b..231d6182f 100644
--- a/src/newt/native/NewtCommon.c
+++ b/src/newt/native/NewtCommon.c
@@ -5,17 +5,43 @@
static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
static jclass runtimeExceptionClz=NULL;
+static JavaVM *_jvmHandle = NULL;
+static int _jvmVersion = 0;
+
+void NewtCommon_init(JNIEnv *env) {
+ if(NULL==_jvmHandle) {
+ if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+ NewtCommon_FatalError(env, "NEWT: Can't fetch JavaVM handle");
+ } else {
+ _jvmVersion = (*env)->GetVersion(env);
+ }
+ jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
+ if(NULL==c) {
+ NewtCommon_FatalError(env, "NEWT: Can't find %s", ClazzNameRuntimeException);
+ }
+ runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==runtimeExceptionClz) {
+ NewtCommon_FatalError(env, "NEWT: Can't use %s", ClazzNameRuntimeException);
+ }
+ }
+}
+
void NewtCommon_FatalError(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
- fprintf(stderr, "%s\n", buffer);
- (*env)->FatalError(env, buffer);
+ fprintf(stderr, "%s\n", buffer);
+ if(NULL != env) {
+ (*env)->FatalError(env, buffer);
+ }
+ }
}
void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
@@ -23,23 +49,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if(NULL==_jvmHandle) {
+ NewtCommon_FatalError(env, "NEWT: NULL JVM handle, call NewtCommon_init 1st\n");
+ return;
+ }
- (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
-}
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
-void NewtCommon_init(JNIEnv *env) {
- if(NULL==runtimeExceptionClz) {
- jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
- if(NULL==c) {
- NewtCommon_FatalError(env, "NEWT: can't find %s", ClazzNameRuntimeException);
- }
- runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==runtimeExceptionClz) {
- NewtCommon_FatalError(env, "NEWT: can't use %s", ClazzNameRuntimeException);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
}
}
}
@@ -65,42 +86,57 @@ const char * NewtCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmet
jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
{
jchar* strChars = NULL;
- strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
- if (strChars != NULL) {
- (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ if( NULL != env && 0 != str ) {
+ strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
+ if (strChars != NULL) {
+ (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ }
}
return strChars;
}
-JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached) {
+JNIEnv* NewtCommon_GetJNIEnv(int asDaemon, int * shallBeDetached) {
JNIEnv* curEnv = NULL;
JNIEnv* newEnv = NULL;
int envRes;
+ if(NULL==_jvmHandle) {
+ fprintf(stderr, "NEWT GetJNIEnv: NULL JVM handle, call NewtCommon_init 1st\n");
+ return NULL;
+ }
+
// retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
+ envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ;
if( JNI_EDETACHED == envRes ) {
// detached thread - attach to JVM
if( asDaemon ) {
- envRes = (*jvmHandle)->AttachCurrentThreadAsDaemon(jvmHandle, (void**) &newEnv, NULL);
+ envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL);
} else {
- envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL);
+ envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL);
}
if( JNI_OK != envRes ) {
- fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
+ fprintf(stderr, "NEWT GetJNIEnv: Can't attach thread: %d\n", envRes);
return NULL;
}
curEnv = newEnv;
} else if( JNI_OK != envRes ) {
// oops ..
- fprintf(stderr, "can't GetEnv: %d\n", envRes);
+ fprintf(stderr, "NEWT GetJNIEnv: Can't GetEnv: %d\n", envRes);
return NULL;
}
if (curEnv==NULL) {
- fprintf(stderr, "env is NULL\n");
+ fprintf(stderr, "NEWT GetJNIEnv: env is NULL\n");
return NULL;
}
*shallBeDetached = NULL != newEnv;
return curEnv;
}
+void NewtCommon_ReleaseJNIEnv (int shallBeDetached) {
+ if(NULL == _jvmHandle) {
+ fprintf(stderr, "NEWT ReleaseJNIEnv: No JavaVM handle registered, call NewtCommon_init(..) 1st");
+ } else if(shallBeDetached) {
+ (*_jvmHandle)->DetachCurrentThread(_jvmHandle);
+ }
+}
+
diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h
index 9cc9e93a6..43db72b5b 100644
--- a/src/newt/native/NewtCommon.h
+++ b/src/newt/native/NewtCommon.h
@@ -42,23 +42,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
/**
*
- * 1) Store jvmHandle and jvmVersion
+ * 1) Init static jvmHandle, jvmVersion and clazz references
+ * from an early initialization call w/ valid 'JNIEnv * env'
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
-
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- } else {
- jvmVersion = (*env)->GetVersion(env);
- }
+ NewtCommon_init(env);
*
* 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv
*
+ int asDaemon = 0;
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("drawRect: null JNIEnv\n");
return;
@@ -70,12 +65,13 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
.. your JNIEnv code here ..
*
- * 4) Detach thread from JVM, if required
+ * 4) Detach thread from JVM if required, i.e. not attached as daemon!
+ * Not recommended for recurring _daemon_ threads (performance)
*
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
*/
-JNIEnv* NewtCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int asDaemon, int * shallBeDetached);
+JNIEnv* NewtCommon_GetJNIEnv (int asDaemon, int * shallBeDetached);
+
+void NewtCommon_ReleaseJNIEnv (int shallBeDetached);
#endif
diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h
index daf75bec7..8f6362ac2 100644
--- a/src/newt/native/NewtMacWindow.h
+++ b/src/newt/native/NewtMacWindow.h
@@ -53,10 +53,6 @@
{
jobject javaWindowObject;
- // This is set while messages are being dispatched and cleared afterward
- JavaVM *jvmHandle;
- int jvmVersion;
-
volatile BOOL destroyNotifySent;
volatile int softLockCount;
pthread_mutex_t softLockSync;
@@ -80,12 +76,6 @@
#endif
- (void) dealloc;
-/* Set during event dispatching cycle */
-- (void) setJVMHandle: (JavaVM*) vm;
-- (JavaVM*) getJVMHandle;
-- (void) setJVMVersion: (int) ver;
-- (int) getJVMVersion;
-
/* Register or deregister (NULL) the java Window object,
ie, if NULL, no events are send */
- (void) setJavaWindowObject: (jobject) javaWindowObj;
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
index 5ccd9c658..b4133ac7e 100644
--- a/src/newt/native/NewtMacWindow.m
+++ b/src/newt/native/NewtMacWindow.m
@@ -193,8 +193,6 @@ static jmethodID windowRepaintID = NULL;
id res = [super initWithFrame:frameRect];
javaWindowObject = NULL;
- jvmHandle = NULL;
- jvmVersion = 0;
destroyNotifySent = NO;
softLockCount = 0;
@@ -244,25 +242,6 @@ static jmethodID windowRepaintID = NULL;
[super dealloc];
}
-- (void) setJVMHandle: (JavaVM*) vm
-{
- jvmHandle = vm;
-}
-- (JavaVM*) getJVMHandle
-{
- return jvmHandle;
-}
-
-- (void) setJVMVersion: (int) ver
-{
- jvmVersion = ver;
-}
-
-- (int) getJVMVersion
-{
- return jvmVersion;
-}
-
- (void) setJavaWindowObject: (jobject) javaWindowObj
{
javaWindowObject = javaWindowObj;
@@ -342,7 +321,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("drawRect: null JNIEnv\n");
return;
@@ -354,9 +333,8 @@ static jmethodID windowRepaintID = NULL;
dirtyRect.origin.x, viewFrame.size.height - dirtyRect.origin.y,
dirtyRect.size.width, dirtyRect.size.height);
- /* if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- } */
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (void) viewDidHide
@@ -366,7 +344,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("viewDidHide: null JNIEnv\n");
return;
@@ -374,9 +352,8 @@ static jmethodID windowRepaintID = NULL;
(*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_FALSE);
- /* if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- } */
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
[super viewDidHide];
}
@@ -388,7 +365,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, 1 /* asDaemon */, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("viewDidUnhide: null JNIEnv\n");
return;
@@ -396,9 +373,8 @@ static jmethodID windowRepaintID = NULL;
(*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_TRUE);
- /* if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- } */
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
[super viewDidUnhide];
}
@@ -645,14 +621,9 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env;
- if( NULL != jvmHandle ) {
- env = NewtCommon_GetJNIEnv(jvmHandle, [self getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
- } else {
- env = NULL;
- }
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
- DBG_PRINT("sendMouseEvent: JVM %p JNIEnv %p\n", jvmHandle, env);
+ DBG_PRINT("sendMouseEvent: null JNIEnv\n");
return;
}
jint javaMods[] = { 0 } ;
@@ -700,9 +671,8 @@ static jmethodID windowRepaintID = NULL;
(jint) location.x, (jint) location.y,
javaButtonNum, scrollDeltaY);
- /* if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- } */
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p
@@ -754,14 +724,9 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env;
- if( NULL != jvmHandle ) {
- env = NewtCommon_GetJNIEnv(jvmHandle, [self getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
- } else {
- env = NULL;
- }
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
- DBG_PRINT("sendKeyEvent: JVM %p JNIEnv %p\n", jvmHandle, env);
+ DBG_PRINT("sendKeyEvent: null JNIEnv\n");
return;
}
@@ -792,9 +757,8 @@ static jmethodID windowRepaintID = NULL;
evType, javaMods, keyCode, keyChar, keyChar);
}
- /* if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- } */
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
@end
@@ -1038,23 +1002,16 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [newtView getJVMHandle];
- JNIEnv* env;
- if( NULL != jvmHandle ) {
- env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
- } else {
- env = NULL;
- }
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
- DBG_PRINT("focusChanged: JVM %p JNIEnv %p\n", jvmHandle, env);
+ DBG_PRINT("focusChanged: null JNIEnv\n");
return;
}
(*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
- /* if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- } */
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (void) keyDown: (NSEvent*) theEvent
@@ -1147,37 +1104,31 @@ static jmethodID windowRepaintID = NULL;
- (void)windowDidResize: (NSNotification*) notification
{
- JNIEnv* env = NULL;
jobject javaWindowObject = NULL;
int shallBeDetached = 0;
- JavaVM *jvmHandle = NULL;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if( NULL == env ) {
+ DBG_PRINT("windowDidResize: null JNIEnv\n");
+ return;
+ }
NewtView* newtView = (NewtView *) [self contentView];
if( [newtView isKindOfClass:[NewtView class]] ) {
javaWindowObject = [newtView getJavaWindowObject];
- if (javaWindowObject != NULL) {
- jvmHandle = [newtView getJVMHandle];
- if( NULL != jvmHandle ) {
- env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
- }
- }
}
+ if( NULL != javaWindowObject ) {
+ // update insets on every window resize for lack of better hook place
+ [self updateInsets: env jwin:javaWindowObject];
- // update insets on every window resize for lack of better hook place
- [self updateInsets: env jwin:javaWindowObject];
-
- if( NULL != env && NULL != javaWindowObject ) {
NSRect frameRect = [self frame];
NSRect contentRect = [self contentRectForFrameRect: frameRect];
(*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE,
(jint) contentRect.size.width,
(jint) contentRect.size.height, JNI_FALSE);
-
- /* if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- } */
}
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (void)windowDidMove: (NSNotification*) notification
@@ -1192,15 +1143,9 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [newtView getJVMHandle];
- JNIEnv* env;
- if( NULL != jvmHandle ) {
- env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
- } else {
- env = NULL;
- }
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
- DBG_PRINT("windowDidMove: JVM %p JNIEnv %p\n", jvmHandle, env);
+ DBG_PRINT("windowDidMove: null JNIEnv\n");
return;
}
@@ -1208,9 +1153,8 @@ static jmethodID windowRepaintID = NULL;
p0 = [self getLocationOnScreen: p0];
(*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_FALSE, (jint) p0.x, (jint) p0.y);
- /* if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- } */
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (BOOL)windowShouldClose: (id) sender
@@ -1226,13 +1170,12 @@ static jmethodID windowRepaintID = NULL;
- (BOOL) windowClosingImpl: (BOOL) force
{
jboolean closed = JNI_FALSE;
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* newtView = (NewtView *) [self contentView];
if( ! [newtView isKindOfClass:[NewtView class]] ) {
return NO;
}
-
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[newtView cursorHide: NO enter: -1];
if( false == [newtView getDestroyNotifySent] ) {
@@ -1240,26 +1183,16 @@ static jmethodID windowRepaintID = NULL;
DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject);
if (javaWindowObject == NULL) {
DBG_PRINT("windowWillClose: null javaWindowObject\n");
+ [pool release];
return NO;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [newtView getJVMHandle];
- JNIEnv* env = NULL;
-NS_DURING
- if( NULL != jvmHandle ) {
- env = NewtCommon_GetJNIEnv(jvmHandle, [newtView getJVMVersion], 1 /* asDaemon */, &shallBeDetached);
- }
-NS_HANDLER
- jvmHandle = NULL;
- env = NULL;
- [newtView setJVMHandle: NULL];
- DBG_PRINT("windowWillClose: JVMHandler Exception\n");
-NS_ENDHANDLER
- DBG_PRINT("windowWillClose: JVM %p JNIEnv %p\n", jvmHandle, env);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
+ DBG_PRINT("windowWillClose: null JNIEnv\n");
+ [pool release];
return NO;
}
-
[newtView setDestroyNotifySent: true]; // earmark assumption of being closed
closed = (*env)->CallBooleanMethod(env, javaWindowObject, windowDestroyNotifyID, force ? JNI_TRUE : JNI_FALSE);
if(!force && !closed) {
@@ -1267,9 +1200,8 @@ NS_ENDHANDLER
[newtView setDestroyNotifySent: false];
}
- /* if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- } */
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed);
} else {
DBG_PRINT( "*************** windowWillClose (skip)\n");
--
cgit v1.2.3