diff options
Diffstat (limited to 'src/jogl')
91 files changed, 3676 insertions, 2222 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java index d162f2bd8..8cb25174c 100644 --- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java +++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java @@ -70,7 +70,7 @@ public class JoglVersion extends JogampVersion { public static StringBuilder getGLInfo(GL gl, StringBuilder sb) { AbstractGraphicsDevice device = gl.getContext().getGLDrawable().getNativeSurface() - .getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + .getGraphicsConfiguration().getScreen().getDevice(); if(null==sb) { sb = new StringBuilder(); } diff --git a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java index 9e4d76869..ba159b82c 100644 --- a/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/com/jogamp/opengl/cg/CgDynamicLibraryBundleInfo.java @@ -28,12 +28,30 @@ package com.jogamp.opengl.cg; +import com.jogamp.common.jvm.JNILibLoaderBase; import com.jogamp.common.os.DynamicLibraryBundleInfo; +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.cache.TempJarCache; + +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.*; public class CgDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { private static List<String> glueLibNames; static { + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Platform.initSingleton(); + + if(TempJarCache.isInitialized()) { + // Cg class and natives are available in their single atomic JAR files only + JNILibLoaderBase.addNativeJarLibs(CgDynamicLibraryBundleInfo.class, "jogl_cg", null); + } + return null; + } + }); + glueLibNames = new ArrayList<String>(); // glueLibNames.addAll(getGlueLibNamesPreload()); glueLibNames.add("jogl_cg"); diff --git a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java index 93b75e70b..26d299663 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java @@ -164,7 +164,7 @@ class AWTAnimatorImpl implements AnimatorBase.AnimatorImpl { } }; - public boolean skipWaitForCompletion(Thread thread) { - return ((Thread.currentThread() == thread) || EventQueue.isDispatchThread()); + public boolean blockUntilDone(Thread thread) { + return ((Thread.currentThread() != thread) && !EventQueue.isDispatchThread()); } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java index 16aac957a..6d508f227 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/Animator.java +++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java @@ -59,7 +59,9 @@ import javax.media.opengl.GLAutoDrawable; */ public class Animator extends AnimatorBase { - + /** timeout in milliseconds, 15 frames @ 60Hz = 240ms, limiting {@link #finishLifecycleAction(Condition)} */ + private static final long TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION = 15*16; + protected ThreadGroup threadGroup; private Runnable runnable; private boolean runAsFastAsPossible; @@ -241,18 +243,24 @@ public class Animator extends AnimatorBase { // dependencies on the Animator's internal thread. Currently we // use a couple of heuristics to determine whether we should do // the blocking wait(). - boolean doWait = !impl.skipWaitForCompletion(animThread); - if (doWait) { - while (condition.result()) { - try { - wait(); - } catch (InterruptedException ie) { } - } + final boolean blocking = impl.blockUntilDone(animThread); + long remaining = blocking ? TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION : 0; + while (remaining>0 && condition.result()) { + long td = System.currentTimeMillis(); + try { + wait(remaining); + } catch (InterruptedException ie) { } + remaining -= (System.currentTimeMillis() - td) ; } if(DEBUG) { - System.err.println("finishLifecycleAction(" + condition.getClass().getName() + "): finished - waited " + doWait + + if(remaining<0) { + System.err.println("finishLifecycleAction(" + condition.getClass().getName() + "): ++++++ timeout reached ++++++ " + Thread.currentThread().getName()); + } + System.err.println("finishLifecycleAction(" + condition.getClass().getName() + "): finished "+ + "- blocking "+blocking+ + ", waited " + (blocking ? ( TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION - remaining ) : 0 ) + "/" + TO_WAIT_FOR_FINISH_LIFECYCLE_ACTION + ", started: " + isStartedImpl() +", animating: " + isAnimatingImpl() + - ", paused: " + isPausedImpl() + ", drawables " + drawables.size()); + ", paused: " + isPausedImpl() + ", drawables " + drawables.size() + " - " + Thread.currentThread().getName()); } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java index e84a9bf78..d65967da1 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java +++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorBase.java @@ -56,7 +56,7 @@ public abstract class AnimatorBase implements GLAnimatorControl { public interface AnimatorImpl { void display(ArrayList<GLAutoDrawable> drawables, boolean ignoreExceptions, boolean printExceptions); - boolean skipWaitForCompletion(Thread thread); + boolean blockUntilDone(Thread thread); } protected ArrayList<GLAutoDrawable> drawables = new ArrayList<GLAutoDrawable>(); @@ -92,7 +92,7 @@ public abstract class AnimatorBase implements GLAnimatorControl { public synchronized void add(GLAutoDrawable drawable) { if(DEBUG) { - System.err.println("Animator add: "+drawable.hashCode()+" - "+Thread.currentThread()); + System.err.println("Animator add: "+drawable.hashCode()+" - "+Thread.currentThread().getName()); } boolean paused = pause(); drawables.add(drawable); @@ -101,7 +101,7 @@ public abstract class AnimatorBase implements GLAnimatorControl { if(paused) { resume(); } - if(!impl.skipWaitForCompletion(animThread)) { + if(impl.blockUntilDone(animThread)) { while(isStarted() && !isPaused() && !isAnimating()) { try { wait(); @@ -113,7 +113,7 @@ public abstract class AnimatorBase implements GLAnimatorControl { public synchronized void remove(GLAutoDrawable drawable) { if(DEBUG) { - System.err.println("Animator remove: "+drawable.hashCode()+" - "+Thread.currentThread() + ": "+toString()); + System.err.println("Animator remove: "+drawable.hashCode()+" - "+Thread.currentThread().getName() + ": "+toString()); } boolean paused = pause(); @@ -123,7 +123,7 @@ public abstract class AnimatorBase implements GLAnimatorControl { if(paused) { resume(); } - if(!impl.skipWaitForCompletion(animThread)) { + if(impl.blockUntilDone(animThread)) { while(isStarted() && drawablesEmpty && isAnimating()) { try { wait(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java index bad268f70..23b0845ee 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/util/DefaultAnimatorImpl.java @@ -60,7 +60,7 @@ class DefaultAnimatorImpl implements AnimatorBase.AnimatorImpl { } } - public boolean skipWaitForCompletion(Thread thread) { - return (Thread.currentThread() == thread); + public boolean blockUntilDone(Thread thread) { + return (Thread.currentThread() != thread); } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java index f2e742cda..4ab603576 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java @@ -49,9 +49,8 @@ import java.nio.*; /** * Utility routines for dealing with direct buffers. - * @author Kenneth Russel - * @author Sven Gothel - * @author Michael Bien + * + * @author Kenneth Russel, et.al. */ public class GLBuffers extends Buffers { @@ -66,7 +65,8 @@ public class GLBuffers extends Buffers { * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV (25) + * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, + * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27) * @return -1 if glType is unhandled, otherwise the actual value > 0 */ public static final int sizeOfGLType(int glType) { @@ -97,6 +97,8 @@ public class GLBuffers extends Buffers { case GL2GL3.GL_UNSIGNED_INT_24_8: case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV: case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV: + case GL2.GL_HILO16_NV: + case GL2.GL_SIGNED_HILO16_NV: return SIZEOF_INT; case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV: @@ -122,7 +124,8 @@ public class GLBuffers extends Buffers { * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV (25) + * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, + * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27) * @return null if glType is unhandled, otherwise the new Buffer object */ public static final Buffer newDirectGLBuffer(int glType, int numElements) { @@ -153,6 +156,8 @@ public class GLBuffers extends Buffers { case GL2GL3.GL_UNSIGNED_INT_24_8: case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV: case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV: + case GL2.GL_HILO16_NV: + case GL2.GL_SIGNED_HILO16_NV: return newDirectIntBuffer(numElements); case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV: @@ -178,7 +183,8 @@ public class GLBuffers extends Buffers { * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV (25) + * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, + * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27) * @return null if glType is unhandled or parent is null or bufLen is 0, otherwise the new Buffer object */ public static final Buffer sliceGLBuffer(ByteBuffer parent, int bytePos, int byteLen, int glType) { @@ -215,6 +221,8 @@ public class GLBuffers extends Buffers { case GL2GL3.GL_UNSIGNED_INT_24_8: case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV: case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV: + case GL2.GL_HILO16_NV: + case GL2.GL_SIGNED_HILO16_NV: return parent.asIntBuffer(); case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV: @@ -360,7 +368,7 @@ public class GLBuffers extends Buffers { * GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_ABGR_EXT, * GL_RED_INTEGER, GL_GREEN_INTEGER, GL_BLUE_INTEGER, * GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER, - * GL_RGBA_INTEGER, GL_BGRA_INTEGER (24) + * GL_RGBA_INTEGER, GL_BGRA_INTEGER, GL_HILO_NV, GL_SIGNED_HILO_NV (26) * * @param type must be one of * GL_BITMAP, @@ -373,7 +381,8 @@ public class GLBuffers extends Buffers { * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV (26) + * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, + * GL_HILO16_NV, GL_SIGNED_HILO16_NV (28) * * @param width in pixels * @param height in pixels @@ -410,6 +419,8 @@ public class GLBuffers extends Buffers { case GL.GL_LUMINANCE_ALPHA: case GL2GL3.GL_RG: case GL2GL3.GL_RG_INTEGER: + case GL2.GL_HILO_NV: + case GL2.GL_SIGNED_HILO_NV: elements = 2; break; case GL.GL_RGB: @@ -470,6 +481,11 @@ public class GLBuffers extends Buffers { esize = 2; elements = 1; break; + case GL2.GL_HILO16_NV: + case GL2.GL_SIGNED_HILO16_NV: + esize = 2; + elements = 2; + break; case GL2GL3.GL_UNSIGNED_INT_8_8_8_8: case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV: case GL2GL3.GL_UNSIGNED_INT_10_10_10_2: @@ -491,6 +507,19 @@ public class GLBuffers extends Buffers { return sizeof(gl, tmp, elements * esize, width, height, depth, pack); } + + public static final int getNextPowerOf2(int number) { + if (((number-1) & number) == 0) { + //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0 + return number; + } + int power = 0; + while (number > 0) { + number = number>>1; + power++; + } + return (1<<power); + } //---------------------------------------------------------------------- // Conversion routines diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java index b6df365ba..7f3aa8a39 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java @@ -1055,9 +1055,7 @@ public class Texture { // Helper routines for disabling certain codepaths private static boolean haveNPOT(GL gl) { - return (!disableNPOT && - ( gl.isGLES2() || - gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two") ) ); + return !disableNPOT && gl.isNPOTTextureAvailable(); } private static boolean haveTexRect(GL gl) { diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index f93d443e0..534e449bc 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -294,6 +294,17 @@ public interface GLBase { */ public boolean isExtensionAvailable(String glExtensionName); + /** + * Returns true if the GL context supports non power of two (NPOT) textures, + * otherwise false. + * <p> + * NPOT textures are supported in OpenGL >= 3, GLES2 or if the + * 'GL_ARB_texture_non_power_of_two' extension is available. + * </p> + * @return + */ + public boolean isNPOTTextureAvailable(); + /** Provides a platform-independent way to specify the minimum swap interval for buffer swaps. An argument of 0 disables sync-to-vertical-refresh completely, while an argument of 1 diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index 9d99a32ff..8626400f7 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -45,9 +45,12 @@ import java.security.AccessControlContext; import java.security.AccessController; import java.util.HashMap; import java.util.HashSet; + import javax.media.nativewindow.AbstractGraphicsDevice; import com.jogamp.common.util.IntObjectHashMap; +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; @@ -65,7 +68,8 @@ import jogamp.opengl.GLContextImpl; abstraction provides a stable object which clients can use to refer to a given context. */ public abstract class GLContext { - + public static final boolean DEBUG = Debug.debug("GLContext"); + /** Reflects property jogl.debug.DebugGL. If true, the debug pipeline is enabled at context creation. */ public final static boolean DEBUG_GL; /** Reflects property jogl.debug.TraceGL. If true, the trace pipeline is enabled at context creation. */ @@ -105,12 +109,15 @@ public abstract class GLContext { protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 0; /** GLContext {@link com.jogamp.gluegen.runtime.ProcAddressTable} caching related: GL hardware implementation */ protected static final int CTX_IMPL_ACCEL_HARD = 1 << 1; - + private static ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>(); private HashMap<String, Object> attachedObjectsByString = new HashMap<String, Object>(); private IntObjectHashMap attachedObjectsByInt = new IntObjectHashMap(); + // RecursiveLock maintains a queue of waiting Threads, ensuring the longest waiting thread will be notified at unlock. + protected RecursiveLock lock = LockFactory.createRecursiveLock(); + /** The underlying native OpenGL context */ protected long contextHandle; @@ -293,8 +300,11 @@ public abstract class GLContext { /** * Destroys this OpenGL context and frees its associated - * resources. The context should have been released before this - * method is called. + * resources. + * <p> + * The context may be current w/o recursion when calling <code>destroy()</code>, + * in which case this method destroys the context and releases the lock. + * </p> */ public abstract void destroy(); @@ -406,6 +416,8 @@ public abstract class GLContext { sb.append(",\n\tDrawable: "); sb.append(getGLDrawable()); } + sb.append(", lock "); + sb.append(lock.toString()); return sb; } @@ -767,12 +779,12 @@ public abstract class GLContext { /** * @see #getDeviceVersionAvailableKey(javax.media.nativewindow.AbstractGraphicsDevice, int, int) */ - protected static /*final*/ HashMap/*<DeviceVersionAvailableKey, Integer>*/ deviceVersionAvailable = new HashMap(); + protected static /*final*/ HashMap<String, Integer> deviceVersionAvailable = new HashMap<String, Integer>(); /** * @see #getUniqueDeviceString(javax.media.nativewindow.AbstractGraphicsDevice) */ - private static /*final*/ HashSet/*<UniqueDeviceString>*/ deviceVersionsAvailableSet = new HashSet(); + private static /*final*/ HashSet<String> deviceVersionsAvailableSet = new HashSet<String>(); protected static String getDeviceVersionAvailableKey(AbstractGraphicsDevice device, int major, int profile) { return device.getUniqueID() + "-" + toHexString(compose8bit(major, profile, 0, 0)); @@ -791,16 +803,18 @@ public abstract class GLContext { throw new InternalError("Already set: "+devKey); } deviceVersionsAvailableSet.add(devKey); - if (GLContextImpl.DEBUG) { + if (DEBUG) { System.err.println(getThreadName() + ": !!! createContextARB: SET mappedVersionsAvailableSet "+devKey); // Thread.dumpStack(); } } } + /** clears the device/context mappings as well as the GL/GLX proc address tables. */ protected static void shutdown() { deviceVersionAvailable.clear(); - deviceVersionsAvailableSet.clear(); + deviceVersionsAvailableSet.clear(); + GLContextImpl.shutdownImpl(); // well .. } /** @@ -824,7 +838,7 @@ public abstract class GLContext { String key = getDeviceVersionAvailableKey(device, reqMajor, profile); Integer val = new Integer(compose8bit(resMajor, resMinor, resCtp, 0)); synchronized(deviceVersionAvailable) { - val = (Integer) deviceVersionAvailable.put( key, val ); + val = deviceVersionAvailable.put( key, val ); } return val; } @@ -833,7 +847,7 @@ public abstract class GLContext { String key = getDeviceVersionAvailableKey(device, reqMajor, profile); Integer val; synchronized(deviceVersionAvailable) { - val = (Integer) deviceVersionAvailable.get( key ); + val = deviceVersionAvailable.get( key ); } return val; } @@ -875,29 +889,29 @@ public abstract class GLContext { return null != getAvailableGLVersion(device, major, profile); } - public static boolean isGLES1Available(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 1, GLContext.CTX_PROFILE_ES); - } + public static boolean isGLES1Available(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 1, GLContext.CTX_PROFILE_ES); + } - public static boolean isGLES2Available(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES); - } + public static boolean isGLES2Available(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES); + } - public static boolean isGL4bcAvailable(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT); - } + public static boolean isGL4bcAvailable(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT); + } - public static boolean isGL4Available(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 4, CTX_PROFILE_CORE); - } + public static boolean isGL4Available(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 4, CTX_PROFILE_CORE); + } - public static boolean isGL3bcAvailable(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 3, CTX_PROFILE_COMPAT); - } + public static boolean isGL3bcAvailable(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 3, CTX_PROFILE_COMPAT); + } - public static boolean isGL3Available(AbstractGraphicsDevice device) { - return isGLVersionAvailable(device, 3, CTX_PROFILE_CORE); - } + public static boolean isGL3Available(AbstractGraphicsDevice device) { + return isGLVersionAvailable(device, 3, CTX_PROFILE_CORE); + } public static boolean isGL2Available(AbstractGraphicsDevice device) { return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT); @@ -941,6 +955,10 @@ public abstract class GLContext { return sb.toString(); } + // + // internal string utils + // + protected static String toString(int val, boolean hex) { if(hex) { return "0x" + Integer.toHexString(val); diff --git a/src/jogl/classes/javax/media/opengl/GLDrawable.java b/src/jogl/classes/javax/media/opengl/GLDrawable.java index f4cd77059..2b86a04ba 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawable.java @@ -158,6 +158,12 @@ public interface GLDrawable { */ public GLProfile getGLProfile(); + /** + * Returns the underlying native surface which surface handle + * represents this OpenGL drawable's native resource. + * + * @see #getHandle() + */ public NativeSurface getNativeSurface(); /** diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index 1282eb168..3f9700436 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -47,12 +47,14 @@ import java.util.List; import com.jogamp.common.JogampRuntimeException; import jogamp.common.Debug; + import com.jogamp.common.util.ReflectionUtil; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GLProfile.ShutdownType; /** <P> Provides a virtual machine- and operating system-independent mechanism for creating {@link GLDrawable}s. </P> @@ -87,14 +89,12 @@ import javax.media.nativewindow.ProxySurface; property <code>opengl.factory.class.name</code> to the fully-qualified name of the desired class. </P> */ - public abstract class GLDrawableFactory { - private static final String nativeOSType; static final String macosxFactoryClassNameCGL = "jogamp.opengl.macosx.cgl.MacOSXCGLDrawableFactory"; static final String macosxFactoryClassNameAWTCGL = "jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLDrawableFactory"; - private static volatile boolean initialized = false; + private static volatile boolean isInit = false; private static GLDrawableFactory eglFactory; private static GLDrawableFactory nativeOSFactory; @@ -107,16 +107,20 @@ public abstract class GLDrawableFactory { /** * Instantiate singleton factories if available, EGLES1, EGLES2 and the OS native ones. */ - static { - nativeOSType = NativeWindowFactory.getNativeWindowType(true); - } - - protected static final void initialize() { - if(initialized) { return; } - initialized = true; - + public static final void initSingleton() { + if (!isInit) { // volatile: ok + synchronized (GLDrawableFactory.class) { + if (!isInit) { + isInit=true; + initSingletonImpl(); + } + } + } + } + private static final void initSingletonImpl() { registerFactoryShutdownHook(); + final String nativeOSType = NativeWindowFactory.getNativeWindowType(true); GLDrawableFactory tmp = null; String factoryClassName = Debug.getProperty("jogl.gldrawablefactory.class.name", true, AccessController.getContext()); ClassLoader cl = GLDrawableFactory.class.getClassLoader(); @@ -165,16 +169,40 @@ public abstract class GLDrawableFactory { eglFactory = tmp; } + protected static void shutdown(ShutdownType shutdownType) { + if (isInit) { // volatile: ok + synchronized (GLDrawableFactory.class) { + if (isInit) { + isInit=false; + unregisterFactoryShutdownHook(); + shutdownImpl(shutdownType); + } + } + } + } + private static void shutdownImpl(ShutdownType shutdownType) { + synchronized(glDrawableFactories) { + for(int i=0; i<glDrawableFactories.size(); i++) { + glDrawableFactories.get(i).destroy(shutdownType); + } + glDrawableFactories.clear(); + + // both were members of glDrawableFactories and are shutdown already + nativeOSFactory = null; + eglFactory = null; + } + } + private static synchronized void registerFactoryShutdownHook() { if (factoryShutdownHookRegistered) { return; } factoryShutdownHook = new Thread(new Runnable() { public void run() { - GLDrawableFactory.shutdownImpl(); + GLDrawableFactory.shutdownImpl(GLProfile.ShutdownType.COMPLETE); } }); - AccessController.doPrivileged(new PrivilegedAction() { + AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { Runtime.getRuntime().addShutdownHook(factoryShutdownHook); return null; @@ -187,7 +215,7 @@ public abstract class GLDrawableFactory { if (!factoryShutdownHookRegistered) { return; } - AccessController.doPrivileged(new PrivilegedAction() { + AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { Runtime.getRuntime().removeShutdownHook(factoryShutdownHook); return null; @@ -196,23 +224,6 @@ public abstract class GLDrawableFactory { factoryShutdownHookRegistered = false; } - private static void shutdownImpl() { - synchronized(glDrawableFactories) { - for(int i=0; i<glDrawableFactories.size(); i++) { - GLDrawableFactory factory = glDrawableFactories.get(i); - factory.shutdownInstance(); - } - glDrawableFactories.clear(); - } - } - - protected static void shutdown() { - unregisterFactoryShutdownHook(); - shutdownImpl(); - eglFactory = null; - nativeOSFactory = null; - initialized = false; - } protected GLDrawableFactory() { synchronized(glDrawableFactories) { @@ -223,7 +234,7 @@ public abstract class GLDrawableFactory { protected void enterThreadCriticalZone() {}; protected void leaveThreadCriticalZone() {}; - protected abstract void shutdownInstance(); + protected abstract void destroy(ShutdownType shutdownType); /** * Retrieve the default <code>device</code> {@link AbstractGraphicsDevice#getConnection() connection}, @@ -258,34 +269,31 @@ public abstract class GLDrawableFactory { } /** - * Returns true if a shared context could be created while initialization - * of shared resources for <code>device</code> {@link AbstractGraphicsDevice#getConnection()}.<br> - * This does not imply a shared context is mapped, but was available<br>. - * - * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device. + * Validate and start the shared resource runner thread if necessary and + * if the implementation uses it. + * + * @return the shared resource runner thread, if implementation uses it. */ - public abstract boolean getWasSharedContextCreated(AbstractGraphicsDevice device); - + protected abstract Thread getSharedResourceThread(); + /** - * Returns the shared context mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}, - * either a pre-existing or newly created, or <code>null</code> if creation failed or not supported.<br> - * Creation of the shared context is tried only once. + * Create the shared resource used internally as a reference for capabilities etc. + * <p> + * Returns true if a shared resource could be created + * for the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}.<br> + * This does not imply a shared resource is mapped (ie. made persistent), but is available in general<br>. + * </p> * * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device. + * @return true if a shared resource could been created, otherwise false. */ - public final GLContext getOrCreateSharedContext(AbstractGraphicsDevice device) { - device = validateDevice(device); - if(null!=device) { - return getOrCreateSharedContextImpl(device); - } - return null; - } - protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device); - + protected abstract boolean createSharedResource(AbstractGraphicsDevice device); + /** * Returns the sole GLDrawableFactory instance for the desktop (X11, WGL, ..) if exist or null */ public static GLDrawableFactory getDesktopFactory() { + GLProfile.initSingleton(); return nativeOSFactory; } @@ -293,6 +301,7 @@ public abstract class GLDrawableFactory { * Returns the sole GLDrawableFactory instance for EGL if exist or null */ public static GLDrawableFactory getEGLFactory() { + GLProfile.initSingleton(); return eglFactory; } diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index 20e2f2a33..6b39fe765 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -48,6 +48,8 @@ import com.jogamp.common.os.Platform; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.common.util.VersionUtil; import com.jogamp.common.util.cache.TempJarCache; +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveThreadGroupLock; import com.jogamp.nativewindow.NativeWindowVersion; import com.jogamp.opengl.JoglVersion; @@ -74,56 +76,80 @@ public class GLProfile { public static final boolean DEBUG = Debug.debug("GLProfile"); + static { + // Also initializes TempJarCache if shall be used. + Platform.initSingleton(); + } + /** - * Static one time initialization of JOGL. + * Static initialization of JOGL. * <p> * The parameter <code>firstUIActionOnProcess</code> has an impact on concurrent locking,<br> * see {@link javax.media.nativewindow.NativeWindowFactory#initSingleton(boolean) NativeWindowFactory.initSingleton(firstUIActionOnProcess)}. * </p> * <p> - * Applications shall call this methods <b>ASAP</b>, before any other UI invocation.<br> - * You may issue the call in your <code>main class</code> static block, which is the earliest point in your application/applet lifecycle, - * or within the <code>main function</code>.<br> - * In case applications are able to initialize JOGL before any other UI action,<br> - * they shall invoke this method with <code>firstUIActionOnProcess=true</code> and benefit from fast native multithreading support on all platforms if possible.</P> - * <P> - * RCP Application (Applet's, Webstart, Netbeans, ..) using JOGL may not be able to initialize JOGL - * before the first UI action.<br> - * In such case you shall invoke this method with <code>firstUIActionOnProcess=false</code>.<br> - * On some platforms, notably X11 with AWT usage, JOGL will utilize special locking mechanisms which may slow down your - * application.</P> + * Applications using this method may place it's call before any other UI invocation + * in the <code>main class</code>'s static block or within the <code>main function</code>. + * In such case, applications may pass <code>firstUIActionOnProcess=true</code> to use native toolkit locking.</P> * <P> - * Remark: NEWT is currently not affected by this behavior, ie always uses native multithreading.</P> + * RCP Application (Applet's, Webstart, Netbeans, ..) using JOGL are not be able to initialize JOGL + * before the first UI action. + * In such case you shall pass <code>firstUIActionOnProcess=false</code>.</P> * <P> - * However, in case this method is not invoked, hence GLProfile is not initialized explicitly by the user,<br> - * the first call to {@link #getDefault()}, {@link #get(java.lang.String)}, etc, will initialize with <code>firstUIActionOnProcess=false</code>,<br> - * hence without the possibility to enable native multithreading.<br> - * This is not the recommended way, since it may has a performance impact, but it allows you to run code without explicit initialization.</P> + * In case this method is not invoked, GLProfile is initialized implicit by + * the first call to {@link #getDefault()}, {@link #get(java.lang.String)} passing <code>firstUIActionOnProcess=false</code>. * <P> * * @param firstUIActionOnProcess Should be <code>true</code> if called before the first UI action of the running program, * otherwise <code>false</code>. + * + * @deprecated This method shall not need to be called for other reasons than having a defined initialization sequence. + * To ensure homogeneous behavior with application not calling this method, you shall pass <code>firstUIActionOnProcess=false</code>. + * This method is subject to be removed in future versions of JOGL. */ - public static synchronized void initSingleton(final boolean firstUIActionOnProcess) { - if(!initialized) { - initialized = true; - // run the whole static initialization privileged to speed up, - // since this skips checking further access - AccessController.doPrivileged(new PrivilegedAction<Object>() { - public Object run() { - if(TempJarCache.isInitialized()) { - String[] atomicNativeJarBaseNames = new String[] { "nativewindow", "jogl", null }; - if( ReflectionUtil.isClassAvailable("com.jogamp.newt.NewtFactory", GLProfile.class.getClassLoader()) ) { - atomicNativeJarBaseNames[2] = "newt"; - } - JNILibLoaderBase.addNativeJarLibs(GLProfile.class, "jogl.all", "jogl-all", atomicNativeJarBaseNames); - } - initProfilesForDefaultDevices(firstUIActionOnProcess); - return null; + public static void initSingleton(final boolean firstUIActionOnProcess) { + initLock.lock(); + try { + if(!initialized) { // volatile: ok + initialized = true; + if(DEBUG) { + System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName()); + Thread.dumpStack(); } - }); + + // run the whole static initialization privileged to speed up, + // since this skips checking further access + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Platform.initSingleton(); + + if(TempJarCache.isInitialized()) { + String[] atomicNativeJarBaseNames = new String[] { "nativewindow", "jogl", null }; + if( ReflectionUtil.isClassAvailable("com.jogamp.newt.NewtFactory", GLProfile.class.getClassLoader()) ) { + atomicNativeJarBaseNames[2] = "newt"; + } + JNILibLoaderBase.addNativeJarLibs(GLProfile.class, "jogl-all", atomicNativeJarBaseNames); + } + initProfilesForDefaultDevices(firstUIActionOnProcess); + return null; + } + }); + } + } finally { + initLock.unlock(); } } + + /** + * Static initialization of JOGL. + * + * <p> + * This method shall not need to be called for other reasons than having a defined initialization sequence. + * </p> + */ + public static void initSingleton() { + GLProfile.initSingleton(false); + } /** * Trigger eager initialization of GLProfiles for the given device, @@ -132,21 +158,50 @@ public class GLProfile { * @throws GLException if no profile for the given device is available. */ public static void initProfiles(AbstractGraphicsDevice device) throws GLException { - getProfileMap(device); + getProfileMap(device, true); } + /** + * Shutdown type for {@link GLProfile#shutdown(ShutdownType)}. + * <p> + * {@link #SHARED_ONLY} For thread based resources only, suitable for eg. {@link java.applet.Applet Applet} restart.<br> + * {@link #COMPLETE} Everything.<br> + * </p> + */ + public enum ShutdownType { + /* Shared thread based resources only, eg. for Applets */ + SHARED_ONLY, + /* Everything */ + COMPLETE; + } + /** * Manual shutdown method, may be called after your last JOGL use * within the running JVM.<br> * It releases all temporary created resources, ie issues {@link javax.media.opengl.GLDrawableFactory#shutdown()}.<br> - * The shutdown implementation is called via the JVM shutdown hook, if not manually invoked here.<br> - * Invoke <code>shutdown()</code> manually is recommended, due to the unreliable JVM state within the shutdown hook.<br> + * The shutdown implementation is called via the JVM shutdown hook, if not manually invoked.<br> + * <p> + * This method shall not need to be called for other reasons than issuing a proper shutdown of resources. + * </p> + * @param type the shutdown type, see {@link ShutdownType}. */ - public static synchronized void shutdown() { - if(initialized) { - initialized = false; - GLDrawableFactory.shutdown(); - GLContext.shutdown(); + public static void shutdown(ShutdownType type) { + initLock.lock(); + try { + if(initialized) { // volatile: ok + initialized = false; + if(DEBUG) { + System.err.println("GLProfile.shutdown(type: "+type+") - thread "+Thread.currentThread().getName()); + Thread.dumpStack(); + } + GLDrawableFactory.shutdown(type); + if(ShutdownType.COMPLETE == type) { + GLContext.shutdown(); + } + NativeWindowFactory.shutdown(); + } + } finally { + initLock.unlock(); } } @@ -163,12 +218,13 @@ public class GLProfile { * @return true if the profile is available for the device, otherwise false. */ public static boolean isAvailable(AbstractGraphicsDevice device, String profile) { - try { - return null != getProfileMap(device).get(profile); - } catch (GLException gle) { /* profiles for device n/a */ } - return false; + initSingleton(); + return isAvailableImpl(getProfileMap(device, false), profile); } - + private static boolean isAvailableImpl(HashMap<String /*GLProfile_name*/, GLProfile> map, String profile) { + return null != map && null != map.get(profile); + } + /** * Returns the availability of a profile on the default device. * @@ -193,74 +249,71 @@ public class GLProfile { boolean avail; StringBuffer sb = new StringBuffer(); - validateInitialization(); - + initSingleton(); + if(null==device) { device = defaultDevice; } - + final HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, false); + sb.append("GLAvailability[Native[GL4bc "); - avail=isAvailable(device, GL4bc); + avail=isAvailableImpl(map, GL4bc); sb.append(avail); if(avail) { glAvailabilityToString(device, sb, 4, GLContext.CTX_PROFILE_COMPAT); } sb.append(", GL4 "); - avail=isAvailable(device, GL4); + avail=isAvailableImpl(map, GL4); sb.append(avail); if(avail) { glAvailabilityToString(device, sb, 4, GLContext.CTX_PROFILE_CORE); } sb.append(", GL3bc "); - avail=isAvailable(device, GL3bc); + avail=isAvailableImpl(map, GL3bc); sb.append(avail); if(avail) { glAvailabilityToString(device, sb, 3, GLContext.CTX_PROFILE_COMPAT); } sb.append(", GL3 "); - avail=isAvailable(device, GL3); + avail=isAvailableImpl(map, GL3); sb.append(avail); if(avail) { glAvailabilityToString(device, sb, 3, GLContext.CTX_PROFILE_CORE); } sb.append(", GL2 "); - avail=isAvailable(device, GL2); + avail=isAvailableImpl(map, GL2); sb.append(avail); if(avail) { glAvailabilityToString(device, sb, 2, GLContext.CTX_PROFILE_COMPAT); } sb.append(", GL2ES1 "); - sb.append(isAvailable(device, GL2ES1)); + sb.append(isAvailableImpl(map, GL2ES1)); sb.append(", GLES1 "); - avail=isAvailable(device, GLES1); + avail=isAvailableImpl(map, GLES1); sb.append(avail); if(avail) { glAvailabilityToString(device, sb, 1, GLContext.CTX_PROFILE_ES); } sb.append(", GL2ES2 "); - sb.append(isAvailable(device, GL2ES2)); + sb.append(isAvailableImpl(map, GL2ES2)); sb.append(", GLES2 "); - avail=isAvailable(device, GLES2); + avail=isAvailableImpl(map, GLES2); sb.append(avail); if(avail) { glAvailabilityToString(device, sb, 2, GLContext.CTX_PROFILE_ES); } sb.append("], Profiles["); - HashMap<String /*GLProfile_name*/, GLProfile> profileMap = null; - try { - profileMap = getProfileMap(device); - } catch (GLException gle) { /* profiles for device n/a */ } - if(null != profileMap) { - for(Iterator<GLProfile> i=profileMap.values().iterator(); i.hasNext(); ) { + if(null != map) { + for(Iterator<GLProfile> i=map.values().iterator(); i.hasNext(); ) { sb.append(i.next().toString()); sb.append(", "); } @@ -275,7 +328,7 @@ public class GLProfile { return sb.toString(); } - + /** Uses the default device */ public static String glAvailabilityToString() { return glAvailabilityToString(null); @@ -596,7 +649,7 @@ public class GLProfile { if(null==profile || profile.equals("GL")) { profile = GL_DEFAULT; } - final HashMap<String /*GLProfile_name*/, GLProfile> glpMap = getProfileMap(device); + final HashMap<String /*GLProfile_name*/, GLProfile> glpMap = getProfileMap(device, true); final GLProfile glp = glpMap.get(profile); if(null == glp) { throw new GLException("Profile "+profile+" is not available on "+device+", but: "+glpMap.values()); @@ -626,7 +679,7 @@ public class GLProfile { public static GLProfile get(AbstractGraphicsDevice device, String[] profiles) throws GLException { - HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device); + HashMap<String /*GLProfile_name*/, GLProfile> map = getProfileMap(device, true); for(int i=0; i<profiles.length; i++) { String profile = profiles[i]; GLProfile glProfile = map.get(profile); @@ -1137,10 +1190,6 @@ public class GLProfile { return "GLProfile[" + getName() + "/" + getImplName() + "]"; } - static { - Platform.initSingleton(); - } - private static /*final*/ boolean isAWTAvailable; private static /*final*/ boolean hasDesktopGLFactory; @@ -1155,7 +1204,8 @@ public class GLProfile { private static /*final*/ AbstractGraphicsDevice defaultDesktopDevice; private static /*final*/ AbstractGraphicsDevice defaultEGLDevice; - static boolean initialized = false; + private static volatile boolean initialized = false; + private static RecursiveThreadGroupLock initLock = LockFactory.createRecursiveThreadGroupLock(); /** * Tries the profiles implementation and native libraries. @@ -1191,7 +1241,7 @@ public class GLProfile { // - Instantiate GLDrawableFactory incl its shared dummy drawable/context, // which will register at GLContext .. // - GLDrawableFactory.initialize(); + GLDrawableFactory.initSingleton(); Throwable t=null; // if successfull it has a shared dummy drawable and context created @@ -1295,19 +1345,24 @@ public class GLProfile { * @param device the device for which profiles shall be initialized * @return true if any profile for the device exists, otherwise false */ - private static synchronized boolean initProfilesForDevice(AbstractGraphicsDevice device) { + private static boolean initProfilesForDevice(AbstractGraphicsDevice device) { if(null == device) { return false; } - GLDrawableFactory factory = GLDrawableFactory.getFactoryImpl(device); - factory.enterThreadCriticalZone(); + initLock.lock(); try { - return initProfilesForDeviceCritical(device); + GLDrawableFactory factory = GLDrawableFactory.getFactoryImpl(device); + factory.enterThreadCriticalZone(); + try { + return initProfilesForDeviceCritical(device); + } finally { + factory.leaveThreadCriticalZone(); + } } finally { - factory.leaveThreadCriticalZone(); + initLock.unlock(); } } - private static synchronized boolean initProfilesForDeviceCritical(AbstractGraphicsDevice device) { + private static boolean initProfilesForDeviceCritical(AbstractGraphicsDevice device) { boolean isSet = GLContext.getAvailableGLVersionsSet(device); if(DEBUG) { @@ -1331,11 +1386,21 @@ public class GLProfile { // Triggers eager initialization of share context in GLDrawableFactory for the device, // hence querying all available GLProfiles - boolean desktopSharedCtxAvail = desktopFactory.getWasSharedContextCreated(device); + final Thread sharedResourceThread = desktopFactory.getSharedResourceThread(); + if(null != sharedResourceThread) { + initLock.addOwner(sharedResourceThread); + } + boolean desktopSharedCtxAvail = desktopFactory.createSharedResource(device); + if(null != sharedResourceThread) { + initLock.removeOwner(sharedResourceThread); + } + if(!desktopSharedCtxAvail) { + hasDesktopGLFactory = false; + } if (DEBUG) { System.err.println("GLProfile.initProfilesForDevice: "+device+": desktop Shared Ctx "+desktopSharedCtxAvail); } - if( null == GLContext.getAvailableGLVersion(device, 2, GLContext.CTX_PROFILE_COMPAT) ) { + if( hasDesktopGLFactory && null == GLContext.getAvailableGLVersion(device, 2, GLContext.CTX_PROFILE_COMPAT) ) { // nobody yet set the available desktop versions, see {@link GLContextImpl#makeCurrent}, // so we have to add the usual suspect GLContext.mapAvailableGLVersion(device, @@ -1350,7 +1415,22 @@ public class GLProfile { // Triggers eager initialization of share context in GLDrawableFactory for the device, // hence querying all available GLProfiles - boolean eglSharedCtxAvail = eglFactory.getWasSharedContextCreated(device); + final Thread sharedResourceThread = eglFactory.getSharedResourceThread(); + if(null != sharedResourceThread) { + initLock.addOwner(sharedResourceThread); + } + boolean eglSharedCtxAvail = eglFactory.createSharedResource(device); + if(null != sharedResourceThread) { + initLock.removeOwner(sharedResourceThread); + } + if(!eglSharedCtxAvail) { + // Remark: On Windows there is a libEGL.dll delivered w/ Chrome 15.0.874.121m and Firefox 8.0.1 + // but it seems even EGL.eglInitialize(eglDisplay, null, null) + // fails in some scenarios (eg VirtualBox 4.1.6) w/ EGL error 0x3001 (EGL_NOT_INITIALIZED). + hasEGLFactory = false; + hasGLES2Impl = false; + hasGLES1Impl = false; + } if (DEBUG) { System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail); } @@ -1423,30 +1503,20 @@ public class GLProfile { } public static AbstractGraphicsDevice getDefaultDevice() { - validateInitialization(); + initSingleton(); return defaultDevice; } public static AbstractGraphicsDevice getDefaultDesktopDevice() { - validateInitialization(); + initSingleton(); return defaultDesktopDevice; } public static AbstractGraphicsDevice getDefaultEGLDevice() { - validateInitialization(); + initSingleton(); return defaultEGLDevice; } - private static void validateInitialization() { - if(!initialized) { - synchronized(GLProfile.class) { - if(!initialized) { - initSingleton(false); - } - } - } - } - private static String array2String(String[] list) { StringBuffer msg = new StringBuffer(); msg.append("["); @@ -1608,29 +1678,38 @@ public class GLProfile { * - initialization<br< * * @param device the key 'device -> GLProfiles-Map' + * @param throwExceptionOnZeroProfile true if <code>GLException</code> shall be thrown in case of no mapped profile, otherwise false. * @return the GLProfile HashMap if exists, otherwise null * @throws GLException if no profile for the given device is available. */ - private static HashMap<String /*GLProfile_name*/, GLProfile> getProfileMap(AbstractGraphicsDevice device) throws GLException { - validateInitialization(); + private static HashMap<String /*GLProfile_name*/, GLProfile> getProfileMap(AbstractGraphicsDevice device, boolean throwExceptionOnZeroProfile) + throws GLException + { + initSingleton(); + if(null==device) { device = defaultDevice; } String deviceKey = device.getUniqueID(); HashMap<String /*GLProfile_name*/, GLProfile> map = deviceConn2ProfileMap.get(deviceKey); - if( null == map ) { - if( !initProfilesForDevice(device) ) { + if( null != map ) { + return map; + } + if( !initProfilesForDevice(device) ) { + if( throwExceptionOnZeroProfile ) { throw new GLException("No Profile available for "+device); + } else { + return null; } - if( null == deviceConn2ProfileMap.get(deviceKey) ) { - throw new InternalError("initProfilesForDevice(..) didn't issue setProfileMap(..) on "+device); - } + } + map = deviceConn2ProfileMap.get(deviceKey); + if( null == map && throwExceptionOnZeroProfile ) { + throw new InternalError("initProfilesForDevice(..) didn't setProfileMap(..) for "+device); } return map; } private static void setProfileMap(AbstractGraphicsDevice device, HashMap<String /*GLProfile_name*/, GLProfile> mappedProfiles) { - validateInitialization(); synchronized ( deviceConn2ProfileMap ) { deviceConn2ProfileMap.put(device.getUniqueID(), mappedProfiles); } diff --git a/src/jogl/classes/javax/media/opengl/GLUniformData.java b/src/jogl/classes/javax/media/opengl/GLUniformData.java index 5c9388be2..475ff4546 100644 --- a/src/jogl/classes/javax/media/opengl/GLUniformData.java +++ b/src/jogl/classes/javax/media/opengl/GLUniformData.java @@ -107,10 +107,10 @@ public class GLUniformData { if(data instanceof Buffer) { final int sz = rows*columns; final Buffer buffer = (Buffer)data; - if(buffer.limit()<sz || 0!=buffer.limit()%sz) { - throw new GLException("data buffer size invalid: new buffer limit: "+buffer.limit()+"\n\t"+this); + if(buffer.remaining()<sz || 0!=buffer.remaining()%sz) { + throw new GLException("remaining data buffer size invalid: buffer: "+buffer.toString()+"\n\t"+this); } - this.count=buffer.limit()/(rows*columns); + this.count=buffer.remaining()/(rows*columns); } else { if(isMatrix) { throw new GLException("Atom type not allowed for matrix : "+this); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index ada9f5222..cd341593e 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -59,8 +59,9 @@ import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; -import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.OffscreenLayerOption; +import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.GraphicsConfigurationFactory; @@ -92,6 +93,8 @@ import com.jogamp.opengl.JoglVersion; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; + +import jogamp.nativewindow.jawt.JAWTWindow; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableHelper; @@ -136,7 +139,7 @@ import jogamp.opengl.ThreadingImpl; */ @SuppressWarnings("serial") -public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosingProtocol { +public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosingProtocol, OffscreenLayerOption { private static final boolean DEBUG; @@ -156,6 +159,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private GLContext shareWith; private int additionalCtxCreationFlags = 0; private GraphicsDevice device; + private boolean shallUseOffscreenLayer = false; private AWTWindowClosingProtocol awtWindowClosingProtocol = new AWTWindowClosingProtocol(this, new Runnable() { @@ -250,6 +254,22 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing this.device = device; } + public void setShallUseOffscreenLayer(boolean v) { + shallUseOffscreenLayer = v; + } + + public final boolean getShallUseOffscreenLayer() { + return shallUseOffscreenLayer; + } + + public final boolean isOffscreenLayerSurfaceEnabled() { + if(null != drawable) { + return ((JAWTWindow)drawable.getNativeSurface()).isOffscreenLayerSurfaceEnabled(); + } + return false; + } + + /** * Overridden to choose a GraphicsConfiguration on a parent container's * GraphicsDevice because both devices @@ -279,7 +299,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing * otherwise it is from an ancestor component that this Canvas is being * added to, and we go into this block. */ - GraphicsConfiguration chosen = awtConfig.getGraphicsConfiguration(); + GraphicsConfiguration chosen = awtConfig.getAWTGraphicsConfiguration(); if (gc != null && chosen != null && !chosen.equals(gc)) { /* @@ -308,7 +328,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing AWTGraphicsConfiguration config = chooseGraphicsConfiguration( (GLCapabilitiesImmutable)awtConfig.getChosenCapabilities(), (GLCapabilitiesImmutable)awtConfig.getRequestedCapabilities(), chooser, gc.getDevice()); - final GraphicsConfiguration compatible = (null!=config)?config.getGraphicsConfiguration():null; + final GraphicsConfiguration compatible = (null!=config)?config.getAWTGraphicsConfiguration():null; boolean equalCaps = config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities()); if(DEBUG) { Exception e = new Exception("Info: Call Stack: "+Thread.currentThread().getName()); @@ -406,15 +426,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private void dispose(boolean regenerate) { drawableSync.lock(); try { + final GLAnimatorControl animator = getAnimator(); if(DEBUG) { - Exception ex1 = new Exception("Info: dispose("+regenerate+") - start, hasContext " + - (null!=context) + ", hasDrawable " + (null!=drawable)); + Exception ex1 = new Exception("Info: dispose("+regenerate+") - START, hasContext " + + (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator); ex1.printStackTrace(); } if(null!=context) { boolean animatorPaused = false; - GLAnimatorControl animator = getAnimator(); if(null!=animator) { // can't remove us from animator for recreational addNotify() animatorPaused = animator.pause(); @@ -422,37 +442,38 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing disposeRegenerate=regenerate; - if (Threading.isSingleThreaded() && - !Threading.isOpenGLThread()) { - // Workaround for termination issues with applets -- - // sun.applet.AppletPanel should probably be performing the - // remove() call on the EDT rather than on its own thread - // Hint: User should run remove from EDT. - if (ThreadingImpl.isAWTMode() && - Thread.holdsLock(getTreeLock())) { - // The user really should not be invoking remove() from this - // thread -- but since he/she is, we can not go over to the - // EDT at this point. Try to destroy the context from here. - if(context.isCreated()) { - drawableHelper.invokeGL(drawable, context, disposeAction, null); + if(context.isCreated()) { + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + // Workaround for termination issues with applets -- + // sun.applet.AppletPanel should probably be performing the + // remove() call on the EDT rather than on its own thread + // Hint: User should run remove from EDT. + if (ThreadingImpl.isAWTMode() && + Thread.holdsLock(getTreeLock())) { + // The user really should not be invoking remove() from this + // thread -- but since he/she is, we can not go over to the + // EDT at this point. Try to destroy the context from here. + drawableHelper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction); + } else { + Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction); + } + } else { + drawableHelper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction); } - } else if(context.isCreated()) { - Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction); - } - } else if(context.isCreated()) { - drawableHelper.invokeGL(drawable, context, disposeAction, null); } if(animatorPaused) { animator.resume(); } } + if(!regenerate) { disposeAbstractGraphicsDevice(); } if(DEBUG) { - System.err.println("dispose("+regenerate+") - stop"); + System.err.println("dispose("+regenerate+") - END, "+animator); } } finally { drawableSync.unlock(); @@ -532,15 +553,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing throw new GLException("Error: NULL AWTGraphicsConfiguration"); } - if (!Beans.isDesignTime()) { - // no lock required, since this resource ain't available yet - drawable = GLDrawableFactory.getFactory(capsReqUser.getGLProfile()) - .createGLDrawable(NativeWindowFactory.getNativeWindow(this, awtConfig)); - context = (GLContextImpl) drawable.createContext(shareWith); - context.setSynchronized(true); - context.setContextCreationFlags(additionalCtxCreationFlags); - } - // before native peer is valid: X11 disableBackgroundErase(); @@ -550,6 +562,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // after native peer is valid: Windows disableBackgroundErase(); + if (!Beans.isDesignTime()) { + createDrawableAndContext(); + } + // init drawable by paint/display makes the init sequence more equal // for all launch flavors (applet/javaws/..) // validateGLDrawable(); @@ -562,6 +578,21 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } } + private void createDrawableAndContext() { + // no lock required, since this resource ain't available yet + final JAWTWindow jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig); + jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); + jawtWindow.lockSurface(); + try { + drawable = GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow); + context = (GLContextImpl) drawable.createContext(shareWith); + context.setSynchronized(true); + context.setContextCreationFlags(additionalCtxCreationFlags); + } finally { + jawtWindow.unlockSurface(); + } + } + private boolean validateGLDrawable() { boolean realized = false; if (!Beans.isDesignTime()) { @@ -636,7 +667,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public void reshape(int x, int y, int width, int height) { super.reshape(x, y, width, height); - sendReshape = true; + if(null != drawable && drawable.isRealized() && !drawable.getChosenGLCapabilities().isOnscreen()) { + dispose(true); + } else { + sendReshape = true; + } } /** <B>Overrides:</B> @@ -800,63 +835,60 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } } - class DisposeAction implements Runnable { + class PostDisposeAction implements Runnable { public void run() { - drawableHelper.dispose(GLCanvas.this); - - if(null!=context) { - context.makeCurrent(); // implicit wait for lock .. - context.destroy(); - context=null; - } - + context=null; if(null!=drawable) { + final JAWTWindow jawtWindow = (JAWTWindow)drawable.getNativeSurface(); drawable.setRealized(false); drawable=null; + if(null!=jawtWindow) { + jawtWindow.destroy(); + } } - + if(disposeRegenerate) { - // recreate GLDrawable to reflect it's new graphics configuration - drawable = GLDrawableFactory.getFactory(capsReqUser.getGLProfile()) - .createGLDrawable(NativeWindowFactory.getNativeWindow(GLCanvas.this, awtConfig)); + // Similar process as in addNotify()! + + // Recreate GLDrawable/GLContext to reflect it's new graphics configuration + createDrawableAndContext(); + if(DEBUG) { System.err.println("GLCanvas.dispose(true): new drawable: "+drawable); } - drawable.setRealized(true); - context = (GLContextImpl) drawable.createContext(shareWith); - context.setSynchronized(true); - sendReshape=true; // ensure a reshape is being send .. + validateGLDrawable(); // immediate attempt to recreate the drawable } } } private boolean disposeRegenerate; - private DisposeAction disposeAction = new DisposeAction(); + private PostDisposeAction postDisposeAction = new PostDisposeAction(); private DisposeOnEventDispatchThreadAction disposeOnEventDispatchThreadAction = new DisposeOnEventDispatchThreadAction(); class DisposeOnEventDispatchThreadAction implements Runnable { public void run() { - drawableHelper.invokeGL(drawable, context, disposeAction, null); + drawableHelper.disposeGL(GLCanvas.this, drawable, context, postDisposeAction); } } class DisposeAbstractGraphicsDeviceAction implements Runnable { public void run() { - AbstractGraphicsConfiguration aconfig = (null!=awtConfig) ? awtConfig.getNativeGraphicsConfiguration() : null; - AbstractGraphicsScreen ascreen = (null!=aconfig) ? aconfig.getScreen() : null; - AbstractGraphicsDevice adevice = (null!=ascreen) ? ascreen.getDevice() : null; - if(null!=adevice) { - String adeviceMsg=null; + if(null != awtConfig) { + final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration(); + final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + final String adeviceMsg; if(DEBUG) { adeviceMsg = adevice.toString(); + } else { + adeviceMsg = null; } boolean closed = adevice.close(); if(DEBUG) { System.err.println(Thread.currentThread().getName() + " - GLCanvas.dispose(false): closed GraphicsDevice: "+adeviceMsg+", result: "+closed); } + awtConfig=null; } - awtConfig=null; } } private DisposeAbstractGraphicsDeviceAction disposeAbstractGraphicsDeviceAction = new DisposeAbstractGraphicsDeviceAction(); @@ -1001,7 +1033,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing return null; } - final AbstractGraphicsScreen aScreen = AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT); + final AbstractGraphicsScreen aScreen = null != device ? + AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT): + AWTGraphicsScreen.createDefault(); AWTGraphicsConfiguration config = null; if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) { @@ -1045,7 +1079,6 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // System.err.println(NativeWindowVersion.getInstance()); System.err.println(JoglVersion.getInstance()); - GLProfile.initSingleton(false); GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory(); List<GLCapabilitiesImmutable> availCaps = factory.getAvailableCapabilities(null); for(int i=0; i<availCaps.size(); i++) { @@ -1053,9 +1086,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDesktopDevice()) ); - Frame frame = new Frame("JOGL AWT Test"); + final Frame frame = new Frame("JOGL AWT Test"); - GLCanvas glCanvas = new GLCanvas(caps); + final GLCanvas glCanvas = new GLCanvas(caps); frame.add(glCanvas); frame.setSize(128, 128); @@ -1064,24 +1097,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing GL gl = drawable.getGL(); System.err.println(JoglVersion.getGLInfo(gl, null)); } - - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - } - - public void display(GLAutoDrawable drawable) { - } - - public void dispose(GLAutoDrawable drawable) { - } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + public void display(GLAutoDrawable drawable) { } + public void dispose(GLAutoDrawable drawable) { } }); - final Frame _frame = frame; - final GLCanvas _glCanvas = glCanvas; - try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.setVisible(true); + frame.setVisible(true); }}); } catch (Throwable t) { t.printStackTrace(); @@ -1090,9 +1114,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { - _frame.setVisible(false); - _frame.remove(_glCanvas); - _frame.dispose(); + frame.dispose(); }}); } catch (Throwable t) { t.printStackTrace(); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 92be62b4d..7a87882ca 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -82,7 +82,10 @@ import javax.media.opengl.GLPbuffer; import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; import javax.media.opengl.Threading; + import com.jogamp.opengl.util.FBObject; +import com.jogamp.opengl.util.GLBuffers; + import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableFactoryImpl; @@ -123,9 +126,9 @@ import jogamp.opengl.awt.Java2DGLContext; * </P> */ +@SuppressWarnings("serial") public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("GLJPanel"); - private static final boolean VERBOSE = Debug.verbose(); private GLDrawableHelper drawableHelper = new GLDrawableHelper(); private volatile boolean isInitialized; @@ -268,70 +271,51 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } } - protected void dispose(boolean regenerate) { + protected void dispose() { if(DEBUG) { - Exception ex1 = new Exception("Info: dispose("+regenerate+") - start"); - ex1.printStackTrace(); + System.err.println("Info: dispose() - start - "+Thread.currentThread().getName()); + Thread.dumpStack(); } - if (backend != null) { + if (backend != null && backend.getContext() != null) { boolean animatorPaused = false; GLAnimatorControl animator = getAnimator(); if(null!=animator) { - if(regenerate) { - animatorPaused = animator.pause(); - } - } - - disposeRegenerate=regenerate; - disposeContext=backend.getContext(); - disposeDrawable=backend.getDrawable(); - - if (Threading.isSingleThreaded() && - !Threading.isOpenGLThread()) { - // Workaround for termination issues with applets -- - // sun.applet.AppletPanel should probably be performing the - // remove() call on the EDT rather than on its own thread - if (ThreadingImpl.isAWTMode() && - Thread.holdsLock(getTreeLock())) { - // The user really should not be invoking remove() from this - // thread -- but since he/she is, we can not go over to the - // EDT at this point. Try to destroy the context from here. - if(disposeContext.isCreated()) { - drawableHelper.invokeGL(disposeDrawable, disposeContext, disposeAction, null); - } - } else if(disposeContext.isCreated()) { - Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction); - } - } else if(disposeContext.isCreated()) { - drawableHelper.invokeGL(disposeDrawable, disposeContext, disposeAction, null); + animatorPaused = animator.pause(); } - if(!regenerate) { - AbstractGraphicsDevice adevice = disposeDrawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); - String adeviceMsg=null; - if(DEBUG) { - adeviceMsg = adevice.toString(); - } - // boolean closed = adevice.close(); - boolean closed = false; - if (DEBUG) { - System.err.println("GLJPanel.dispose(false): closed GraphicsDevice: " + adeviceMsg + ", result: " + closed); + if(backend.getContext().isCreated()) { + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + // Workaround for termination issues with applets -- + // sun.applet.AppletPanel should probably be performing the + // remove() call on the EDT rather than on its own thread + if (ThreadingImpl.isAWTMode() && + Thread.holdsLock(getTreeLock())) { + // The user really should not be invoking remove() from this + // thread -- but since he/she is, we can not go over to the + // EDT at this point. Try to destroy the context from here. + drawableHelper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction); + } else { + Threading.invokeOnOpenGLThread(disposeOnEventDispatchThreadAction); + } + } else { + drawableHelper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction); } } - - backend.setContext(disposeContext); - if(null==disposeContext) { - isInitialized = false; + if(null != backend) { + // not yet destroyed due to backend.isUsingOwnThreadManagment() == true + backend.destroy(); + isInitialized = false; } if(animatorPaused) { animator.resume(); - } + } } - + if(DEBUG) { - System.err.println("dispose("+regenerate+") - stop"); + System.err.println("dispose() - stop"); } } @@ -347,8 +331,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing super.paintComponent() in their paintComponent() method in order to function properly. <P> - <B>Overrides:</B> <DL><DD><CODE>paintComponent</CODE> in class <CODE>javax.swing.JComponent</CODE></DD></DL> */ + @Override protected void paintComponent(final Graphics g) { if (Beans.isDesignTime()) { // Make GLJPanel behave better in NetBeans GUI builder @@ -396,8 +380,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing super.addNotify() in their addNotify() method in order to function properly. <P> - <B>Overrides:</B> <DL><DD><CODE>addNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + @Override public void addNotify() { super.addNotify(); if (DEBUG) { @@ -410,26 +394,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing super.removeNotify() in their removeNotify() method in order to function properly. <P> - <B>Overrides:</B> <DL><DD><CODE>removeNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + @Override public void removeNotify() { - if(DEBUG) { - Exception ex1 = new Exception("Info: removeNotify - start"); - ex1.printStackTrace(); - } - awtWindowClosingProtocol.removeClosingListener(); - dispose(false); - if (backend != null) { - backend.destroy(); - backend = null; - } - isInitialized = false; + dispose(); super.removeNotify(); - if(DEBUG) { - System.err.println("Info: removeNotify - end"); - } } /** Overridden to cause {@link GLDrawableHelper#reshape} to be @@ -437,9 +408,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing which override this method must call super.reshape() in their reshape() method in order to function properly. <P> - <B>Overrides:</B> <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ - public void reshape(int x, int y, int width, int height) { + @SuppressWarnings("deprecation") + @Override +public void reshape(int x, int y, int width, int height) { super.reshape(x, y, width, height); // reshapeX = x; @@ -449,6 +421,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing handleReshape = true; } + @Override public void setOpaque(boolean opaque) { if (backend != null) { backend.setOpaque(opaque); @@ -481,7 +454,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } public GLContext createContext(GLContext shareWith) { - return backend.createContext(shareWith); + return (null != backend) ? backend.createContext(shareWith) : null; } public void setRealized(boolean realized) { @@ -690,7 +663,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return; } if (sendReshape) { - if (DEBUG||VERBOSE) { + if (DEBUG) { System.err.println("display: reshape(" + viewportX + "," + viewportY + " " + panelWidth + "x" + panelHeight + ")"); } drawableHelper.reshape(GLJPanel.this, viewportX, viewportY, panelWidth, panelHeight); @@ -713,42 +686,26 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return "AWT-GLJPanel[ "+((null!=backend)?backend.getDrawable().getClass().getName():"null-drawable")+"]"; } - private boolean disposeRegenerate; - private GLContext disposeContext; - private GLDrawable disposeDrawable; - private DisposeAction disposeAction = new DisposeAction(); - - class DisposeAction implements Runnable { + class PostDisposeAction implements Runnable { public void run() { - updater.dispose(GLJPanel.this); - - if (null != disposeContext) { - disposeContext.destroy(); - disposeContext = null; - } - if (null != disposeDrawable) { - disposeDrawable.setRealized(false); - } - if (null != disposeDrawable) { - if (disposeRegenerate) { - disposeDrawable.setRealized(true); - disposeContext = (GLContextImpl) disposeDrawable.createContext(shareWith); - disposeContext.setSynchronized(true); - } + if (backend != null && !backend.isUsingOwnThreadManagment()) { + backend.destroy(); + backend = null; + isInitialized = false; } } } + private PostDisposeAction postDisposeAction = new PostDisposeAction(); private DisposeOnEventDispatchThreadAction disposeOnEventDispatchThreadAction = new DisposeOnEventDispatchThreadAction(); class DisposeOnEventDispatchThreadAction implements Runnable { public void run() { - drawableHelper.invokeGL(disposeDrawable, disposeContext, disposeAction, null); + drawableHelper.disposeGL(GLJPanel.this, backend.getDrawable(), backend.getContext(), postDisposeAction); } } - - + class InitAction implements Runnable { public void run() { updater.init(GLJPanel.this); @@ -776,17 +733,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing if (number == 0) { return 2; } - - if (((number-1) & number) == 0) { - //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0 - return number; - } - int power = 0; - while (number > 0) { - number = number>>1; - power++; - } - return (1<<power); + return GLBuffers.getNextPowerOf2(number); } private int getGLInteger(GL gl, int which) { @@ -803,6 +750,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // software / pixmap rendering, pbuffer-based acceleration, Java 2D // / JOGL bridge static interface Backend { + // Create, Destroy, .. + public boolean isUsingOwnThreadManagment(); + // Called each time the backend needs to initialize itself public void initialize(); @@ -862,7 +812,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing protected int readBackWidthInPixels; protected int readBackHeightInPixels; - private int awtFormat; private int glFormat; private int glType; @@ -1031,7 +980,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private GLDrawableImpl offscreenDrawable; private GLContextImpl offscreenContext; + public boolean isUsingOwnThreadManagment() { return false; } + public void initialize() { + if(DEBUG) { + System.err.println("SoftwareBackend: initialize() - "+Thread.currentThread().getName()); + } // Fall-through path: create an offscreen context instead offscreenDrawable = (GLDrawableImpl) factory.createOffscreenDrawable( null /* default platform device */, @@ -1039,6 +993,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing chooser, Math.max(1, panelWidth), Math.max(1, panelHeight)); + offscreenDrawable.setRealized(true); offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith); offscreenContext.setSynchronized(true); offscreenContext.setContextCreationFlags(additionalCtxCreationFlags); @@ -1047,18 +1002,25 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } public void destroy() { + if(DEBUG) { + System.err.println("SoftwareBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable)+" - "+Thread.currentThread().getName()); + } if (offscreenContext != null) { offscreenContext.destroy(); offscreenContext = null; } if (offscreenDrawable != null) { + final AbstractGraphicsDevice adevice = offscreenDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); offscreenDrawable.destroy(); offscreenDrawable = null; + if(null != adevice) { + adevice.close(); + } } } public GLContext createContext(GLContext shareWith) { - return offscreenDrawable.createContext(shareWith); + return (null != offscreenDrawable) ? offscreenDrawable.createContext(shareWith) : null; } public void setContext(GLContext ctx) { @@ -1117,10 +1079,15 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private int pbufferWidth = 256; private int pbufferHeight = 256; + public boolean isUsingOwnThreadManagment() { return false; } + public void initialize() { if (pbuffer != null) { throw new InternalError("Creating pbuffer twice without destroying it (memory leak / correctness bug)"); } + if(DEBUG) { + System.err.println("PbufferBackend: initialize() - "+Thread.currentThread().getName()); + } try { pbuffer = factory.createGLPbuffer(null /* default platform device */, offscreenCaps, @@ -1144,6 +1111,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } public void destroy() { + if(DEBUG) { + System.err.println("PbufferBackend: destroy() - pbuffer: "+(null!=pbuffer)+" - "+Thread.currentThread().getName()); + } if (pbuffer != null) { pbuffer.destroy(); pbuffer = null; @@ -1151,7 +1121,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } public GLContext createContext(GLContext shareWith) { - return pbuffer.createContext(shareWith); + return (null != pbuffer) ? pbuffer.createContext(shareWith) : null; } public void setContext(GLContext ctx) { @@ -1265,7 +1235,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private Object j2dSurface; // Graphics object being used during Java2D update action // (absolutely essential to cache this) - private Graphics cached2DGraphics; // No-op context representing the Java2D OpenGL context private GLContext j2dContext; // Context associated with no-op drawable representing the JOGL @@ -1308,7 +1277,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // comment related to Issue 274 below private GraphicsConfiguration workaroundConfig; + public boolean isUsingOwnThreadManagment() { return true; } + public void initialize() { + if(DEBUG) { + System.err.println("J2DOGL: initialize() - "+Thread.currentThread().getName()); + } // No-op in this implementation; everything is done lazily isInitialized = true; } @@ -1316,6 +1290,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing public void destroy() { Java2D.invokeWithOGLContextCurrent(null, new Runnable() { public void run() { + if(DEBUG) { + System.err.println("J2DOGL: destroy() - joglContext: "+(null!=joglContext)+" - joglDrawable: "+(null!=joglDrawable)+" - "+Thread.currentThread().getName()); + } if (joglContext != null) { joglContext.destroy(); joglContext = null; @@ -1334,9 +1311,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } public GLContext createContext(GLContext shareWith) { - // FIXME: should implement this, but it was not properly - // implemented before the refactoring anyway - throw new GLException("Not yet implemented"); + if(null != shareWith) { + throw new GLException("J2DOGLBackend cannot create context w/ additional shared context, since it already needs to share the context w/ J2D."); + } + return (null != joglDrawable && null != j2dContext) ? joglDrawable.createContext(j2dContext) : null; } public void setContext(GLContext ctx) { @@ -1372,12 +1350,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing Rectangle r = Java2D.getOGLScissorBox(g); if (r == null) { - if (DEBUG && VERBOSE) { + if (DEBUG) { System.err.println("Java2D.getOGLScissorBox() returned null"); } return false; } - if (DEBUG && VERBOSE) { + if (DEBUG) { System.err.println("GLJPanel: gl.glScissor(" + r.x + ", " + r.y + ", " + r.width + ", " + r.height + ")"); } @@ -1418,14 +1396,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // Need to do workarounds fbObjectWorkarounds = true; createNewDepthBuffer = true; - if (DEBUG || VERBOSE) { + if (DEBUG) { System.err.println("GLJPanel: ERR GL_FRAMEBUFFER_BINDING: Discovered Invalid J2D FBO("+frameBuffer[0]+"): "+FBObject.getStatusString(status) + ", frame_buffer_object workarounds to be necessary"); } } else { // Don't need the frameBufferTexture temporary any more frameBufferTexture = null; - if (DEBUG || VERBOSE) { + if (DEBUG) { System.err.println("GLJPanel: OK GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]); } } @@ -1472,7 +1450,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing fboTextureTarget, frameBufferTexture[0], 0); - if (DEBUG && VERBOSE) { + if (DEBUG) { System.err.println("GLJPanel: frameBufferDepthBuffer: " + frameBufferDepthBuffer[0]); } gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, @@ -1489,7 +1467,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } } } else { - if (DEBUG && VERBOSE) { + if (DEBUG) { System.err.println("GLJPanel: Setting up drawBuffer " + drawBuffer[0] + " and readBuffer " + readBuffer[0]); } @@ -1547,14 +1525,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing Java2D.invokeWithOGLContextCurrent(g, new Runnable() { public void run() { - if (DEBUG && VERBOSE) { - System.err.println("-- In invokeWithOGLContextCurrent"); + if (DEBUG) { + System.err.println("-- In invokeWithOGLContextCurrent - "+Thread.currentThread().getName()); } // Create no-op context representing Java2D context if (j2dContext == null) { j2dContext = factory.createExternalGLContext(); - if (DEBUG||VERBOSE) { + if (DEBUG) { System.err.println("-- Created External Context: "+j2dContext); } if (DEBUG) { @@ -1595,15 +1573,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing backend = null; oglPipelineEnabled = false; handleReshape = true; - j2dContext.release(); j2dContext.destroy(); j2dContext = null; return; } - j2dContext.release(); + } else { + j2dContext.makeCurrent(); } - - j2dContext.makeCurrent(); try { captureJ2DState(j2dContext.getGL(), g); Object curSurface = Java2D.getOGLSurfaceIdentifier(g); @@ -1614,13 +1590,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing joglContext = null; joglDrawable = null; sendReshape = true; - if (DEBUG||VERBOSE) { + if (DEBUG) { System.err.println("Sending reshape because surface changed"); System.err.println("New surface = " + curSurface); } } j2dSurface = curSurface; - if (DEBUG || VERBOSE) { + if (DEBUG) { System.err.print("-- Surface type: "); int surfaceType = Java2D.getOGLSurfaceType(g); if (surfaceType == Java2D.UNDEFINED) { @@ -1641,22 +1617,20 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } } if (joglContext == null) { - AbstractGraphicsDevice device = j2dContext.getGLDrawable().getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + AbstractGraphicsDevice device = j2dContext.getGLDrawable().getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); if (factory.canCreateExternalGLDrawable(device)) { joglDrawable = factory.createExternalGLDrawable(); - // FIXME: Need to share with j2d context, due to FBO resource .. - // - ORIG: joglContext = joglDrawable.createContext(shareWith); joglContext = joglDrawable.createContext(j2dContext); - if (DEBUG||VERBOSE) { + joglContext.setSynchronized(true); + if (DEBUG) { System.err.println("-- Created External Drawable: "+joglDrawable); System.err.println("-- Created Context: "+joglContext); } } else if (factory.canCreateContextOnJava2DSurface(device)) { // Mac OS X code path - // FIXME: Need to share with j2d context, due to FBO resource .. - // - ORIG: joglContext = factory.createContextOnJava2DSurface(g, shareWith); joglContext = factory.createContextOnJava2DSurface(g, j2dContext); - if (DEBUG||VERBOSE) { + joglContext.setSynchronized(true); + if (DEBUG) { System.err.println("-- Created Context: "+joglContext); } } @@ -1694,7 +1668,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing checkedForFBObjectWorkarounds=true; fbObjectWorkarounds = true; createNewDepthBuffer = true; - if (DEBUG || VERBOSE) { + if (DEBUG) { System.err.println("GLJPanel: Fetched ERR GL_FRAMEBUFFER_BINDING: "+frameBuffer[0]+" - NOT A FBO"+ ", frame_buffer_object workarounds to be necessary"); } @@ -1713,7 +1687,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing GL.GL_COLOR_ATTACHMENT0, GL.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, frameBufferTexture, 0); - if (DEBUG && VERBOSE) { + if (DEBUG) { System.err.println("GLJPanel: FBO COLOR_ATTACHMENT0: " + frameBufferTexture[0]); } } diff --git a/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java b/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java index 2fa708404..bc9a93042 100644 --- a/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java +++ b/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java @@ -79,7 +79,7 @@ public class GlyphString { * @param shape is not null, add all {@link GlyphShape}'s {@link Outline} to this instance. * @param vertexFactory vertex impl factory {@link Factory} * @param font the target {@link Font} - * @param size font size + * @param fontSize font size * @param str string text * @return the created {@link GlyphString} instance */ diff --git a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java index 2d2d1c536..ff49303ca 100644 --- a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java +++ b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java @@ -42,7 +42,7 @@ public class DesktopGLDynamicLookupHelper extends GLDynamicLookupHelper { public synchronized boolean loadGLULibrary() { /** hacky code .. where all platform GLU libs are tried ..*/ if(null==gluLib) { - List/*<String>*/ gluLibNames = new ArrayList(); + List<String> gluLibNames = new ArrayList<String>(); gluLibNames.add("/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib"); // osx gluLibNames.add("libGLU.so"); // unix gluLibNames.add("GLU32"); // windows diff --git a/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java b/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java index 96d62fbb3..27569d210 100644 --- a/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java +++ b/src/jogl/classes/jogamp/opengl/FPSCounterImpl.java @@ -28,6 +28,8 @@ package jogamp.opengl; import java.io.PrintStream; +import java.util.concurrent.TimeUnit; + import javax.media.opengl.FPSCounter; /** @@ -55,7 +57,7 @@ public class FPSCounterImpl implements FPSCounter { public final synchronized void tickFPS() { fpsTotalFrames++; if(fpsUpdateFramesInterval>0 && fpsTotalFrames%fpsUpdateFramesInterval == 0) { - final long now = System.currentTimeMillis(); + final long now = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); fpsLastPeriod = now - fpsLastUpdateTime; fpsLastPeriod = Math.max(fpsLastPeriod, 1); // div 0 fpsLast = ( (float)fpsUpdateFramesInterval * 1000f ) / ( (float) fpsLastPeriod ) ; @@ -96,7 +98,7 @@ public class FPSCounterImpl implements FPSCounter { } public final synchronized void resetFPSCounter() { - fpsStartTime = System.currentTimeMillis(); // overwrite startTime to real init one + fpsStartTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); // overwrite startTime to real init one fpsLastUpdateTime = fpsStartTime; fpsLastPeriod = 0; fpsTotalFrames = 0; diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 58f1bf1cd..e87d283eb 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -47,8 +47,6 @@ import java.util.Map; import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.util.ReflectionUtil; -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; import com.jogamp.gluegen.runtime.FunctionAddressResolver; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLExtensionNames; @@ -69,11 +67,8 @@ import javax.media.opengl.GLPipelineFactory; import javax.media.opengl.GLProfile; public abstract class GLContextImpl extends GLContext { - public static final boolean DEBUG = Debug.debug("GLContext"); - - // RecursiveLock maintains a queue of waiting Threads, ensuring the longest waiting thread will be notified at unlock. - protected RecursiveLock lock = LockFactory.createRecursiveLock(); - + public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true); + /** * Context full qualified name: display_type + display_connection + major + minor + ctp. * This is the key for all cached GL ProcAddressTables, etc, to support multi display/device setups. @@ -113,6 +108,12 @@ public abstract class GLContextImpl extends GLContext { mappedGLXProcAddress = new HashMap<String, ProcAddressTable>(); } + public static void shutdownImpl() { + mappedExtensionAvailabilityCache.clear(); + mappedGLProcAddress.clear(); + mappedGLXProcAddress.clear(); + } + public GLContextImpl(GLDrawableImpl drawable, GLContext shareWith) { super(); @@ -209,74 +210,94 @@ public abstract class GLContextImpl extends GLContext { */ protected void drawableUpdatedNotify() throws GLException { } - boolean lockFailFast = true; - Object lockFailFastSync = new Object(); + volatile boolean lockFailFast = true; public boolean isSynchronized() { - synchronized (lockFailFastSync) { - return !lockFailFast; - } + return !lockFailFast; // volatile: ok } public void setSynchronized(boolean isSynchronized) { - synchronized (lockFailFastSync) { - lockFailFast = !isSynchronized; - } + lockFailFast = !isSynchronized; // volatile: ok } - private final void lockConsiderFailFast() { - synchronized (lockFailFastSync) { - if(lockFailFast && lock.isLockedByOtherThread()) { - throw new GLException("Error: Attempt to make context current on thread " + Thread.currentThread() + - " which is already current on thread " + lock.getOwner()); + private final void lockConsiderFailFast() { + if( lockFailFast ) { // volatile: ok + try { + if( !lock.tryLock(0) ) { // immediate return w/ false, if lock is already held by other thread + throw new GLException("Error: Attempt to make context current on thread " + Thread.currentThread().getName() + + " which is already current on thread " + lock.getOwner().getName()); + } + } catch (InterruptedException ie) { + throw new GLException(ie); } + } else { + lock.lock(); } - lock.lock(); } public abstract Object getPlatformGLExtensions(); // Note: the surface is locked within [makeCurrent .. swap .. release] public void release() throws GLException { + release(false); + } + private void release(boolean force) throws GLException { if ( !lock.isOwner() ) { throw new GLException("Context not current on current thread"); } - setCurrent(null); + final boolean actualRelease = force || lock.getHoldCount() == 1 ; try { - releaseImpl(); + if( actualRelease ) { + setCurrent(null); + if (contextHandle != 0) { // allow dbl-release + releaseImpl(); + } + } } finally { - if (drawable.isSurfaceLocked()) { - drawable.unlockSurface(); - } + drawable.unlockSurface(); lock.unlock(); + if(TRACE_SWITCH) { + if( actualRelease ) { + System.err.println("GLContext.ContextSwitch: - switch - CONTEXT_RELEASE - "+Thread.currentThread().getName()+" - "+lock); + } else { + System.err.println("GLContext.ContextSwitch: - keep - CONTEXT_RELEASE - "+Thread.currentThread().getName()+" - "+lock); + } + } } } protected abstract void releaseImpl() throws GLException; public final void destroy() { - if ( lock.isOwner() ) { - // release current context - if(null != glDebugHandler) { - glDebugHandler.enable(false); - } - release(); - } - // Must hold the lock around the destroy operation to make sure we // don't destroy the context out from under another thread rendering to it - lockConsiderFailFast(); + lockConsiderFailFast(); // holdCount++ -> 1 or 2 try { + if(lock.getHoldCount() > 2) { + throw new GLException("XXX: "+lock); + } + if (DEBUG || TRACE_SWITCH) { + System.err.println("GLContextImpl.destroy.0: " + toHexString(contextHandle) + + ", isShared "+GLContextShareSet.isShared(this)+" - "+lock); + } if (contextHandle != 0) { int lockRes = drawable.lockSurface(); if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { // this would be odd .. throw new GLException("Surface not ready to lock: "+drawable); } - try { - if (DEBUG) { - System.err.println("GLContextImpl.destroy: " + toHexString(contextHandle) + - ", isShared "+GLContextShareSet.isShared(this)); + // release current context + if(null != glDebugHandler) { + if(lock.getHoldCount() == 1) { + // needs current context to disable debug handler + makeCurrent(); } + glDebugHandler.enable(false); + } + if(lock.getHoldCount() > 1) { + // pending release() after makeCurrent() + release(true); + } + try { destroyImpl(); contextHandle = 0; glDebugHandler = null; @@ -290,6 +311,10 @@ public abstract class GLContextImpl extends GLContext { } } finally { lock.unlock(); + if (DEBUG || TRACE_SWITCH) { + System.err.println("GLContextImpl.destroy.X: " + toHexString(contextHandle) + + ", isShared "+GLContextShareSet.isShared(this)+" - "+lock); + } } resetStates(); @@ -321,7 +346,10 @@ public abstract class GLContextImpl extends GLContext { // /** - * MakeCurrent functionality, which also issues the creation of the actual OpenGL context.<br> + * {@inheritDoc} + * <p> + * MakeCurrent functionality, which also issues the creation of the actual OpenGL context. + * </p> * The complete callgraph for general OpenGL context creation is:<br> * <ul> * <li> {@link #makeCurrent} <i>GLContextImpl</i></li> @@ -355,55 +383,75 @@ public abstract class GLContextImpl extends GLContext { * @see #destroyContextARBImpl */ public int makeCurrent() throws GLException { - // One context can only be current by one thread, - // and one thread can only have one context current! - GLContext current = getCurrent(); - if (current != null) { - if (current == this) { - // Assume we don't need to make this context current again - // For Mac OS X, however, we need to update the context to track resizes - drawableUpdatedNotify(); - return CONTEXT_CURRENT; - } else { - current.release(); - } - } - - if (GLWorkerThread.isStarted() && - !GLWorkerThread.isWorkerThread()) { - // Kick the GLWorkerThread off its current context - GLWorkerThread.invokeLater(new Runnable() { public void run() {} }); - } - - if (!isCreated()) { - // verify if the drawable has chosen Capabilities - if (null == getGLDrawable().getChosenGLCapabilities()) { - throw new GLException("drawable has no chosen GLCapabilities: "+getGLDrawable()); - } - if(DEBUG_GL) { - // only impacts w/ createContextARB(..) - additionalCtxCreationFlags |= GLContext.CTX_OPTION_DEBUG ; - } - } - + boolean unlockContextAndDrawable = false; lockConsiderFailFast(); - int res = 0; + int res = CONTEXT_NOT_CURRENT; try { - res = makeCurrentLocking(); - - /* FIXME: refactor dependence on Java 2D / JOGL bridge - if ((tracker != null) && - (res == CONTEXT_CURRENT_NEW)) { - // Increase reference count of GLObjectTracker - tracker.ref(); - } - */ - } catch (GLException e) { - lock.unlock(); - throw(e); + // Note: the surface is locked within [makeCurrent .. swap .. release] + int lockRes = drawable.lockSurface(); + if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { + return CONTEXT_NOT_CURRENT; + } + try { + if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { + drawable.updateHandle(); + } + // One context can only be current by one thread, + // and one thread can only have one context current! + final GLContext current = getCurrent(); + if (current != null) { + if (current == this) { + // Assume we don't need to make this context current again + // For Mac OS X, however, we need to update the context to track resizes + drawableUpdatedNotify(); + if(TRACE_SWITCH) { + System.err.println("GLContext.ContextSwitch: - keep - CONTEXT_CURRENT - "+Thread.currentThread().getName()+" - "+lock); + } + return CONTEXT_CURRENT; + } else { + current.release(); + } + } + if (GLWorkerThread.isStarted() && + !GLWorkerThread.isWorkerThread()) { + // Kick the GLWorkerThread off its current context + GLWorkerThread.invokeLater(new Runnable() { public void run() {} }); + } + + if (0 == drawable.getHandle()) { + throw new GLException("drawable has invalid handle: "+drawable); + } + res = makeCurrentWithinLock(lockRes); + unlockContextAndDrawable = CONTEXT_NOT_CURRENT == res; + + /** + * FIXME: refactor dependence on Java 2D / JOGL bridge + if ((tracker != null) && + (res == CONTEXT_CURRENT_NEW)) { + // Increase reference count of GLObjectTracker + tracker.ref(); + } + */ + } catch (RuntimeException e) { + unlockContextAndDrawable = true; + throw e; + } finally { + if (unlockContextAndDrawable) { + drawable.unlockSurface(); + } + } + } catch (RuntimeException e) { + unlockContextAndDrawable = true; + throw e; + } finally { + if (unlockContextAndDrawable) { + lock.unlock(); + } } if (res == CONTEXT_NOT_CURRENT) { - lock.unlock(); + if(TRACE_SWITCH) { + System.err.println("GLContext.ContextSwitch: - switch - CONTEXT_NOT_CURRENT - "+Thread.currentThread().getName()+" - "+lock); + } } else { setCurrent(this); if(res == CONTEXT_CURRENT_NEW) { @@ -422,6 +470,11 @@ public abstract class GLContextImpl extends GLContext { if(TRACE_GL) { gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ); } + if(TRACE_SWITCH) { + System.err.println("GLContext.ContextSwitch: - switch - CONTEXT_CURRENT_NEW - "+Thread.currentThread().getName()+" - "+lock); + } + } else if(TRACE_SWITCH) { + System.err.println("GLContext.ContextSwitch: - switch - CONTEXT_CURRENT - "+Thread.currentThread().getName()+" - "+lock); } /* FIXME: refactor dependence on Java 2D / JOGL bridge @@ -436,71 +489,76 @@ public abstract class GLContextImpl extends GLContext { return res; } - // Note: the surface is locked within [makeCurrent .. swap .. release] - protected final int makeCurrentLocking() throws GLException { - boolean shallUnlockSurface = false; - int lockRes = drawable.lockSurface(); - try { - if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { - return CONTEXT_NOT_CURRENT; - } - try { - if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { - drawable.updateHandle(); - } - if (0 == drawable.getHandle()) { - throw new GLException("drawable has invalid handle: "+drawable); - } - boolean newCreated = false; - if (!isCreated()) { - GLProfile.initProfiles( - getGLDrawable().getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice()); - newCreated = createImpl(); // may throws exception if fails! - if (DEBUG) { - if(newCreated) { - System.err.println(getThreadName() + ": !!! Create GL context OK: " + toHexString(contextHandle) + " for " + getClass().getName()); - } else { - System.err.println(getThreadName() + ": !!! Create GL context FAILED for " + getClass().getName()); - } - } - if(!newCreated) { - shallUnlockSurface = true; - return CONTEXT_NOT_CURRENT; + private final int makeCurrentWithinLock(int surfaceLockRes) throws GLException { + if (!isCreated()) { + if(DEBUG_GL) { + // only impacts w/ createContextARB(..) + additionalCtxCreationFlags |= GLContext.CTX_OPTION_DEBUG ; + } + + final GLContextImpl shareWith = (GLContextImpl) GLContextShareSet.getShareContext(this); + if (null != shareWith) { + shareWith.getDrawableImpl().lockSurface(); + } + final boolean created; + try { + created = createImpl(shareWith); // may throws exception if fails! + } finally { + if (null != shareWith) { + shareWith.getDrawableImpl().unlockSurface(); + } + } + if (DEBUG) { + if(created) { + System.err.println(getThreadName() + ": !!! Create GL context OK: " + toHexString(contextHandle) + " for " + getClass().getName()); + } else { + System.err.println(getThreadName() + ": !!! Create GL context FAILED for " + getClass().getName()); } - GLContextShareSet.contextCreated(this); - } - makeCurrentImpl(newCreated); - return newCreated ? CONTEXT_CURRENT_NEW : CONTEXT_CURRENT ; - } catch (RuntimeException e) { - shallUnlockSurface = true; - throw e; - } - } finally { - if (shallUnlockSurface) { - drawable.unlockSurface(); + } + if(!created) { + return CONTEXT_NOT_CURRENT; + } + GLContextShareSet.contextCreated(this); + return CONTEXT_CURRENT_NEW; } - } + makeCurrentImpl(); + return CONTEXT_CURRENT; } - protected abstract void makeCurrentImpl(boolean newCreatedContext) throws GLException; - protected abstract boolean createImpl() throws GLException ; + protected abstract void makeCurrentImpl() throws GLException; + + /** + * Platform dependent entry point for context creation.<br> + * + * This method is called from {@link #makeCurrentWithinLock()} .. {@link #makeCurrent()} .<br> + * + * The implementation shall verify this context with a + * <code>MakeContextCurrent</code> call.<br> + * + * The implementation <b>must</b> leave the context current.<br> + * + * @param share the shared context or null + * @return the valid and current context if successful, or null + * @throws GLException + */ + protected abstract boolean createImpl(GLContextImpl sharedWith) throws GLException ; /** * Platform dependent but harmonized implementation of the <code>ARB_create_context</code> * mechanism to create a context.<br> * - * This method is called from {@link #createContextARB}.<br> + * This method is called from {@link #createContextARB}, {@link #createImpl(GLContextImpl)} .. {@link #makeCurrent()} .<br> * * The implementation shall verify this context with a * <code>MakeContextCurrent</code> call.<br> * - * The implementation shall leave the context current.<br> + * The implementation <b>must</b> leave the context current.<br> * * @param share the shared context or null * @param direct flag if direct is requested * @param ctxOptionFlags <code>ARB_create_context</code> related, see references below * @param major major number * @param minor minor number - * @return the valid context if successfull, or null + * @return the valid and current context if successful, or null * * @see #makeCurrent * @see #CTX_PROFILE_COMPAT @@ -548,7 +606,7 @@ public abstract class GLContextImpl extends GLContext { */ protected final long createContextARB(long share, boolean direct) { - AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration(); AbstractGraphicsDevice device = config.getScreen().getDevice(); GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); GLProfile glp = glCaps.getGLProfile(); @@ -583,7 +641,7 @@ public abstract class GLContextImpl extends GLContext { _ctp[0] |= additionalCtxCreationFlags; _ctx = createContextARBImpl(share, direct, _ctp[0], _major[0], _minor[0]); if(0!=_ctx) { - setGLFunctionAvailability(true, true, _major[0], _minor[0], _ctp[0]); + setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0]); } } return _ctx; @@ -654,12 +712,11 @@ public abstract class GLContextImpl extends GLContext { } } if(0!=_context) { - AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); if( isExtensionAvailable("GL_ARB_ES2_compatibility") ) { ctp |= CTX_PROFILE_ES2_COMPAT; } GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, major[0], minor[0], ctp); - setGLFunctionAvailability(true, true, major[0], minor[0], ctp); destroyContextARBImpl(_context); if (DEBUG) { System.err.println(getThreadName() + ": !!! createContextARBMapVersionsAvailable HAVE: "+ @@ -677,8 +734,9 @@ public abstract class GLContextImpl extends GLContext { major[0]=majorMax; minor[0]=minorMax; long _context=0; + boolean ok = false; - while ( 0==_context && + while ( !ok && GLContext.isValidGLVersion(major[0], minor[0]) && ( major[0]>majorMin || major[0]==majorMin && minor[0] >=minorMin ) ) { @@ -687,15 +745,20 @@ public abstract class GLContextImpl extends GLContext { } _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]); - boolean ok = 0!=_context; + if(0 != _context) { + ok = true; + setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags); + } else { + ok = false; + } if(ok && major[0]>=3) { int[] hasMajor = new int[1]; int[] hasMinor = new int[1]; - setGLFunctionAvailability(true, false, major[0], minor[0], ctxOptionFlags); gl.glGetIntegerv(GL3.GL_MAJOR_VERSION, hasMajor, 0); gl.glGetIntegerv(GL3.GL_MINOR_VERSION, hasMinor, 0); ok = hasMajor[0]>major[0] || ( hasMajor[0]==major[0] && hasMinor[0]>=minor[0] ) ; if(!ok) { + removeCachedVersion(major[0], minor[0], ctxOptionFlags); destroyContextARBImpl(_context); _context = 0; } @@ -703,6 +766,7 @@ public abstract class GLContextImpl extends GLContext { System.err.println(getThreadName() + ": createContextARBVersions: version verification - expected "+major[0]+"."+minor[0]+", has "+hasMajor[0]+"."+hasMinor[0]+" == "+ok); } } + if(!ok) { if(!GLContext.decrementGLVersion(major, minor)) break; } @@ -854,15 +918,15 @@ public abstract class GLContextImpl extends GLContext { * * @param force force the setting, even if is already being set. * This might be useful if you change the OpenGL implementation. - * @param cached whether this version's data shall be cached or not * @param major OpenGL major version * @param minor OpenGL minor version * @param ctxProfileBits OpenGL context profile and option bits, see {@link javax.media.opengl.GLContext#CTX_OPTION_ANY} + * * @see #setContextVersion * @see javax.media.opengl.GLContext#CTX_OPTION_ANY * @see javax.media.opengl.GLContext#CTX_PROFILE_COMPAT */ - protected final void setGLFunctionAvailability(boolean force, boolean cached, int major, int minor, int ctxProfileBits) { + protected final void setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits) { if(null!=this.gl && null!=glProcAddressTable && !force) { return; // already done and not forced } @@ -873,7 +937,7 @@ public abstract class GLContextImpl extends GLContext { updateGLXProcAddressTable(); - AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); final int ctxImplBits = drawable.getChosenGLCapabilities().getHardwareAccelerated() ? GLContext.CTX_IMPL_ACCEL_HARD : GLContext.CTX_IMPL_ACCEL_SOFT; contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits, ctxImplBits); @@ -904,12 +968,10 @@ public abstract class GLContextImpl extends GLContext { new Object[] { new GLProcAddressResolver() } ); } resetProcAddressTable(getGLProcAddressTable()); - if(cached) { - synchronized(mappedContextTypeObjectLock) { - mappedGLProcAddress.put(contextFQN, getGLProcAddressTable()); - if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+getGLProcAddressTable().hashCode()); - } + synchronized(mappedContextTypeObjectLock) { + mappedGLProcAddress.put(contextFQN, getGLProcAddressTable()); + if(DEBUG) { + System.err.println(getThreadName() + ": !!! GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+getGLProcAddressTable().hashCode()); } } } @@ -919,34 +981,56 @@ public abstract class GLContextImpl extends GLContext { // setContextVersion(major, minor, ctxProfileBits); - if(cached) { - // - // Update ExtensionAvailabilityCache - // - ExtensionAvailabilityCache eCache; - synchronized(mappedContextTypeObjectLock) { - eCache = mappedExtensionAvailabilityCache.get( contextFQN ); + // + // Update ExtensionAvailabilityCache + // + ExtensionAvailabilityCache eCache; + synchronized(mappedContextTypeObjectLock) { + eCache = mappedExtensionAvailabilityCache.get( contextFQN ); + } + if(null != eCache) { + extensionAvailability = eCache; + if(DEBUG) { + System.err.println(getThreadName() + ": !!! GLContext GL ExtensionAvailabilityCache reusing key("+contextFQN+") -> "+eCache.hashCode()); + } + } else { + if(null==extensionAvailability) { + extensionAvailability = new ExtensionAvailabilityCache(this); } - if(null != eCache) { - extensionAvailability = eCache; + extensionAvailability.reset(); + synchronized(mappedContextTypeObjectLock) { + mappedExtensionAvailabilityCache.put(contextFQN, extensionAvailability); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GL ExtensionAvailabilityCache reusing key("+contextFQN+") -> "+eCache.hashCode()); - } - } else { - if(null==extensionAvailability) { - extensionAvailability = new ExtensionAvailabilityCache(this); - } - extensionAvailability.reset(); - synchronized(mappedContextTypeObjectLock) { - mappedExtensionAvailabilityCache.put(contextFQN, extensionAvailability); - if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+extensionAvailability.hashCode()); - } + System.err.println(getThreadName() + ": !!! GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+extensionAvailability.hashCode()); } } } } + protected final void removeCachedVersion(int major, int minor, int ctxProfileBits) { + AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); + AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + final int ctxImplBits = drawable.getChosenGLCapabilities().getHardwareAccelerated() ? GLContext.CTX_IMPL_ACCEL_HARD : GLContext.CTX_IMPL_ACCEL_SOFT; + contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits, ctxImplBits); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! RM Context FQN: "+contextFQN); + } + + synchronized(mappedContextTypeObjectLock) { + ProcAddressTable table = mappedGLProcAddress.remove( contextFQN ); + if(DEBUG) { + System.err.println(getThreadName() + ": !!! RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+table.hashCode()); + } + } + + synchronized(mappedContextTypeObjectLock) { + ExtensionAvailabilityCache eCache = mappedExtensionAvailabilityCache.get( contextFQN ); + if(DEBUG) { + System.err.println(getThreadName() + ": !!! RM GLContext GL ExtensionAvailabilityCache reusing key("+contextFQN+") -> "+eCache.hashCode()); + } + } + } + /** * Updates the platform's 'GLX' function cache */ diff --git a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java index 8ca0c016d..b950c2fdf 100644 --- a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java +++ b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java @@ -35,6 +35,7 @@ import javax.media.opengl.GLDebugListener; import javax.media.opengl.GLDebugMessage; import javax.media.opengl.GLException; +import com.jogamp.common.os.Platform; import com.jogamp.gluegen.runtime.ProcAddressTable; import jogamp.opengl.gl4.GL4bcProcAddressTable; @@ -122,7 +123,14 @@ public class GLDebugMessageHandler { } return; } - + if(Platform.OS_TYPE == Platform.OSType.WINDOWS && Platform.is32Bit()) { + // Currently buggy, ie. throws an exception after leaving the native callback. + // Probably a 32bit on 64bit JVM / OpenGL-driver issue. + if(DEBUG) { + System.err.println("GLDebugMessageHandler: Windows 32bit currently not supported!"); + } + return; + } if( ctx.isExtensionAvailable(GL_ARB_debug_output) ) { extName = GL_ARB_debug_output; extType = EXT_ARB; @@ -199,7 +207,7 @@ public class GLDebugMessageHandler { */ public final void setSynchronous(boolean synchronous) { this.synchronous = synchronous; - if(isEnabled() && isExtensionARB()) { + if( isEnabled() ) { setSynchronousImpl(); } } @@ -227,9 +235,9 @@ public class GLDebugMessageHandler { enableImpl(enable); } final void enableImpl(boolean enable) throws GLException { - setSynchronousImpl(); if(enable) { if(0 == handle) { + setSynchronousImpl(); handle = register0(glDebugMessageCallbackProcAddress, extType); if(0 == handle) { throw new GLException("Failed to register via \"glDebugMessageCallback*\" using "+extName); diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index 704f71457..e5f415a87 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -40,11 +40,25 @@ package jogamp.opengl; -import java.nio.*; -import javax.media.nativewindow.*; -import javax.media.opengl.*; - -import com.jogamp.common.util.VersionNumber; +import java.nio.Buffer; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.OffscreenLayerSurface; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.SurfaceChangeable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; +import javax.media.opengl.GLPbuffer; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.MutableGraphicsConfiguration; /** Extends GLDrawableFactory with a few methods for handling typically software-accelerated offscreen rendering (Device @@ -53,17 +67,28 @@ import com.jogamp.common.util.VersionNumber; they may be instantiated by the GLJPanel implementation. */ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected static final boolean DEBUG = GLDrawableImpl.DEBUG; - public static final VersionNumber versionOneZero = new VersionNumber(1, 0, 0); - public static final VersionNumber versionOneOne = new VersionNumber(1, 1, 0); - public static final VersionNumber versionOneTwo = new VersionNumber(1, 2, 0); - public static final VersionNumber versionOneThree = new VersionNumber(1, 3, 0); - public static final VersionNumber versionOneFour = new VersionNumber(1, 4, 0); protected GLDrawableFactoryImpl() { super(); } /** + * Returns the shared context mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}, + * either a pre-existing or newly created, or <code>null</code> if creation failed or not supported.<br> + * Creation of the shared context is tried only once. + * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be <code>null</code> for the platform's default device. + */ + public final GLContext getOrCreateSharedContext(AbstractGraphicsDevice device) { + device = validateDevice(device); + if(null!=device) { + return getOrCreateSharedContextImpl(device); + } + return null; + } + protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device); + + /** * Returns the shared device mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()}, * either a preexisting or newly created, or <code>null</code> if creation failed or not supported.<br> * Creation of the shared context is tried only once. @@ -103,24 +128,40 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { if (target == null) { throw new IllegalArgumentException("Null target"); } - AbstractGraphicsConfiguration config = target.getGraphicsConfiguration().getNativeGraphicsConfiguration(); - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration(); + GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); AbstractGraphicsDevice adevice = config.getScreen().getDevice(); GLDrawable result = null; adevice.lock(); try { - if(caps.isOnscreen()) { + final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true); + if(null != ols) { + // layered surface -> Offscreen/PBuffer + final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable(); + chosenCapsMod.setOnscreen(false); + chosenCapsMod.setPBuffer(canCreateGLPbuffer(adevice)); + config.setChosenCapabilities(chosenCapsMod); + if(DEBUG) { + System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target); + } + if( ! ( target instanceof SurfaceChangeable ) ) { + throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target); + } + result = createOffscreenDrawableImpl(target); + } else if(chosenCaps.isOnscreen()) { + // onscreen if(DEBUG) { System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable: "+target); } result = createOnscreenDrawableImpl(target); } else { + // offscreen + if(DEBUG) { + System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable (PBuffer: "+chosenCaps.isPBuffer()+"): "+target); + } if( ! ( target instanceof SurfaceChangeable ) ) { throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target); } - if(DEBUG) { - System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable (PBuffer: "+caps.isPBuffer()+"): "+target); - } result = createOffscreenDrawableImpl(target); } } finally { @@ -171,6 +212,9 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { device.lock(); try { drawable = (GLDrawableImpl) createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) ); + if(null != drawable) { + drawable.setRealized(true); + } } finally { device.unlock(); } @@ -287,15 +331,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // GLDrawableFactoryImpl details // - protected void maybeDoSingleThreadedWorkaround(Runnable action) { - if (Threading.isSingleThreaded() && - !Threading.isOpenGLThread()) { - Threading.invokeOnOpenGLThread(action); - } else { - action.run(); - } - } - /** * Returns the sole GLDrawableFactoryImpl instance. * diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index 151ec2e9c..509839f55 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -40,8 +40,16 @@ package jogamp.opengl; -import java.util.*; -import javax.media.opengl.*; +import java.util.ArrayList; +import java.util.HashSet; + +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.GLException; +import javax.media.opengl.GLRunnable; import com.jogamp.opengl.util.Animator; @@ -49,6 +57,9 @@ import com.jogamp.opengl.util.Animator; methods to be able to share it between GLCanvas and GLJPanel. */ public class GLDrawableHelper { + /** true if property <code>jogl.debug.GLDrawable.PerfStats</code> is defined. */ + private static final boolean PERF_STATS = Debug.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true); + protected static final boolean DEBUG = GLDrawableImpl.DEBUG; private Object listenersLock = new Object(); private ArrayList<GLEventListener> listeners; @@ -120,6 +131,10 @@ public class GLDrawableHelper { /** * Issues {@link javax.media.opengl.GLEventListener#dispose(javax.media.opengl.GLAutoDrawable)} * to all listeners. + * <p> + * Please consider using {@link #disposeGL(GLAutoDrawable, GLDrawable, GLContext, Runnable)} + * for correctness! + * </p> * @param drawable */ public final void dispose(GLAutoDrawable drawable) { @@ -129,12 +144,12 @@ public class GLDrawableHelper { } } } - + private boolean init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { if(listenersToBeInit.remove(l)) { l.init(drawable); if(sendReshape) { - reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */); + reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false); } return true; } @@ -177,7 +192,12 @@ public class GLDrawableHelper { } private void reshape(GLEventListener listener, GLAutoDrawable drawable, - int x, int y, int width, int height, boolean setViewport) { + int x, int y, int width, int height, boolean setViewport, boolean checkInit) { + if(checkInit) { + // GLEventListener may need to be init, + // in case this one is added after the realization of the GLAutoDrawable + init( listener, drawable, false ) ; + } if(setViewport) { drawable.getGL().glViewport(x, y, width, height); } @@ -187,7 +207,7 @@ public class GLDrawableHelper { public final void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { synchronized(listenersLock) { for (int i=0; i < listeners.size(); i++) { - reshape((GLEventListener) listeners.get(i), drawable, x, y, width, height, 0==i); + reshape((GLEventListener) listeners.get(i), drawable, x, y, width, height, 0==i, true); } } } @@ -294,6 +314,8 @@ public class GLDrawableHelper { * ie. {@link Animator#getThread()}. * @deprecated this is an experimental feature, * intended for measuring performance in regards to GL context switch + * and only being used if {@link #PERF_STATS} is enabled + * by defining property <code>jogl.debug.GLDrawable.PerfStats</code>. */ public final void setSkipContextReleaseThread(Thread t) { skipContextReleaseThread = t; @@ -305,7 +327,7 @@ public class GLDrawableHelper { public final Thread getSkipContextReleaseThread() { return skipContextReleaseThread; } - + private static final ThreadLocal<Runnable> perThreadInitAction = new ThreadLocal<Runnable>(); /** Principal helper method which runs a Runnable with the context @@ -315,8 +337,6 @@ public class GLDrawableHelper { class helps ensure that we don't inadvertently use private methods of the GLContext or its implementing classes.<br> * <br> - * Remark: In case this method is called to dispose the GLDrawable/GLAutoDrawable, - * <code>initAction</code> shall be <code>null</code> to mark this cause.<br> * * @param drawable * @param context @@ -335,13 +355,112 @@ public class GLDrawableHelper { return; } - if(null==initAction) { - // disposal case - if(!context.isCreated()) { - throw new GLException(Thread.currentThread().getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context is not created: "+context); - } + if(PERF_STATS) { + invokeGLImplStats(drawable, context, runnable, initAction, null); + } else { + invokeGLImpl(drawable, context, runnable, initAction, null); } + } + /** + * Principal helper method which runs {@link #dispose(GLAutoDrawable)} with the context + * made current and destroys the context afterwards while holding the lock. + * + * @param autoDrawable + * @param drawable + * @param context + * @param postAction + */ + public final void disposeGL(GLAutoDrawable autoDrawable, + GLDrawable drawable, + GLContext context, + Runnable postAction) { + if(PERF_STATS) { + invokeGLImplStats(drawable, context, null, null, autoDrawable); + } else { + invokeGLImpl(drawable, context, null, null, autoDrawable); + } + if(null != postAction) { + postAction.run(); + } + } + + private final void invokeGLImpl(GLDrawable drawable, + GLContext context, + Runnable runnable, + Runnable initAction, + GLAutoDrawable disposeAutoDrawable) { + final Thread currentThread = Thread.currentThread(); + + final boolean isDisposeAction = null==initAction ; + + // Support for recursive makeCurrent() calls as well as calling + // other drawables' display() methods from within another one's + GLContext lastContext = GLContext.getCurrent(); + Runnable lastInitAction = null; + if (lastContext != null) { + if (lastContext == context) { + lastContext = null; // utilize recursive locking + } else { + lastInitAction = perThreadInitAction.get(); + lastContext.release(); + } + } + int res = GLContext.CONTEXT_NOT_CURRENT; + + try { + res = context.makeCurrent(); + if (res != GLContext.CONTEXT_NOT_CURRENT) { + if(!isDisposeAction) { + perThreadInitAction.set(initAction); + if (res == GLContext.CONTEXT_CURRENT_NEW) { + if (DEBUG) { + System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction"); + } + initAction.run(); + } + runnable.run(); + if (autoSwapBufferMode) { + drawable.swapBuffers(); + } + } else { + if(res == GLContext.CONTEXT_CURRENT_NEW) { + throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context); + } + if(listeners.size()>0) { + dispose(disposeAutoDrawable); + } + } + } + } finally { + try { + if(isDisposeAction) { + context.destroy(); + } else if( res != GLContext.CONTEXT_NOT_CURRENT ) { + context.release(); + } + } catch (Exception e) { + System.err.println("Catched: "+e.getMessage()); + e.printStackTrace(); + } + if (lastContext != null) { + final int res2 = lastContext.makeCurrent(); + if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) { + lastInitAction.run(); + } + } + } + } + + private final void invokeGLImplStats(GLDrawable drawable, + GLContext context, + Runnable runnable, + Runnable initAction, + GLAutoDrawable disposeAutoDrawable) { + final Thread currentThread = Thread.currentThread(); + + final boolean isDisposeAction = null==initAction ; + // Support for recursive makeCurrent() calls as well as calling // other drawables' display() methods from within another one's int res = GLContext.CONTEXT_NOT_CURRENT; @@ -349,7 +468,9 @@ public class GLDrawableHelper { Runnable lastInitAction = null; if (lastContext != null) { if (lastContext == context) { - res = GLContext.CONTEXT_CURRENT; + if( currentThread == skipContextReleaseThread ) { + res = GLContext.CONTEXT_CURRENT; + } // else: utilize recursive locking lastContext = null; } else { lastInitAction = perThreadInitAction.get(); @@ -357,20 +478,21 @@ public class GLDrawableHelper { } } - /** long t0 = System.currentTimeMillis(); - long td1 = 0; // makeCurrent + long tdA = 0; // makeCurrent long tdR = 0; // render time - long td2 = 0; // swapBuffers - long td3 = 0; // release - boolean scr = true; */ - + long tdS = 0; // swapBuffers + long tdX = 0; // release + boolean ctxClaimed = false; + boolean ctxReleased = false; + boolean ctxDestroyed = false; try { if (res == GLContext.CONTEXT_NOT_CURRENT) { res = context.makeCurrent(); + ctxClaimed = true; } if (res != GLContext.CONTEXT_NOT_CURRENT) { - if(null!=initAction) { + if(!isDisposeAction) { perThreadInitAction.set(initAction); if (res == GLContext.CONTEXT_CURRENT_NEW) { if (DEBUG) { @@ -378,41 +500,50 @@ public class GLDrawableHelper { } initAction.run(); } - } - // tdR = System.currentTimeMillis(); - // td1 = tdR - t0; // makeCurrent - if(null!=runnable) { + tdR = System.currentTimeMillis(); + tdA = tdR - t0; // makeCurrent runnable.run(); - // td2 = System.currentTimeMillis(); - // tdR = td2 - tdR; // render time - if (autoSwapBufferMode && null != initAction) { - if (drawable != null) { + tdS = System.currentTimeMillis(); + tdR = tdS - tdR; // render time + if (autoSwapBufferMode) { drawable.swapBuffers(); - // td3 = System.currentTimeMillis(); - // td2 = td3 - td2; // swapBuffers - } + tdX = System.currentTimeMillis(); + tdS = tdX - tdS; // swapBuffers + } + } else { + if(res == GLContext.CONTEXT_CURRENT_NEW) { + throw new GLException(currentThread.getName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context); + } + if(listeners.size()>0) { + dispose(disposeAutoDrawable); } } } } finally { - if(res != GLContext.CONTEXT_NOT_CURRENT && - (null == skipContextReleaseThread || Thread.currentThread()!=skipContextReleaseThread) ) { - try { + try { + if(isDisposeAction) { + context.destroy(); + ctxDestroyed = true; + } else if( res != GLContext.CONTEXT_NOT_CURRENT && + (null == skipContextReleaseThread || currentThread != skipContextReleaseThread) ) { context.release(); - // scr = false; - } catch (Exception e) { + ctxReleased = true; } + } catch (Exception e) { + System.err.println("Catched: "+e.getMessage()); + e.printStackTrace(); } - // td3 = System.currentTimeMillis() - td3; // release + + tdX = System.currentTimeMillis() - tdX; // release / destroy if (lastContext != null) { - int res2 = lastContext.makeCurrent(); + final int res2 = lastContext.makeCurrent(); if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) { lastInitAction.run(); } } } - // long td0 = System.currentTimeMillis() - t0; - // System.err.println("td0 "+td0+"ms, fps "+(1.0/(td0/1000.0))+", td-makeCurrent: "+td1+"ms, td-render "+tdR+"ms, td-swap "+td2+"ms, td-release "+td3+"ms, skip ctx release: "+scr); + long td = System.currentTimeMillis() - t0; + System.err.println("td0 "+td+"ms, fps "+(1.0/(td/1000.0))+", td-makeCurrent: "+tdA+"ms, td-render "+tdR+"ms, td-swap "+tdS+"ms, td-release "+tdX+"ms, ctx claimed: "+ctxClaimed+", ctx release: "+ctxReleased+", ctx destroyed "+ctxDestroyed); } - + } diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index 58c9aaaa6..b9c216eab 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -40,8 +40,14 @@ package jogamp.opengl; -import javax.media.nativewindow.*; -import javax.media.opengl.*; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; public abstract class GLDrawableImpl implements GLDrawable { protected static final boolean DEBUG = Debug.debug("GLDrawable"); @@ -52,7 +58,7 @@ public abstract class GLDrawableImpl implements GLDrawable { this.factory = factory; this.surface = comp; this.realized = realized; - this.requestedCapabilities = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getNativeGraphicsConfiguration().getRequestedCapabilities(); + this.requestedCapabilities = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getRequestedCapabilities(); } /** @@ -79,7 +85,7 @@ public abstract class GLDrawableImpl implements GLDrawable { } public final void swapBuffers() throws GLException { - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); if ( caps.getDoubleBuffered() ) { if(!surface.surfaceSwap()) { int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] @@ -114,7 +120,7 @@ public abstract class GLDrawableImpl implements GLDrawable { } public GLCapabilitiesImmutable getChosenGLCapabilities() { - return (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + return (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); } public GLCapabilitiesImmutable getRequestedGLCapabilities() { @@ -125,7 +131,10 @@ public abstract class GLDrawableImpl implements GLDrawable { return surface; } + /** called with locked surface @ setRealized(false) */ protected void destroyHandle() {} + + /** called with locked surface @ setRealized(true) or @ lockSurface(..) when surface changed */ protected void updateHandle() {} public long getHandle() { diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java index 318d00637..6e2b7b744 100644 --- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java +++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java @@ -29,6 +29,7 @@ package jogamp.opengl; import java.util.ArrayList; + import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; @@ -86,6 +87,7 @@ public class GLGraphicsConfigurationUtil { return getWinAttributeBits(caps.isOnscreen(), caps.isPBuffer()); } + @SuppressWarnings({ "rawtypes", "unchecked" }) public static final boolean addGLCapabilitiesPermutations(ArrayList capsBucket, GLCapabilitiesImmutable temp, int winattrbits) { int preSize = capsBucket.size(); if( 0 != ( WINDOW_BIT & winattrbits ) ) { @@ -138,7 +140,7 @@ public class GLGraphicsConfigurationUtil { if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || !capsRequested.isPBuffer()) { // fix caps .. GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); - caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN + caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN - we don't need to be single buffered .. caps2.setOnscreen(false); caps2.setPBuffer(true); return caps2; diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java index d667fa53a..10d5a3f27 100644 --- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java @@ -42,6 +42,8 @@ package jogamp.opengl; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; + +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.opengl.GL; import javax.media.opengl.GLAnimatorControl; @@ -70,7 +72,7 @@ public class GLPbufferImpl implements GLPbuffer { public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext parentContext) { GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) - pbufferDrawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + pbufferDrawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities(); if(caps.isOnscreen()) { if(caps.isPBuffer()) { throw new IllegalArgumentException("Error: Given drawable is Onscreen and Pbuffer: "+pbufferDrawable); @@ -97,26 +99,25 @@ public class GLPbufferImpl implements GLPbuffer { return true; } - class DisposeAction implements Runnable { - public void run() { - // Lock: Covered by DestroyAction .. - drawableHelper.dispose(GLPbufferImpl.this); - } - } - DisposeAction disposeAction = new DisposeAction(); - public void destroy() { if(pbufferDrawable.isRealized()) { + final AbstractGraphicsDevice adevice = pbufferDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); + if (null != context && context.isCreated()) { try { - drawableHelper.invokeGL(pbufferDrawable, context, disposeAction, null); + drawableHelper.disposeGL(GLPbufferImpl.this, pbufferDrawable, context, null); } catch (GLException gle) { gle.printStackTrace(); } - context.destroy(); + context = null; // drawableHelper.reset(); } pbufferDrawable.destroy(); + pbufferDrawable = null; + + if(null != adevice) { + adevice.close(); + } } } diff --git a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java index 2c396e265..a33e03a1a 100644 --- a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java +++ b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java @@ -44,24 +44,28 @@ public class SharedResourceRunner implements Runnable { } public static interface Implementation { + /** + * @param connection for creation a {@link AbstractGraphicsDevice} instance. + * @return A new shared resource instance + */ Resource createSharedResource(String connection); void releaseSharedResource(Resource shared); void clear(); Resource mapPut(String connection, Resource resource); Resource mapGet(String connection); - Collection/*<Resource>*/ mapValues(); + Collection<Resource> mapValues(); } - Implementation impl = null; + final HashSet<String> devicesTried = new HashSet<String>(); + final Implementation impl; - boolean ready = false; - boolean released = false; - boolean shouldRelease = false; - String initConnection = null; - String releaseConnection = null; - - HashSet devicesTried = new HashSet(); + Thread thread; + boolean ready; + boolean released; + boolean shouldRelease; + String initConnection; + String releaseConnection; private boolean getDeviceTried(String connection) { synchronized (devicesTried) { @@ -81,22 +85,82 @@ public class SharedResourceRunner implements Runnable { public SharedResourceRunner(Implementation impl) { this.impl = impl; + resetState(); + } + + private void resetState() { + devicesTried.clear(); + thread = null; + ready = false; + released = false; + shouldRelease = false; + initConnection = null; + releaseConnection = null; } + /** + * Start the shared resource runner thread, if not running. + * <p> + * Validate the thread upfront and release all related resource if it was killed. + * </p> + * + * @return the shared resource runner thread. + */ + public Thread start() { + if(null != thread && !thread.isAlive()) { + // thread was killed unrecognized .. + if (DEBUG) { + System.err.println("SharedResourceRunner.start() - dead-old-thread cleanup - "+Thread.currentThread().getName()); + } + releaseSharedResources(); + thread = null; + } + if(null == thread) { + if (DEBUG) { + System.err.println("SharedResourceRunner.start() - start new Thread - "+Thread.currentThread().getName()); + } + resetState(); + thread = new Thread(this, Thread.currentThread().getName()+"-SharedResourceRunner"); + thread.setDaemon(true); // Allow JVM to exit, even if this one is running + thread.start(); + } + return thread; + } + + public void stop() { + if(null != thread) { + if (DEBUG) { + System.err.println("SharedResourceRunner.stop() - "+Thread.currentThread().getName()); + } + synchronized (this) { + shouldRelease = true; + this.notifyAll(); + + while (!released) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + } + } + } + public SharedResourceRunner.Resource getOrCreateShared(AbstractGraphicsDevice device) { SharedResourceRunner.Resource sr = null; if(null != device) { - String connection = device.getConnection(); + start(); + final String connection = device.getConnection(); sr = impl.mapGet(connection); if (null == sr && !getDeviceTried(connection)) { addDeviceTried(connection); if (DEBUG) { - System.err.println("getOrCreateShared() " + connection + ": trying"); + System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": trying - "+Thread.currentThread().getName()); } doAndWait(connection, null); sr = impl.mapGet(connection); if (DEBUG) { - System.err.println("getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) ); + System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) +" - "+Thread.currentThread().getName()); } } } @@ -111,11 +175,11 @@ public class SharedResourceRunner implements Runnable { if (null != sr) { removeDeviceTried(connection); if (DEBUG) { - System.err.println("releaseShared() " + connection + ": trying"); + System.err.println("SharedResourceRunner.releaseShared() " + connection + ": trying - "+Thread.currentThread().getName()); } doAndWait(null, connection); if (DEBUG) { - System.err.println("releaseShared() " + connection + ": done"); + System.err.println("SharedResourceRunner.releaseShared() " + connection + ": done - "+Thread.currentThread().getName()); } } } @@ -125,9 +189,9 @@ public class SharedResourceRunner implements Runnable { private final void doAndWait(String initConnection, String releaseConnection) { // wait until thread becomes ready to init new device, // pass the device and release the sync - String threadName = Thread.currentThread().getName(); + final String threadName = Thread.currentThread().getName(); if (DEBUG) { - System.err.println(threadName + " doAndWait START init: " + initConnection + ", release: "+releaseConnection); + System.err.println("SharedResourceRunner.doAndWait() START init: " + initConnection + ", release: "+releaseConnection+" - "+threadName); } synchronized (this) { while (!ready) { @@ -137,7 +201,7 @@ public class SharedResourceRunner implements Runnable { } } if (DEBUG) { - System.err.println(threadName + " initializeAndWait set command init: " + initConnection + ", release: "+releaseConnection); + System.err.println("SharedResourceRunner.doAndWait() set command: " + initConnection + ", release: "+releaseConnection+" - "+threadName); } this.initConnection = initConnection; this.releaseConnection = releaseConnection; @@ -151,31 +215,17 @@ public class SharedResourceRunner implements Runnable { } } if (DEBUG) { - System.err.println(threadName + " initializeAndWait END init: " + initConnection + ", release: "+releaseConnection); + System.err.println("SharedResourceRunner.initializeAndWait END init: " + initConnection + ", release: "+releaseConnection+" - "+threadName); } } // done } - public final void releaseAndWait() { - synchronized (this) { - shouldRelease = true; - this.notifyAll(); - - while (!released) { - try { - this.wait(); - } catch (InterruptedException ex) { - } - } - } - } - public final void run() { - String threadName = Thread.currentThread().getName(); + final String threadName = Thread.currentThread().getName(); if (DEBUG) { - System.err.println(threadName + " STARTED"); + System.err.println("SharedResourceRunner.run(): STARTED - " + threadName); } synchronized (this) { @@ -184,21 +234,27 @@ public class SharedResourceRunner implements Runnable { // wait for stop or init ready = true; if (DEBUG) { - System.err.println(threadName + " -> ready"); + System.err.println("SharedResourceRunner.run(): READY - " + threadName); } notifyAll(); this.wait(); - } catch (InterruptedException ex) { } + } catch (InterruptedException ex) { + shouldRelease = true; + if(DEBUG) { + System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+Thread.currentThread().getName()); + ex.printStackTrace(); + } + } ready = false; if (!shouldRelease) { if (DEBUG) { - System.err.println(threadName + " woke up for device connection init: " + initConnection + - ", release: " + releaseConnection); + System.err.println("SharedResourceRunner.run(): WOKE UP for device connection init: " + initConnection + + ", release: " + releaseConnection + " - " + threadName); } if(null != initConnection) { if (DEBUG) { - System.err.println(threadName + " create Shared for: " + initConnection); + System.err.println("SharedResourceRunner.run(): create Shared for: " + initConnection + " - " + threadName); } Resource sr = null; try { @@ -212,7 +268,7 @@ public class SharedResourceRunner implements Runnable { } if(null != releaseConnection) { if (DEBUG) { - System.err.println(threadName + " release Shared for: " + releaseConnection); + System.err.println("SharedResourceRunner.run(): release Shared for: " + releaseConnection + " - " + threadName); } Resource sr = impl.mapGet(releaseConnection); if (null != sr) { @@ -230,26 +286,34 @@ public class SharedResourceRunner implements Runnable { } if (DEBUG) { - System.err.println(threadName + " release START"); + System.err.println("SharedResourceRunner.run(): RELEASE START - " + threadName); } releaseSharedResources(); if (DEBUG) { - System.err.println(threadName + " release END"); + System.err.println("SharedResourceRunner.run(): RELEASE END - " + threadName); } + shouldRelease = false; released = true; - ready = false; + thread = null; notifyAll(); } } private void releaseSharedResources() { - Collection/*<Resource>*/ sharedResources = impl.mapValues(); - for (Iterator iter = sharedResources.iterator(); iter.hasNext();) { - Resource sr = (Resource) iter.next(); - impl.releaseSharedResource(sr); + synchronized (devicesTried) { + devicesTried.clear(); + } + Collection<Resource> sharedResources = impl.mapValues(); + for (Iterator<Resource> iter = sharedResources.iterator(); iter.hasNext();) { + try { + impl.releaseSharedResource(iter.next()); + } catch (Throwable t) { + System.err.println("Catched Exception: "+t.getStackTrace()+" - "+Thread.currentThread().getName()); + t.printStackTrace(); + } } impl.clear(); } diff --git a/src/jogl/classes/jogamp/opengl/awt/Java2D.java b/src/jogl/classes/jogamp/opengl/awt/Java2D.java index e240169e1..3e4a6a147 100644 --- a/src/jogl/classes/jogamp/opengl/awt/Java2D.java +++ b/src/jogl/classes/jogamp/opengl/awt/Java2D.java @@ -39,23 +39,32 @@ package jogamp.opengl.awt; -import jogamp.opengl.*; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.HeadlessException; +import java.awt.Rectangle; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import javax.media.opengl.GL; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.Debug; -import java.awt.*; -import java.awt.image.*; -import java.lang.reflect.*; -import java.security.*; - -import javax.media.opengl.*; -import javax.media.nativewindow.*; -import javax.media.nativewindow.awt.*; /** Defines integration with the Java2D OpenGL pipeline. This integration is only supported in 1.6 and is highly experimental. */ public class Java2D { private static boolean DEBUG = Debug.debug("Java2D"); - private static boolean VERBOSE = Debug.verbose(); private static boolean isHeadless; private static boolean isOGLPipelineActive; private static Method invokeWithOGLContextCurrentMethod; @@ -103,9 +112,9 @@ public class Java2D { private static Method destroyOGLContextMethod; static { - AccessController.doPrivileged(new PrivilegedAction() { + AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { - if (DEBUG && VERBOSE) { + if (DEBUG) { System.err.println("Checking for Java2D/OpenGL support"); } try { @@ -119,7 +128,7 @@ public class Java2D { // If we get here, we aren't running in headless mode isHeadless = false; String name = cfg.getClass().getName(); - if (DEBUG && VERBOSE) { + if (DEBUG) { System.err.println("Java2D support: default GraphicsConfiguration = " + name); } isOGLPipelineActive = (name.startsWith("sun.java2d.opengl")); @@ -127,7 +136,7 @@ public class Java2D { if (isOGLPipelineActive) { try { // Try to get methods we need to integrate - Class utils = Class.forName("sun.java2d.opengl.OGLUtilities"); + Class<?> utils = Class.forName("sun.java2d.opengl.OGLUtilities"); invokeWithOGLContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLContextCurrent", new Class[] { Graphics.class, @@ -176,7 +185,7 @@ public class Java2D { getOGLSurfaceTypeMethod.setAccessible(true); } catch (Exception e) { fbObjectSupportInitialized = false; - if (DEBUG && VERBOSE) { + if (DEBUG) { e.printStackTrace(); System.err.println("Info: Disabling Java2D/JOGL FBO support"); } @@ -190,7 +199,7 @@ public class Java2D { }); getOGLTextureTypeMethod.setAccessible(true); } catch (Exception e) { - if (DEBUG && VERBOSE) { + if (DEBUG) { e.printStackTrace(); System.err.println("Info: GL_ARB_texture_rectangle FBO support disabled"); } @@ -199,11 +208,11 @@ public class Java2D { // Try to set up APIs for enabling the bridge on OS X, // where it isn't possible to create generalized // external GLDrawables - Class cglSurfaceData = null; + Class<?> cglSurfaceData = null; try { cglSurfaceData = Class.forName("sun.java2d.opengl.CGLSurfaceData"); } catch (Exception e) { - if (DEBUG && VERBOSE) { + if (DEBUG) { e.printStackTrace(); System.err.println("Info: Unable to find class sun.java2d.opengl.CGLSurfaceData for OS X"); } @@ -234,7 +243,7 @@ public class Java2D { destroyOGLContextMethod.setAccessible(true); } } catch (Exception e) { - if (DEBUG && VERBOSE) { + if (DEBUG) { e.printStackTrace(); System.err.println("Info: Disabling Java2D/JOGL integration"); } @@ -513,15 +522,15 @@ public class Java2D { } private static int getOGLUtilitiesIntField(final String name) { - Integer i = (Integer) AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + Integer i = AccessController.doPrivileged(new PrivilegedAction<Integer>() { + public Integer run() { try { - Class utils = Class.forName("sun.java2d.opengl.OGLUtilities"); + Class<?> utils = Class.forName("sun.java2d.opengl.OGLUtilities"); Field f = utils.getField(name); f.setAccessible(true); - return f.get(null); + return (Integer) f.get(null); } catch (Exception e) { - if (DEBUG && VERBOSE) { + if (DEBUG) { e.printStackTrace(); } return null; @@ -530,7 +539,7 @@ public class Java2D { }); if (i == null) return 0; - if (DEBUG && VERBOSE) { + if (DEBUG) { System.err.println("OGLUtilities." + name + " = " + i.intValue()); } return i.intValue(); diff --git a/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java b/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java index 5856bf3a0..55fb3f9a2 100644 --- a/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java +++ b/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java @@ -67,6 +67,8 @@ public class VersionApplet extends Applet { private synchronized void my_init() { if(null != canvas) { return; } + setEnabled(true); + GLProfile glp = GLProfile.getDefault(); GLCapabilities glcaps = new GLCapabilities(glp); @@ -120,8 +122,10 @@ public class VersionApplet extends Applet { remove(canvas); canvas.destroy(); canvas = null; - remove(tareaVersion); - tareaVersion=null; + remove(tareaVersion.getParent()); // remove the grid + tareaVersion = null; + tareaCaps = null; + setEnabled(false); } } @@ -133,11 +137,13 @@ public class VersionApplet extends Applet { public void start() { System.err.println("VersionApplet: start() - begin"); + canvas.setVisible(true); System.err.println("VersionApplet: start() - end"); } public void stop() { System.err.println("VersionApplet: stop() - begin"); + canvas.setVisible(false); System.err.println("VersionApplet: stop() - end"); } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index 0ec913e31..62ee20f92 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -35,17 +35,20 @@ package jogamp.opengl.egl; -import javax.media.opengl.*; +import java.nio.ByteBuffer; +import java.util.Map; -import jogamp.opengl.*; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLContextImpl; +import jogamp.opengl.GLDrawableImpl; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; -import java.nio.*; -import java.util.*; - -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.nativewindow.AbstractGraphicsDevice; public abstract class EGLContext extends GLContextImpl { private boolean eglQueryStringInitialized; @@ -95,7 +98,7 @@ public abstract class EGLContext extends GLContextImpl { return true; } - protected void makeCurrentImpl(boolean newCreated) throws GLException { + protected void makeCurrentImpl() throws GLException { if(EGL.EGL_NO_DISPLAY==((EGLDrawable)drawable).getDisplay() ) { throw new GLException("drawable not properly initialized, NO DISPLAY: "+drawable); } @@ -135,12 +138,12 @@ public abstract class EGLContext extends GLContextImpl { // FIXME } - protected boolean createImpl() throws GLException { + protected boolean createImpl(GLContextImpl shareWith) throws GLException { long eglDisplay = ((EGLDrawable)drawable).getDisplay(); EGLGraphicsConfiguration config = ((EGLDrawable)drawable).getGraphicsConfiguration(); GLProfile glProfile = drawable.getGLProfile(); long eglConfig = config.getNativeConfig(); - long shareWith = EGL.EGL_NO_CONTEXT; + long shareWithHandle = EGL.EGL_NO_CONTEXT; if (eglDisplay == 0) { throw new GLException("Error: attempted to create an OpenGL context without a display connection"); @@ -160,10 +163,9 @@ public abstract class EGLContext extends GLContextImpl { } } - EGLContext other = (EGLContext) GLContextShareSet.getShareContext(this); - if (other != null) { - shareWith = other.getHandle(); - if (shareWith == 0) { + if (shareWith != null) { + shareWithHandle = shareWith.getHandle(); + if (shareWithHandle == 0) { throw new GLException("GLContextShareSet returned an invalid OpenGL context"); } } @@ -179,10 +181,10 @@ public abstract class EGLContext extends GLContextImpl { } else { throw new GLException("Error creating OpenGL context - invalid GLProfile: "+glProfile); } - contextHandle = EGL.eglCreateContext(eglDisplay, eglConfig, shareWith, contextAttrs, 0); + contextHandle = EGL.eglCreateContext(eglDisplay, eglConfig, shareWithHandle, contextAttrs, 0); if (contextHandle == 0) { throw new GLException("Error creating OpenGL context: eglDisplay "+toHexString(eglDisplay)+ - ", eglConfig "+config+", "+glProfile+", shareWith "+toHexString(shareWith)+", error "+toHexString(EGL.eglGetError())); + ", eglConfig "+config+", "+glProfile+", shareWith "+toHexString(shareWithHandle)+", error "+toHexString(EGL.eglGetError())); } if (DEBUG) { System.err.println(getThreadName() + ": !!! Created OpenGL context 0x" + @@ -190,7 +192,7 @@ public abstract class EGLContext extends GLContextImpl { ",\n\twrite surface 0x" + Long.toHexString(drawable.getHandle()) + ",\n\tread surface 0x" + Long.toHexString(drawableRead.getHandle())+ ",\n\t"+this+ - ",\n\tsharing with 0x" + Long.toHexString(shareWith)); + ",\n\tsharing with 0x" + Long.toHexString(shareWithHandle)); } if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), drawable.getHandle(), @@ -207,12 +209,12 @@ public abstract class EGLContext extends GLContextImpl { } else { major = 1; } - setGLFunctionAvailability(true, true, major, 0, ctp); + setGLFunctionAvailability(true, major, 0, ctp); return true; } protected final void updateGLXProcAddressTable() { - final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); final String key = "EGL-"+adevice.getUniqueID(); if (DEBUG) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index a9cc40335..14a0a40cd 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -99,7 +99,7 @@ public abstract class EGLDrawable extends GLDrawableImpl { protected void setRealizedImpl() { if (realized) { - AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); if(aDevice instanceof EGLGraphicsDevice) { if(DEBUG) { @@ -197,6 +197,16 @@ public abstract class EGLDrawable extends GLDrawableImpl { } } + protected final void swapBuffersImpl() { + // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() + if(!EGL.eglSwapBuffers(eglDisplay, eglSurface)) { + if(DEBUG) { + System.err.println("eglSwapBuffers failed:"); + Thread.dumpStack(); + } + } + } + public int getWidth() { int[] tmp = new int[1]; if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index 79d96bdb6..cd6d61a22 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -39,6 +39,7 @@ package jogamp.opengl.egl; import javax.media.nativewindow.*; import javax.media.nativewindow.egl.EGLGraphicsDevice; import javax.media.opengl.*; +import javax.media.opengl.GLProfile.ShutdownType; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.*; @@ -50,13 +51,15 @@ import java.util.HashMap; import java.util.List; public class EGLDrawableFactory extends GLDrawableFactoryImpl { - private static final GLDynamicLookupHelper eglES1DynamicLookupHelper; - private static final GLDynamicLookupHelper eglES2DynamicLookupHelper; - - static { + private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; + private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null; + + public EGLDrawableFactory() { + super(); + // Register our GraphicsConfigurationFactory implementations // The act of constructing them causes them to be registered - new EGLGraphicsConfigurationFactory(); + EGLGraphicsConfigurationFactory.registerFactory(); // Check for other underlying stuff .. if(NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) { @@ -69,38 +72,69 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { // to a dynamic one, where there can be 2 instances // for each ES profile with their own ProcAddressTable. - GLDynamicLookupHelper tmp=null; - try { - tmp = new GLDynamicLookupHelper(new EGLES1DynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); + synchronized(EGLDrawableFactory.class) { + if(null==eglES1DynamicLookupHelper) { + GLDynamicLookupHelper tmp=null; + try { + tmp = new GLDynamicLookupHelper(new EGLES1DynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + eglES1DynamicLookupHelper = tmp; + if(null!=eglES1DynamicLookupHelper && eglES1DynamicLookupHelper.isLibComplete()) { + EGL.resetProcAddressTable(eglES1DynamicLookupHelper); + } } } - eglES1DynamicLookupHelper = tmp; - if(null!=eglES1DynamicLookupHelper && eglES1DynamicLookupHelper.isLibComplete()) { - EGL.resetProcAddressTable(eglES1DynamicLookupHelper); - } - tmp=null; - try { - tmp = new GLDynamicLookupHelper(new EGLES2DynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); + synchronized(EGLDrawableFactory.class) { + if(null==eglES2DynamicLookupHelper) { + GLDynamicLookupHelper tmp=null; + try { + tmp = new GLDynamicLookupHelper(new EGLES2DynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + eglES2DynamicLookupHelper = tmp; + if(null!=eglES2DynamicLookupHelper && eglES2DynamicLookupHelper.isLibComplete()) { + EGL.resetProcAddressTable(eglES2DynamicLookupHelper); + } } } - eglES2DynamicLookupHelper = tmp; - if(null!=eglES2DynamicLookupHelper && eglES2DynamicLookupHelper.isLibComplete()) { - EGL.resetProcAddressTable(eglES2DynamicLookupHelper); + if(null != eglES1DynamicLookupHelper || null != eglES2DynamicLookupHelper) { + defaultDevice = new EGLGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + sharedMap = new HashMap(); } } - public EGLDrawableFactory() { - super(); - defaultDevice = new EGLGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + protected final void destroy(ShutdownType shutdownType) { + if(null != sharedMap) { + sharedMap.clear(); + sharedMap = null; + } + defaultDevice = null; + /** + * Pulling away the native library may cause havoc .. + * + if(ShutdownType.COMPLETE == shutdownType) { + if(null != eglES1DynamicLookupHelper) { + eglES1DynamicLookupHelper.destroy(); + eglES1DynamicLookupHelper = null; + } + if(null != eglES2DynamicLookupHelper) { + eglES2DynamicLookupHelper.destroy(); + eglES2DynamicLookupHelper = null; + } + } */ } + private HashMap/*<connection, SharedResource>*/ sharedMap; + private EGLGraphicsDevice defaultDevice; + static class SharedResource { private EGLGraphicsDevice device; // private EGLDrawable drawable; @@ -125,8 +159,6 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { final boolean wasES1ContextAvailable() { return wasES1ContextCreated; } final boolean wasES2ContextAvailable() { return wasES2ContextCreated; } } - HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); - EGLGraphicsDevice defaultDevice; public final AbstractGraphicsDevice getDefaultDevice() { return defaultDevice; @@ -200,10 +232,21 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return sr; } - public final boolean getWasSharedContextCreated(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateEGLSharedResource(device); - if(null!=sr) { - return sr.wasES1ContextAvailable() || sr.wasES2ContextAvailable(); + protected final Thread getSharedResourceThread() { + return null; + } + + protected final boolean createSharedResource(AbstractGraphicsDevice device) { + try { + SharedResource sr = getOrCreateEGLSharedResource(device); + if(null!=sr) { + return sr.wasES1ContextAvailable() || sr.wasES2ContextAvailable(); + } + } catch (GLException gle) { + if(DEBUG) { + System.err.println("Catched Exception while EGL Shared Resource initialization"); + gle.printStackTrace(); + } } return false; } @@ -236,8 +279,6 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } } - protected final void shutdownInstance() {} - protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) { return EGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device); } @@ -253,7 +294,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - AbstractGraphicsConfiguration config = target.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsConfiguration config = target.getGraphicsConfiguration(); GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); if(!caps.isPBuffer()) { throw new GLException("Non pbuffer not yet implemented"); @@ -268,7 +309,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser)); - ns.setSize(width, height); + ns.surfaceSizeChanged(width, height); return ns; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java index 33154b089..1f9254b49 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java @@ -29,18 +29,11 @@ package jogamp.opengl.egl; import com.jogamp.common.os.AndroidVersion; -import com.jogamp.common.os.DynamicLookupHelper; -import com.jogamp.common.os.NativeLibrary; -import com.jogamp.common.os.Platform; import java.util.*; -import javax.media.nativewindow.*; -import javax.media.opengl.*; import jogamp.opengl.*; -import java.security.*; - /** * Abstract implementation of the DynamicLookupHelper for EGL, * which decouples it's dependencies to EGLDrawable. diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java index 3b0fc5957..63109f445 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java @@ -30,10 +30,6 @@ package jogamp.opengl.egl; import java.util.*; -import com.jogamp.common.os.Platform; - -import jogamp.opengl.*; - public class EGLES1DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo { protected EGLES1DynamicLibraryBundleInfo() { super(); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java index 28c480b0c..b0748ad10 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java @@ -30,10 +30,6 @@ package jogamp.opengl.egl; import java.util.*; -import com.jogamp.common.os.Platform; - -import jogamp.opengl.*; - public class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo { protected EGLES2DynamicLibraryBundleInfo() { super(); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java index 389daa7ca..796a4311b 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java @@ -45,7 +45,7 @@ public class EGLExternalContext extends EGLContext { public EGLExternalContext(AbstractGraphicsScreen screen) { super(null, null); GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, true, 0, 0, CTX_IS_ARB_CREATED|CTX_PROFILE_ES|CTX_OPTION_ANY); + setGLFunctionAvailability(false, 0, 0, CTX_IS_ARB_CREATED|CTX_PROFILE_ES|CTX_OPTION_ANY); getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } @@ -66,7 +66,7 @@ public class EGLExternalContext extends EGLContext { lastContext = null; } - protected void makeCurrentImpl(boolean newCreated) throws GLException { + protected void makeCurrentImpl() throws GLException { } protected void releaseImpl() throws GLException { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 4fb3dca78..ea625fb27 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -38,15 +38,25 @@ package jogamp.opengl.egl; import java.nio.IntBuffer; import java.util.ArrayList; -import javax.media.nativewindow.*; -import javax.media.nativewindow.egl.*; -import javax.media.opengl.*; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.egl.EGLGraphicsDevice; +import javax.media.opengl.DefaultGLCapabilitiesChooser; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.MutableGraphicsConfiguration; +import jogamp.opengl.Debug; +import jogamp.opengl.GLGraphicsConfigurationUtil; import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; -import jogamp.opengl.*; -public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { +public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); public final long getNativeConfig() { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java index 74f7d884b..ceeebe60b 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java @@ -69,9 +69,11 @@ import java.nio.IntBuffer; public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { static EGLGLCapabilities.EglCfgIDComparator EglCfgIDComparator = new EGLGLCapabilities.EglCfgIDComparator(); - EGLGraphicsConfigurationFactory() { + static void registerFactory() { // become the selector for KD/EGL .. - GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.egl.EGLGraphicsDevice.class, this); + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.egl.EGLGraphicsDevice.class, new EGLGraphicsConfigurationFactory()); + } + private EGLGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl ( diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java index 7d5e0448d..42f067b29 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java @@ -55,15 +55,5 @@ public class EGLOnscreenDrawable extends EGLDrawable { protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { return EGL.eglCreateWindowSurface(eglDpy, eglNativeCfg, surfaceHandle, null); } - - protected void swapBuffersImpl() { - if(!EGL.eglSwapBuffers(eglDisplay, eglSurface)) { - if(DEBUG) { - System.err.println("eglSwapBuffers failed:"); - Thread.dumpStack(); - } - } - } - } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java index 5fb32e6cd..28a23d294 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java @@ -40,48 +40,39 @@ package jogamp.opengl.egl; +import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.SurfaceChangeable; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; -import jogamp.opengl.x11.glx.GLX; - public class EGLPbufferDrawable extends EGLDrawable { private int texFormat; protected static final boolean useTexture = false; // No yet .. protected EGLPbufferDrawable(EGLDrawableFactory factory, NativeSurface target) { super(factory, target); + } - // get choosen ones .. - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) - getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + protected void destroyImpl() { + setRealized(false); + } + + protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { + final AbstractGraphicsConfiguration config = getNativeSurface().getGraphicsConfiguration(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); if(useTexture) { - this.texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; + texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; } else { - this.texFormat = EGL.EGL_NO_TEXTURE; + texFormat = EGL.EGL_NO_TEXTURE; } if (DEBUG) { - System.out.println("Pbuffer config: " + getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration()); - } - - setRealized(true); - - if (DEBUG) { - System.out.println("Created pbuffer: " + this); + System.out.println("Pbuffer config: " + config); } - } - - protected void destroyImpl() { - setRealized(false); - } - - protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { NativeSurface nw = getNativeSurface(); int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(nw.getWidth(), nw.getHeight(), texFormat); long surf = EGL.eglCreatePbufferSurface(eglDpy, eglNativeCfg, attrs, 0); @@ -97,11 +88,5 @@ public class EGLPbufferDrawable extends EGLDrawable { public GLContext createContext(GLContext shareWith) { return new EGLPbufferContext(this, shareWith); } - - protected void swapBuffersImpl() { - if(DEBUG) { - System.err.println("unhandled swapBuffersImpl() called for: "+this); - } - } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index 1fe47f60b..0dd1a460e 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -45,14 +45,15 @@ import java.util.Map; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.nativewindow.DefaultGraphicsConfiguration; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.OffscreenLayerSurface; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import jogamp.opengl.GLContextImpl; -import jogamp.opengl.GLContextShareSet; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType; @@ -63,7 +64,6 @@ import com.jogamp.common.util.VersionNumber; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; - public abstract class MacOSXCGLContext extends GLContextImpl { // Abstract interface for implementation of this context (either @@ -76,7 +76,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl boolean makeCurrent(long ctx); boolean release(long ctx); boolean setSwapInterval(int interval); - boolean swapBuffers(boolean isOnscreen); + boolean swapBuffers(); } /* package */ static final boolean isTigerOrLater; @@ -95,7 +95,12 @@ public abstract class MacOSXCGLContext extends GLContextImpl // We exclude 3.0, since we would map it's core to GL2. Hence we force mapping 2.1 to GL2 if(3==major && 1<=minor && minor<=2) { // [3.1..3.2] -> GL3* + if(!isLionOrLater) { + // no GL3* on pre lion + return false; + } if(ctBwdCompat) { + // no compatibility profile on OS X return false; } return ctCore; @@ -203,44 +208,43 @@ public abstract class MacOSXCGLContext extends GLContextImpl return false; } - protected long createImplPreset() throws GLException { - MacOSXCGLContext other = (MacOSXCGLContext) GLContextShareSet.getShareContext(this); + protected long createImplPreset(GLContextImpl shareWith) throws GLException { long share = 0; - if (other != null) { + if (shareWith != null) { // Change our OpenGL mode to match that of any share context before we create ourselves - setOpenGLMode(other.getOpenGLMode()); - share = other.getHandle(); + setOpenGLMode(((MacOSXCGLContext)shareWith).getOpenGLMode()); + share = shareWith.getHandle(); if (share == 0) { throw new GLException("GLContextShareSet returned a NULL OpenGL context"); } } - MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + + MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); GLCapabilitiesImmutable capabilitiesChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities(); - if (capabilitiesChosen.getPbufferFloatingPointBuffers() && - !isTigerOrLater) { + if (capabilitiesChosen.getPbufferFloatingPointBuffers() && !isTigerOrLater) { throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later"); } GLProfile glp = capabilitiesChosen.getGLProfile(); if(glp.isGLES1() || glp.isGLES2() || glp.isGL4() || glp.isGL3() && !isLionOrLater) { throw new GLException("OpenGL profile not supported on MacOSX "+Platform.getOSVersionNumber()+": "+glp); } + if (DEBUG) { System.err.println("!!! Share context is " + toHexString(share) + " for " + this); } - return share; + return share; } - - protected boolean createImpl() throws GLException { - long share = createImplPreset(); + + protected boolean createImpl(GLContextImpl shareWith) throws GLException { + long share = createImplPreset(shareWith); contextHandle = createContextARB(share, true); return 0 != contextHandle; } - protected void makeCurrentImpl(boolean newCreated) throws GLException { + protected void makeCurrentImpl() throws GLException { if (getOpenGLMode() != ((MacOSXCGLDrawable)drawable).getOpenGLMode()) { setOpenGLMode(((MacOSXCGLDrawable)drawable).getOpenGLMode()); } - if (!impl.makeCurrent(contextHandle)) { throw new GLException("Error making Context current: "+this); } @@ -268,9 +272,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl } protected void swapBuffers() { - DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); - if(!impl.swapBuffers(caps.isOnscreen())) { + // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() + if(!impl.swapBuffers()) { throw new GLException("Error swapping buffers: "+this); } } @@ -282,12 +285,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl if(!impl.setSwapInterval(interval)) { throw new GLException("Error set swap-interval: "+this); } - if ( isNSContext() ) { - CGL.setSwapInterval(contextHandle, interval); - } else { - int[] lval = new int[] { (int) interval } ; - CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0); - } currentSwapInterval = interval ; } @@ -297,7 +294,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl } protected final void updateGLXProcAddressTable() { - final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); final String key = "MacOSX-"+adevice.getUniqueID(); if (DEBUG) { @@ -403,31 +400,44 @@ public abstract class MacOSXCGLContext extends GLContextImpl // NSOpenGLContext-based implementation class NSOpenGLImpl implements GLBackendImpl { + long nsOpenGLLayer = 0; + long nsOpenGLLayerPFmt = 0; + public boolean isNSContext() { return true; } public long create(long share, int ctp, int major, int minor) { long ctx = 0; - MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) MacOSXCGLContext.this.drawable; + final NativeSurface surface = drawable.getNativeSurface(); + final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true); + final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps, ctp, major, minor); if (pixelFormat == 0) { throw new GLException("Unable to allocate pixel format with requested GLCapabilities"); } config.setChosenPixelFormat(pixelFormat); + if(DEBUG) { + System.err.println("NS create OSX>=lion "+isLionOrLater); + System.err.println("NS create backingLayerHost: "+backingLayerHost); + System.err.println("NS create share: "+share); + System.err.println("NS create chosenCaps: "+chosenCaps); + System.err.println("NS create pixelFormat: "+toHexString(pixelFormat)); + System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle())); + System.err.println("NS create drawable NSView-handle: "+toHexString(drawable.getNSViewHandle())); + // Thread.dumpStack(); + } try { int[] viewNotReady = new int[1]; // Try to allocate a context with this ctx = CGL.createContext(share, - drawable.getHandle(), + drawable.getNSViewHandle(), null!=backingLayerHost, pixelFormat, chosenCaps.isBackgroundOpaque(), viewNotReady, 0); if (0 == ctx) { - if (viewNotReady[0] == 1) { - if (DEBUG) { - System.err.println("!!! View not ready for " + getClass().getName()); - } - // View not ready at the window system level + if(DEBUG) { + System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady[0])); } return 0; } @@ -439,22 +449,66 @@ public abstract class MacOSXCGLContext extends GLContextImpl if(DEBUG) { GLCapabilitiesImmutable caps0 = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(null, pixelFormat); - System.err.println("NS created(>=lion "+isLionOrLater+"): "+caps0); + System.err.println("NS create pixelformat2GLCaps: "+caps0); } - GLCapabilitiesImmutable caps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat); - caps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(caps, chosenCaps.isBackgroundOpaque()); - config.setChosenCapabilities(caps); - if(caps.isPBuffer()) { + GLCapabilitiesImmutable fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat); + fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque()); + config.setChosenCapabilities(fixedCaps); + if(DEBUG) { + System.err.println("NS create fixedCaps: "+fixedCaps); + } + if(fixedCaps.isPBuffer()) { // Must now associate the pbuffer with our newly-created context CGL.setContextPBuffer(ctx, drawable.getHandle()); - } + } + // + // handled layered surface + // + if(null != backingLayerHost) { + nsOpenGLLayerPFmt = pixelFormat; + pixelFormat = 0; + final int texWidth, texHeight; + if(drawable instanceof MacOSXPbufferCGLDrawable) { + final MacOSXPbufferCGLDrawable osxPDrawable = (MacOSXPbufferCGLDrawable)drawable; + texWidth = osxPDrawable.getTextureWidth(); + texHeight = osxPDrawable.getTextureHeight(); + } else { + texWidth = drawable.getWidth(); + texHeight = drawable.getHeight(); + } + nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), texWidth, texHeight); + if(0>=texWidth || 0>=texHeight || !drawable.isRealized()) { + throw new GLException("Drawable not realized yet or invalid texture size, texSize "+texWidth+"x"+texHeight+", "+drawable); + } + if (DEBUG) { + System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", texSize "+texWidth+"x"+texHeight+", "+drawable); + } + backingLayerHost.attachSurfaceLayer(nsOpenGLLayer); + } } finally { - CGL.deletePixelFormat(pixelFormat); + if(0!=pixelFormat) { + CGL.deletePixelFormat(pixelFormat); + } } return ctx; } public boolean destroy(long ctx) { + if(0 != nsOpenGLLayer) { + final NativeSurface surface = drawable.getNativeSurface(); + if (DEBUG) { + System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer)); + } + final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true); + if(null == ols) { + throw new InternalError("XXX: "+ols); + } + CGL.releaseNSOpenGLLayer(nsOpenGLLayer); + ols.detachSurfaceLayer(nsOpenGLLayer); + CGL.deletePixelFormat(nsOpenGLLayerPFmt); + nsOpenGLLayerPFmt = 0; + nsOpenGLLayer = 0; + } return CGL.deleteContext(ctx, true); } @@ -464,22 +518,54 @@ public abstract class MacOSXCGLContext extends GLContextImpl } public boolean makeCurrent(long ctx) { - return CGL.makeCurrentContext(ctx); + final long cglCtx = CGL.getCGLContext(ctx); + if(0 == cglCtx) { + throw new InternalError("Null CGLContext for: "+this); + } + int err = CGL.CGLLockContext(cglCtx); + if(CGL.kCGLNoError == err) { + return CGL.makeCurrentContext(ctx); + } else if(DEBUG) { + System.err.println("NSGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this); + } + return false; } public boolean release(long ctx) { - return CGL.clearCurrentContext(ctx); + gl.glFinish(); // w/o glFinish() OSX < 10.7 (NVidia driver) may freeze + final boolean res = CGL.clearCurrentContext(ctx); + final long cglCtx = CGL.getCGLContext(ctx); + if(0 == cglCtx) { + throw new InternalError("Null CGLContext for: "+this); + } + final int err = CGL.CGLUnlockContext(cglCtx); + if(DEBUG && CGL.kCGLNoError != err) { + System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err)+": "+this); + } + return res && CGL.kCGLNoError == err; } public boolean setSwapInterval(int interval) { - CGL.setSwapInterval(contextHandle, interval); + if(0 != nsOpenGLLayer) { + CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval); + } + CGL.setSwapInterval(contextHandle, interval); return true; } - public boolean swapBuffers(boolean isOnscreen) { - if(isOnscreen) { - return CGL.flushBuffer(contextHandle); - } - return true; + + public boolean swapBuffers() { + if(0 != nsOpenGLLayer) { + // sync w/ CALayer renderer - wait until next frame is required (v-sync) + CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, 16); // timeout 16ms -> 60Hz + } + if(CGL.flushBuffer(contextHandle)) { + if(0 != nsOpenGLLayer) { + // trigger CALayer to update + CGL.setNSOpenGLLayerNeedsDisplay(nsOpenGLLayer); + } + return true; + } + return false; } } @@ -488,7 +574,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl public long create(long share, int ctp, int major, int minor) { long ctx = 0; - MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2CGLPixelFormat(chosenCaps, ctp, major, minor); if (pixelFormat == 0) { @@ -535,11 +621,31 @@ public abstract class MacOSXCGLContext extends GLContextImpl } public boolean makeCurrent(long ctx) { - return CGL.CGLSetCurrentContext(ctx) == CGL.kCGLNoError; + int err = CGL.CGLLockContext(ctx); + if(CGL.kCGLNoError == err) { + err = CGL.CGLSetCurrentContext(ctx); + if(CGL.kCGLNoError == err) { + return true; + } else if(DEBUG) { + System.err.println("CGL: Could not make context current: err 0x"+Integer.toHexString(err)+": "+this); + } + } else if(DEBUG) { + System.err.println("CGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this); + } + return false; } public boolean release(long ctx) { - return (CGL.CGLSetCurrentContext(0) == CGL.kCGLNoError); + gl.glFinish(); // w/o glFinish() OSX < 10.7 (NVidia driver) may freeze + int err = CGL.CGLSetCurrentContext(0); + if(DEBUG && CGL.kCGLNoError != err) { + System.err.println("CGL: Could not release current context: err 0x"+Integer.toHexString(err)+": "+this); + } + int err2 = CGL.CGLUnlockContext(ctx); + if(DEBUG && CGL.kCGLNoError != err2) { + System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err2)+": "+this); + } + return CGL.kCGLNoError == err && CGL.kCGLNoError == err2; } public boolean setSwapInterval(int interval) { @@ -547,11 +653,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0); return true; } - public boolean swapBuffers(boolean isOnscreen) { - if(isOnscreen) { - return CGL.kCGLNoError == CGL.CGLFlushDrawable(contextHandle); - } - return true; + public boolean swapBuffers() { + return CGL.kCGLNoError == CGL.CGLFlushDrawable(contextHandle); } } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java index 5a35f661d..12d480fd1 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java @@ -40,6 +40,11 @@ package jogamp.opengl.macosx.cgl; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + import javax.media.nativewindow.NativeSurface; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; @@ -87,18 +92,46 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl { this.id = id; } } - + private List<WeakReference<MacOSXCGLContext>> createdContexts = new ArrayList<WeakReference<MacOSXCGLContext>>(); + private boolean haveSetOpenGLMode = false; private GLBackendType openGLMode = GLBackendType.NSOPENGL; public MacOSXCGLDrawable(GLDrawableFactory factory, NativeSurface comp, boolean realized) { super(factory, comp, realized); - initOpenGLImpl(getOpenGLMode()); - } - + initOpenGLImpl(getOpenGLMode()); + } + protected void setRealizedImpl() { } + protected long getNSViewHandle() { + return GLBackendType.NSOPENGL == openGLMode ? getHandle() : null; + } + + protected void registerContext(MacOSXCGLContext ctx) { + // NOTE: we need to keep track of the created contexts in order to + // implement swapBuffers() because of how Mac OS X implements its + // OpenGL window interface + synchronized (createdContexts) { + createdContexts.add(new WeakReference<MacOSXCGLContext>(ctx)); + } + } + protected final void swapBuffersImpl() { + // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() + synchronized (createdContexts) { + for (Iterator<WeakReference<MacOSXCGLContext>> iter = createdContexts.iterator(); iter.hasNext(); ) { + WeakReference<MacOSXCGLContext> ref = iter.next(); + MacOSXCGLContext ctx = ref.get(); + if (ctx != null) { + ctx.swapBuffers(); + } else { + iter.remove(); + } + } + } + } + public GLDynamicLookupHelper getGLDynamicLookupHelper() { return getFactoryImpl().getGLDynamicLookupHelper(0); } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index 5c726bc54..3dd7a7f08 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -42,6 +42,7 @@ package jogamp.opengl.macosx.cgl; import java.nio.Buffer; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import javax.media.nativewindow.AbstractGraphicsConfiguration; @@ -52,6 +53,7 @@ import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.macosx.MacOSXGraphicsDevice; +import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; @@ -59,6 +61,7 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import javax.media.opengl.GLProfile.ShutdownType; import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.DesktopGLDynamicLookupHelper; @@ -70,62 +73,93 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { - private static final DesktopGLDynamicLookupHelper macOSXCGLDynamicLookupHelper; - - static { - DesktopGLDynamicLookupHelper tmp = null; - try { - tmp = new DesktopGLDynamicLookupHelper(new MacOSXCGLDynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); + private static DesktopGLDynamicLookupHelper macOSXCGLDynamicLookupHelper = null; + + public MacOSXCGLDrawableFactory() { + super(); + + synchronized(MacOSXCGLDrawableFactory.class) { + if(null==macOSXCGLDynamicLookupHelper) { + DesktopGLDynamicLookupHelper tmp = null; + try { + tmp = new DesktopGLDynamicLookupHelper(new MacOSXCGLDynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } } + macOSXCGLDynamicLookupHelper = tmp; + /** FIXME ?? + if(null!=macOSXCGLDynamicLookupHelper) { + CGL.getCGLProcAddressTable().reset(macOSXCGLDynamicLookupHelper); + } */ + } + } + + if(null!=macOSXCGLDynamicLookupHelper) { + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + MacOSXCGLGraphicsConfigurationFactory.registerFactory(); + if(GLProfile.isAWTAvailable()) { + try { + ReflectionUtil.callStaticMethod("jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLGraphicsConfigurationFactory", + "registerFactory", null, null, getClass().getClassLoader()); + } catch (JogampRuntimeException jre) { /* n/a .. */ } } - macOSXCGLDynamicLookupHelper = tmp; - /** FIXME ?? - if(null!=macOSXCGLDynamicLookupHelper) { - CGL.getCGLProcAddressTable().reset(macOSXCGLDynamicLookupHelper); - } */ + + defaultDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + sharedMap = new HashMap<String, SharedResource>(); + } + } + + protected final void destroy(ShutdownType shutdownType) { + if(null != sharedMap) { + sharedMap.clear(); + sharedMap = null; + } + defaultDevice = null; + /** + * Pulling away the native library may cause havoc .. + * + if(ShutdownType.COMPLETE == shutdownType && null != macOSXCGLDynamicLookupHelper) { + macOSXCGLDynamicLookupHelper.destroy(); + macOSXCGLDynamicLookupHelper = null; + } */ } public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) { return macOSXCGLDynamicLookupHelper; } - public MacOSXCGLDrawableFactory() { - super(); - - // Register our GraphicsConfigurationFactory implementations - // The act of constructing them causes them to be registered - new MacOSXCGLGraphicsConfigurationFactory(); - if(GLProfile.isAWTAvailable()) { - try { - ReflectionUtil.createInstance("jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLGraphicsConfigurationFactory", - null, getClass().getClassLoader()); - } catch (JogampRuntimeException jre) { /* n/a .. */ } - } - - defaultDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); - } + private HashMap<String, SharedResource> sharedMap = new HashMap<String, SharedResource>(); + private MacOSXGraphicsDevice defaultDevice; static class SharedResource { // private MacOSXCGLDrawable drawable; // private MacOSXCGLContext context; MacOSXGraphicsDevice device; boolean wasContextCreated; + boolean hasNPOTTextures; + boolean hasRECTTextures; + boolean hasAppletFloatPixels; - SharedResource(MacOSXGraphicsDevice device, boolean wasContextCreated + SharedResource(MacOSXGraphicsDevice device, boolean wasContextCreated, + boolean hasNPOTTextures, boolean hasRECTTextures, boolean hasAppletFloatPixels /* MacOSXCGLDrawable draw, MacOSXCGLContext ctx */) { // drawable = draw; // context = ctx; this.device = device; this.wasContextCreated = wasContextCreated; + this.hasNPOTTextures = hasNPOTTextures; + this.hasRECTTextures = hasRECTTextures; + this.hasAppletFloatPixels = hasAppletFloatPixels; } final MacOSXGraphicsDevice getDevice() { return device; } final boolean wasContextAvailable() { return wasContextCreated; } + final boolean isNPOTTextureAvailable() { return hasNPOTTextures; } + final boolean isRECTTextureAvailable() { return hasRECTTextures; } + final boolean isAppletFloatPixelsAvailable() { return hasAppletFloatPixels; } } - HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); - MacOSXGraphicsDevice defaultDevice; public final AbstractGraphicsDevice getDefaultDevice() { return defaultDevice; @@ -138,52 +172,79 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { return false; } - private boolean isOSXContextAvailable(AbstractGraphicsDevice sharedDevice) { - boolean madeCurrent = false; - GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP); - if (null == glp) { - throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); - } - final GLCapabilities caps = new GLCapabilities(glp); - caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); - caps.setDoubleBuffered(false); - caps.setOnscreen(false); - caps.setPBuffer(true); - final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) ); - if(null!=drawable) { - final GLContext context = drawable.createContext(null); - if (null != context) { - context.setSynchronized(true); - try { - context.makeCurrent(); // could cause exception - madeCurrent = context.isCurrent(); - } catch (GLException gle) { - if (DEBUG) { - System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent failed"); - gle.printStackTrace(); - } - } finally { - context.destroy(); - } - } - drawable.destroy(); - } - return madeCurrent; + private HashSet<String> devicesTried = new HashSet<String>(); + + private boolean getDeviceTried(String connection) { + synchronized (devicesTried) { + return devicesTried.contains(connection); + } + } + private void addDeviceTried(String connection) { + synchronized (devicesTried) { + devicesTried.add(connection); + } + } + private void removeDeviceTried(String connection) { + synchronized (devicesTried) { + devicesTried.remove(connection); + } } /* package */ SharedResource getOrCreateOSXSharedResource(AbstractGraphicsDevice adevice) { - String connection = adevice.getConnection(); + final String connection = adevice.getConnection(); SharedResource sr; synchronized(sharedMap) { - sr = (SharedResource) sharedMap.get(connection); + sr = sharedMap.get(connection); } - if(null==sr) { + if(null==sr && !getDeviceTried(connection)) { + addDeviceTried(connection); final MacOSXGraphicsDevice sharedDevice = new MacOSXGraphicsDevice(adevice.getUnitID()); - final boolean madeCurrent = isOSXContextAvailable(sharedDevice); - sr = new SharedResource(sharedDevice, madeCurrent); + boolean madeCurrent = false; + boolean hasNPOTTextures = false; + boolean hasRECTTextures = false; + boolean hasAppletFloatPixels = false; + { + GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP); + if (null == glp) { + throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); + } + final GLCapabilities caps = new GLCapabilities(glp); + caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); + caps.setDoubleBuffered(false); + caps.setOnscreen(false); + caps.setPBuffer(true); + final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) ); + if(null!=drawable) { + drawable.setRealized(true); + final GLContext context = drawable.createContext(null); + if (null != context) { + context.setSynchronized(true); + try { + context.makeCurrent(); // could cause exception + madeCurrent = context.isCurrent(); + if(madeCurrent) { + GL gl = context.getGL(); + hasNPOTTextures = gl.isNPOTTextureAvailable(); + hasRECTTextures = gl.isExtensionAvailable("GL_EXT_texture_rectangle"); + hasAppletFloatPixels = gl.isExtensionAvailable("GL_APPLE_float_pixels"); + } + } catch (GLException gle) { + if (DEBUG) { + System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent failed"); + gle.printStackTrace(); + } + } finally { + context.destroy(); + } + } + drawable.destroy(); + } + } + sr = new SharedResource(sharedDevice, madeCurrent, hasNPOTTextures, hasRECTTextures, hasAppletFloatPixels); synchronized(sharedMap) { sharedMap.put(connection, sr); } + removeDeviceTried(connection); if (DEBUG) { System.err.println("MacOSXCGLDrawableFactory.createShared: device: " + sharedDevice); System.err.println("MacOSXCGLDrawableFactory.createShared: context: " + madeCurrent); @@ -191,11 +252,22 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } return sr; } - - public final boolean getWasSharedContextCreated(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateOSXSharedResource(device); - if(null!=sr) { - return sr.wasContextAvailable(); + + protected final Thread getSharedResourceThread() { + return null; + } + + protected final boolean createSharedResource(AbstractGraphicsDevice device) { + try { + SharedResource sr = getOrCreateOSXSharedResource(device); + if(null!=sr) { + return sr.wasContextAvailable(); + } + } catch (GLException gle) { + if(DEBUG) { + System.err.println("Catched Exception while MaxOSXCGL Shared Resource initialization"); + gle.printStackTrace(); + } } return false; } @@ -213,8 +285,6 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { return null; } - protected final void shutdownInstance() {} - protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) { return MacOSXCGLGraphicsConfiguration.getAvailableCapabilities(this, device); } @@ -227,26 +297,11 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) { - AbstractGraphicsConfiguration config = target.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsConfiguration config = target.getGraphicsConfiguration(); GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); if(!caps.isPBuffer()) { return new MacOSXOffscreenCGLDrawable(this, target); } - - // PBuffer GLDrawable Creation - /** - * FIXME: Think about this .. - * should not be necessary ? .. - final List returnList = new ArrayList(); - final GLDrawableFactory factory = this; - Runnable r = new Runnable() { - public void run() { - returnList.add(new MacOSXPbufferCGLDrawable(factory, target)); - } - }; - maybeDoSingleThreadedWorkaround(r); - return (GLDrawableImpl) returnList.get(0); - */ return new MacOSXPbufferCGLDrawable(this, target); } @@ -257,7 +312,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_MACOSX); WrappedSurface ns = new WrappedSurface(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, true)); - ns.setSize(width, height); + ns.surfaceSizeChanged(width, height); return ns; } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java index a429720db..f552ab3dd 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java @@ -41,15 +41,16 @@ import java.util.List; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; -import javax.media.nativewindow.DefaultGraphicsConfiguration; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.MutableGraphicsConfiguration; + import com.jogamp.common.nio.PointerBuffer; -public class MacOSXCGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { +public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { long pixelformat; MacOSXCGLGraphicsConfiguration(AbstractGraphicsScreen screen, @@ -67,10 +68,6 @@ public class MacOSXCGLGraphicsConfiguration extends DefaultGraphicsConfiguration this.pixelformat=pixelformat; } - void setChosenCapabilities(GLCapabilitiesImmutable caps) { - super.setChosenCapabilities(caps); - } - protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(MacOSXCGLDrawableFactory factory, AbstractGraphicsDevice device) { MacOSXCGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateOSXSharedResource(device); if(null == sharedResource) { @@ -83,6 +80,8 @@ public class MacOSXCGLGraphicsConfiguration extends DefaultGraphicsConfiguration static final int[] cglInternalAttributeToken = new int[] { CGL.kCGLPFAOpenGLProfile, CGL.kCGLPFAColorFloat, + CGL.NSOpenGLPFANoRecovery, + CGL.NSOpenGLPFAAccelerated, CGL.NSOpenGLPFAPixelBuffer, CGL.NSOpenGLPFADoubleBuffer, CGL.NSOpenGLPFAStereo, @@ -114,6 +113,13 @@ public class MacOSXCGLGraphicsConfiguration extends DefaultGraphicsConfiguration ivalues[idx] = caps.getPbufferFloatingPointBuffers() ? 1 : 0; break; + case CGL.NSOpenGLPFANoRecovery: + ivalues[idx] = caps.getHardwareAccelerated() ? 1 : 0; + break; + case CGL.NSOpenGLPFAAccelerated: + ivalues[idx] = caps.getHardwareAccelerated() ? 1 : 0; + break; + case CGL.NSOpenGLPFAPixelBuffer: ivalues[idx] = caps.isPBuffer() ? 1 : 0; break; @@ -222,7 +228,7 @@ public class MacOSXCGLGraphicsConfiguration extends DefaultGraphicsConfiguration // Use attribute array to select pixel format PointerBuffer fmt = PointerBuffer.allocateDirect(1); - long[] numScreens = new long[1]; + int[] numScreens = new int[1]; int res = CGL.CGLChoosePixelFormat(attrs, 0, fmt, numScreens, 0); if (res != CGL.kCGLNoError) { throw new GLException("Error code " + res + " while choosing pixel format"); @@ -285,6 +291,10 @@ public class MacOSXCGLGraphicsConfiguration extends DefaultGraphicsConfiguration caps.setPbufferFloatingPointBuffers(ivalues[i] != 0); break; + case CGL.NSOpenGLPFAAccelerated: + caps.setHardwareAccelerated(ivalues[i] != 0); + break; + case CGL.NSOpenGLPFAPixelBuffer: caps.setPBuffer(ivalues[i] != 0); break; diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java index d4526f04e..0de290c6b 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java @@ -51,8 +51,10 @@ import javax.media.opengl.GLCapabilitiesImmutable; public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { protected static final boolean DEBUG = jogamp.opengl.Debug.debug("GraphicsConfiguration"); - MacOSXCGLGraphicsConfigurationFactory() { - GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.macosx.MacOSXGraphicsDevice.class, this); + static void registerFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.macosx.MacOSXGraphicsDevice.class, new MacOSXCGLGraphicsConfigurationFactory()); + } + private MacOSXCGLGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index 08a531200..6ce2d7ba7 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -48,9 +48,9 @@ import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; -import javax.media.opengl.GLProfile; import jogamp.nativewindow.WrappedSurface; +import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLContextShareSet; import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType; @@ -61,10 +61,10 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { private MacOSXExternalCGLContext(Drawable drawable, boolean isNSContext, long handle) { super(drawable, null); setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL ); - drawable.setExternalCGLContext(this); + drawable.registerContext(this); this.contextHandle = handle; GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } @@ -118,7 +118,7 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { return new MacOSXExternalCGLContext(new Drawable(factory, ns), isNSContext, contextHandle); } - protected boolean createImpl() throws GLException { + protected boolean createImpl(GLContextImpl shareWith) throws GLException { return true; } @@ -139,7 +139,7 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { lastContext = null; } - protected void makeCurrentImpl(boolean newCreated) throws GLException { + protected void makeCurrentImpl() throws GLException { } protected void releaseImpl() throws GLException { @@ -150,16 +150,10 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { // Need to provide the display connection to extension querying APIs static class Drawable extends MacOSXCGLDrawable { - MacOSXExternalCGLContext extCtx; - Drawable(GLDrawableFactory factory, NativeSurface comp) { super(factory, comp, true); } - void setExternalCGLContext(MacOSXExternalCGLContext externalContext) { - extCtx = externalContext; - } - public GLContext createContext(GLContext shareWith) { throw new GLException("Should not call this"); } @@ -175,11 +169,5 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { public void setSize(int width, int height) { throw new GLException("Should not call this"); } - - protected void swapBuffersImpl() { - if (extCtx != null) { - extCtx.swapBuffers(); - } - } } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java index bec4cf32a..f81cd725e 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java @@ -40,9 +40,9 @@ package jogamp.opengl.macosx.cgl; -import javax.media.opengl.*; -import javax.media.nativewindow.*; -import jogamp.opengl.*; +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; public class MacOSXOffscreenCGLDrawable extends MacOSXPbufferCGLDrawable { diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java index 97d198c92..9e051311c 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java @@ -42,6 +42,8 @@ package jogamp.opengl.macosx.cgl; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; +import jogamp.opengl.GLContextImpl; + public class MacOSXOnscreenCGLContext extends MacOSXCGLContext { public MacOSXOnscreenCGLContext(MacOSXOnscreenCGLDrawable drawable, @@ -50,14 +52,20 @@ public class MacOSXOnscreenCGLContext extends MacOSXCGLContext { } @Override - protected void makeCurrentImpl(boolean newCreated) throws GLException { - super.makeCurrentImpl(newCreated); + protected void makeCurrentImpl() throws GLException { + super.makeCurrentImpl(); drawableUpdatedNotify(); } @Override protected void drawableUpdatedNotify() throws GLException { - if(0==updateHandle || CGL.updateContextNeedsUpdate(updateHandle)) { + final int w = drawable.getWidth(); + final int h = drawable.getHeight(); + final boolean updateContext = ( 0!=updateHandle && CGL.updateContextNeedsUpdate(updateHandle) ) || + w != lastWidth || h != lastHeight; + if(updateContext) { + lastWidth = w; + lastHeight = h; if (contextHandle == 0) { throw new GLException("Context not created"); } @@ -65,11 +73,11 @@ public class MacOSXOnscreenCGLContext extends MacOSXCGLContext { } } - protected long updateHandle = 0; - @Override - protected boolean createImpl() { - boolean res = super.createImpl(); + protected boolean createImpl(GLContextImpl sharedWith) { + boolean res = super.createImpl(sharedWith); + lastWidth = -1; + lastHeight = -1; if(res && isNSContext()) { if(0 != updateHandle) { throw new InternalError("XXX1"); @@ -89,5 +97,8 @@ public class MacOSXOnscreenCGLContext extends MacOSXCGLContext { updateHandle = 0; } super.destroyImpl(); - } + } + + private long updateHandle = 0; + private int lastWidth, lastHeight; } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java index 24276c39e..80c54042f 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java @@ -40,44 +40,20 @@ package jogamp.opengl.macosx.cgl; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - import javax.media.nativewindow.NativeSurface; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; public class MacOSXOnscreenCGLDrawable extends MacOSXCGLDrawable { - private List<WeakReference<MacOSXCGLContext>> createdContexts = new ArrayList<WeakReference<MacOSXCGLContext>>(); - + protected MacOSXOnscreenCGLDrawable(GLDrawableFactory factory, NativeSurface component) { super(factory, component, false); } public GLContext createContext(GLContext shareWith) { - MacOSXOnscreenCGLContext ctx= new MacOSXOnscreenCGLContext(this, shareWith); - // NOTE: we need to keep track of the created contexts in order to - // implement swapBuffers() because of how Mac OS X implements its - // OpenGL window interface - synchronized (createdContexts) { - createdContexts.add(new WeakReference<MacOSXCGLContext>(ctx)); - } + final MacOSXOnscreenCGLContext ctx= new MacOSXOnscreenCGLContext(this, shareWith); + registerContext(ctx); return ctx; } - protected void swapBuffersImpl() { - synchronized (createdContexts) { - for (Iterator<WeakReference<MacOSXCGLContext>> iter = createdContexts.iterator(); iter.hasNext(); ) { - WeakReference<MacOSXCGLContext> ref = iter.next(); - MacOSXCGLContext ctx = ref.get(); - if (ctx != null) { - ctx.swapBuffers(); - } else { - iter.remove(); - } - } - } - } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java index c5743b923..7ba7d2d5a 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java @@ -33,19 +33,16 @@ package jogamp.opengl.macosx.cgl; -import javax.media.nativewindow.DefaultGraphicsConfiguration; import javax.media.opengl.GL; -import javax.media.opengl.GL2; -import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLPbuffer; +import jogamp.opengl.GLContextImpl; public class MacOSXPbufferCGLContext extends MacOSXCGLContext { // State for render-to-texture and render-to-texture-rectangle support - private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV private int texture; // actual texture object public MacOSXPbufferCGLContext(MacOSXPbufferCGLDrawable drawable, @@ -55,7 +52,7 @@ public class MacOSXPbufferCGLContext extends MacOSXCGLContext { public void bindPbufferToTexture() { GL gl = getGL(); - gl.glBindTexture(textureTarget, texture); + gl.glBindTexture(((MacOSXPbufferCGLDrawable)drawable).getTextureTarget(), texture); // FIXME: not clear whether this is really necessary, but since // the API docs seem to imply it is and since it doesn't seem to // impact performance, leaving it in @@ -65,23 +62,14 @@ public class MacOSXPbufferCGLContext extends MacOSXCGLContext { public void releasePbufferFromTexture() { } - protected void makeCurrentImpl(boolean newCreated) throws GLException { - super.makeCurrentImpl(newCreated); - - if (newCreated) { + protected boolean createImpl(GLContextImpl shareWith) { + boolean res = super.createImpl(shareWith); + if(res) { // Initialize render-to-texture support if requested - DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities(); - GL gl = getGL(); - boolean rect = gl.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle(); - if (rect) { - if (!gl.isExtensionAvailable("GL_EXT_texture_rectangle")) { - System.err.println("MacOSXPbufferCGLContext: WARNING: GL_EXT_texture_rectangle extension not " + - "supported; skipping requested render_to_texture_rectangle support for pbuffer"); - rect = false; - } - } - textureTarget = (rect ? GL2.GL_TEXTURE_RECTANGLE : GL.GL_TEXTURE_2D); + final GL gl = getGL(); + final MacOSXPbufferCGLDrawable osxPDrawable = (MacOSXPbufferCGLDrawable)drawable; + final int textureTarget = osxPDrawable.getTextureTarget(); + int[] tmp = new int[1]; gl.glGenTextures(1, tmp, 0); texture = tmp[0]; @@ -90,8 +78,11 @@ public class MacOSXPbufferCGLContext extends MacOSXCGLContext { gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); - gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0); + gl.glTexImage2D(textureTarget, 0, GL.GL_RGB, osxPDrawable.getTextureWidth(), osxPDrawable.getTextureHeight(), + 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, null); + gl.glCopyTexSubImage2D(textureTarget, 0, 0, 0, 0, 0, drawable.getWidth(), drawable.getHeight()); } + return res; } public int getFloatingPointMode() { diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java index fdbfaf6d6..e02c3efec 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java @@ -51,14 +51,10 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import jogamp.opengl.Debug; - import com.jogamp.common.nio.PointerBuffer; +import com.jogamp.opengl.util.GLBuffers; - -public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { - private static final boolean DEBUG = Debug.debug("MacOSXPbufferCGLDrawable"); - +public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { // Abstract interface for implementation of this drawable (either // NSOpenGL-based or CGL-based) interface GLBackendImpl { @@ -76,34 +72,46 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { // Note that we can not store this in the NativeSurface because the // semantic is that contains an NSView protected long pBuffer; + protected int pBufferTexTarget, pBufferTexWidth, pBufferTexHeight; public MacOSXPbufferCGLDrawable(GLDrawableFactory factory, NativeSurface target) { - super(factory, target, true); - - if (DEBUG) { - System.out.println("Pbuffer config: " + getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration()); - } - - createPbuffer(); - - if (DEBUG) { - System.err.println("Created pbuffer " + this); - } + super(factory, target, false); } + protected void destroyImpl() { + setRealized(false); + } + protected void setRealizedImpl() { if(realized) { createPbuffer(); } else { - destroyImpl(); + destroyPbuffer(); } } public GLContext createContext(GLContext shareWith) { - return new MacOSXPbufferCGLContext(this, shareWith); + final MacOSXPbufferCGLContext ctx = new MacOSXPbufferCGLContext(this, shareWith); + registerContext(ctx); + return ctx; } - protected void destroyImpl() { + @Override + protected long getNSViewHandle() { + // pbuffer handle is NSOpenGLPixelBuffer + return 0; + } + + @Override + public long getHandle() { + return pBuffer; + } + + protected int getTextureTarget() { return pBufferTexTarget; } + protected int getTextureWidth() { return pBufferTexWidth; } + protected int getTextureHeight() { return pBufferTexHeight; } + + protected void destroyPbuffer() { if (this.pBuffer != 0) { NativeSurface ns = getNativeSurface(); impl.destroy(pBuffer); @@ -112,73 +120,56 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { } } - public long getHandle() { - return pBuffer; - } - - protected void swapBuffersImpl() { - if(DEBUG) { - System.err.println("unhandled swapBuffersImpl() called for: "+this); + private void createPbuffer() { + final NativeSurface ns = getNativeSurface(); + final DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ns.getGraphicsConfiguration(); + final GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities(); + final GLProfile glProfile = capabilities.getGLProfile(); + MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateOSXSharedResource(config.getScreen().getDevice()); + + if (DEBUG) { + System.out.println("Pbuffer config: " + config); } - } - private void createPbuffer() { - NativeSurface ns = getNativeSurface(); - DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); - GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities(); - GLProfile glProfile = capabilities.getGLProfile(); - int renderTarget; - if (glProfile.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle()) { - renderTarget = GL2.GL_TEXTURE_RECTANGLE; + if ( capabilities.getPbufferRenderToTextureRectangle() && null!=sr && sr.isRECTTextureAvailable() ) { + pBufferTexTarget = GL2.GL_TEXTURE_RECTANGLE; } else { - int w = getNextPowerOf2(getWidth()); - int h = getNextPowerOf2(getHeight()); - ((SurfaceChangeable)ns).setSize(w, h); - renderTarget = GL.GL_TEXTURE_2D; + pBufferTexTarget = GL.GL_TEXTURE_2D; + } + if ( GL2.GL_TEXTURE_RECTANGLE == pBufferTexTarget || ( null!=sr && sr.isNPOTTextureAvailable() ) ) { + pBufferTexWidth = getWidth(); + pBufferTexHeight = getHeight(); + } else { + pBufferTexWidth = GLBuffers.getNextPowerOf2(getWidth()); + pBufferTexHeight = GLBuffers.getNextPowerOf2(getHeight()); } int internalFormat = GL.GL_RGBA; if (capabilities.getPbufferFloatingPointBuffers()) { - // FIXME: want to check availability of GL_APPLE_float_pixels - // extension, but need valid OpenGL context in order to do so -- - // in worst case would need to create dummy window / GLCanvas - // (undesirable) -- could maybe also do this with pbuffers - /* - if (!gl.isExtensionAvailable("GL_APPLE_float_pixels")) { - throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available"); - } - */ - if(glProfile.isGL2GL3()) { - switch (capabilities.getRedBits()) { + if(!glProfile.isGL2GL3() || null==sr || sr.isAppletFloatPixelsAvailable()) { + throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available"); + } + switch (capabilities.getRedBits()) { case 16: internalFormat = GL2.GL_RGBA_FLOAT16_APPLE; break; case 32: internalFormat = GL2.GL_RGBA_FLOAT32_APPLE; break; default: throw new GLException("Invalid floating-point bit depth (only 16 and 32 supported)"); - } - } else { - internalFormat = GL.GL_RGBA; } } - - pBuffer = impl.create(renderTarget, internalFormat, getWidth(), getHeight()); + + pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight()); + if(DEBUG) { + System.err.println("MacOSXPbufferCGLDrawable tex: target "+toHexString(pBufferTexTarget)+ + ", pbufferSize "+getWidth()+"x"+getHeight()+ + ", texSize "+pBufferTexWidth+"x"+pBufferTexHeight+ + ", internal-fmt "+toHexString(internalFormat)); + System.err.println("MacOSXPbufferCGLDrawable pBuffer: "+toHexString(pBuffer)); + // Thread.dumpStack(); + } if (pBuffer == 0) { throw new GLException("pbuffer creation error: CGL.createPBuffer() failed"); } ((SurfaceChangeable)ns).setSurfaceHandle(pBuffer); - - } - - private int getNextPowerOf2(int number) { - if (((number-1) & number) == 0) { - //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0 - return number; - } - int power = 0; - while (number > 0) { - number = number>>1; - power++; - } - return (1<<power); } public void setOpenGLMode(GLBackendType mode) { diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java index 68e82dc19..a8c04eee4 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java @@ -58,8 +58,10 @@ import jogamp.opengl.macosx.cgl.MacOSXCGLGraphicsConfiguration; public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { protected static final boolean DEBUG = jogamp.opengl.Debug.debug("GraphicsConfiguration"); - public MacOSXAWTCGLGraphicsConfigurationFactory() { - GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, this); + public static void registerFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, new MacOSXAWTCGLGraphicsConfigurationFactory()); + } + private MacOSXAWTCGLGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( @@ -72,7 +74,7 @@ public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigur } if(null==absScreen) { - absScreen = AWTGraphicsScreen.createScreenDevice(-1, AbstractGraphicsDevice.DEFAULT_UNIT); + absScreen = AWTGraphicsScreen.createDefault(); } AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen; device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java index ae58f6811..70416d1f4 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java @@ -44,6 +44,7 @@ import java.awt.Graphics; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; +import jogamp.opengl.GLContextImpl; import jogamp.opengl.awt.Java2D; import jogamp.opengl.awt.Java2DGLContext; import jogamp.opengl.macosx.cgl.MacOSXCGLContext; @@ -73,20 +74,30 @@ public class MacOSXJava2DCGLContext extends MacOSXCGLContext implements Java2DGL this.graphics = g; } - protected void makeCurrentImpl(boolean newCreated) throws GLException { + protected void makeCurrentImpl() throws GLException { if (!Java2D.makeOGLContextCurrentOnSurface(graphics, contextHandle)) { throw new GLException("Error making context current"); } } - protected boolean createImpl() { - long share = createImplPreset(); + protected boolean createImpl(GLContextImpl shareWith) { + long share = createImplPreset(shareWith); long ctx = Java2D.createOGLContextOnSurface(graphics, share); if (ctx == 0) { + if(DEBUG) { + System.err.println("Error creating current: "+this); + } return false; } - setGLFunctionAvailability(true, true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + if (!Java2D.makeOGLContextCurrentOnSurface(graphics, contextHandle)) { + Java2D.destroyOGLContext(ctx); + if(DEBUG) { + System.err.println("Error making created context current: "+this); + } + return false; + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION contextHandle = ctx; return true; } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java new file mode 100644 index 000000000..845d749ba --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java @@ -0,0 +1,95 @@ +/** + * 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.opengl.windows.wgl; + +import java.security.AccessController; + +import jogamp.nativewindow.windows.GDI; +import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR; +import jogamp.opengl.Debug; + +public class WGLUtil { + /** + * Switch to use the <code>wgl</code> variants of {@link jogamp.opengl.windows.wgl.WGL} + * to replace the following 5 GDI based functions (see below). + * <p> + * Disabled per default. + * </p> + * <p> + * You can enable it by defining the property <code>jogl.windows.useWGLVersionOf5WGLGDIFuncSet</code>. + * </p> + * + * @see jogamp.nativewindow.windows.GDI#ChoosePixelFormat(long, PIXELFORMATDESCRIPTOR) + * @see jogamp.nativewindow.windows.GDI#DescribePixelFormat(long, int, int, PIXELFORMATDESCRIPTOR) + * @see jogamp.nativewindow.windows.GDI#GetPixelFormat(long) + * @see jogamp.nativewindow.windows.GDI#SetPixelFormat(long, int, PIXELFORMATDESCRIPTOR) + * @see jogamp.nativewindow.windows.GDI#SwapBuffers(long) + */ + public static final boolean USE_WGLVersion_Of_5WGLGDIFuncSet; + + static { + USE_WGLVersion_Of_5WGLGDIFuncSet = Debug.isPropertyDefined("jogl.windows.useWGLVersionOf5WGLGDIFuncSet", true, AccessController.getContext()); + System.err.println("USE_WGLVersion_Of_5WGLGDIFuncSet: "+USE_WGLVersion_Of_5WGLGDIFuncSet); + } + + public static int ChoosePixelFormat(long hdc, PIXELFORMATDESCRIPTOR pfd) { + if(USE_WGLVersion_Of_5WGLGDIFuncSet) { + return WGL.wglChoosePixelFormat(hdc, pfd); + } else { + return GDI.ChoosePixelFormat(hdc, pfd); + } + } + public static int DescribePixelFormat(long hdc, int pfdid, int pfdSize, PIXELFORMATDESCRIPTOR pfd) { + if(USE_WGLVersion_Of_5WGLGDIFuncSet) { + return WGL.wglDescribePixelFormat(hdc, pfdid, pfdSize, pfd); + } else { + return GDI.DescribePixelFormat(hdc, pfdid, pfdSize, pfd); + } + } + public static int GetPixelFormat(long hdc) { + if(USE_WGLVersion_Of_5WGLGDIFuncSet) { + return WGL.wglGetPixelFormat(hdc); + } else { + return GDI.GetPixelFormat(hdc); + } + } + public static boolean SetPixelFormat(long hdc, int pfdid, PIXELFORMATDESCRIPTOR pfd) { + if(USE_WGLVersion_Of_5WGLGDIFuncSet) { + return WGL.wglSetPixelFormat(hdc, pfdid, pfd); + } else { + return GDI.SetPixelFormat(hdc, pfdid, pfd); + } + } + public static boolean SwapBuffers(long hdc) { + if(USE_WGLVersion_Of_5WGLGDIFuncSet) { + return WGL.wglSwapBuffers(hdc); + } else { + return GDI.SwapBuffers(hdc); + } + } +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java index b2c95de39..574226570 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java @@ -57,15 +57,18 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { private long hbitmap; protected WindowsBitmapWGLDrawable(GLDrawableFactory factory, NativeSurface target) { - super(factory, target, true); - create(); + super(factory, target, false); } + protected void destroyImpl() { + setRealized(false); + } + protected void setRealizedImpl() { if(realized) { - create(); + createBitmap(); } else { - destroyImpl(); + destroyBitmap(); } } @@ -73,13 +76,13 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { return new WindowsBitmapWGLContext(this, shareWith); } - private void create() { + private void createBitmap() { int werr; NativeSurface ns = getNativeSurface(); if(DEBUG) { System.err.println("WindowsBitmapWGLDrawable (1): "+ns); } - WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration(); GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getRequestedCapabilities(); int width = getWidth(); int height = getHeight(); @@ -153,7 +156,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { config.updateGraphicsConfiguration(getFactory(), ns, null); } - protected void destroyImpl() { + protected void destroyBitmap() { NativeSurface ns = getNativeSurface(); if (ns.getSurfaceHandle() != 0) { // Must destroy bitmap and device context @@ -165,11 +168,4 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { ((SurfaceChangeable)ns).setSurfaceHandle(0); } } - - protected void swapBuffersImpl() { - if(DEBUG) { - System.err.println("unhandled swapBuffersImpl() called for: "+this); - } - } - } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java index 3d0cce725..0bd83b923 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java @@ -46,6 +46,8 @@ import javax.media.opengl.GLProfile; import javax.media.nativewindow.AbstractGraphicsScreen; import jogamp.nativewindow.windows.GDI; +import jogamp.nativewindow.windows.GDIUtil; + import javax.media.nativewindow.NativeSurface; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLException; @@ -63,7 +65,7 @@ public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { throw new GLException("WindowsDummyWGLDrawable: surface not ready (lockSurface)"); } try { - WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration(); config.updateGraphicsConfiguration(factory, ns, null); if (DEBUG) { System.err.println("!!! WindowsDummyWGLDrawable: "+config); @@ -84,7 +86,7 @@ public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { GLCapabilities caps = new GLCapabilities(glp); WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.createDefaultGraphicsConfiguration(caps, absScreen); GDISurface ns = new GDISurface(cfg, windowHandle); - ns.setSize(width, height); + ns.surfaceSizeChanged(width, height); return new WindowsDummyWGLDrawable(factory, ns, handleWindowLifecycle); } @@ -96,7 +98,7 @@ public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { protected void destroyImpl() { if (handleHwndLifecycle && hwnd != 0) { GDI.ShowWindow(hwnd, GDI.SW_HIDE); - GDI.DestroyDummyWindow(hwnd); + GDIUtil.DestroyDummyWindow(hwnd); hwnd = 0; } } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java index c3588fd48..b183ad59f 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java @@ -65,7 +65,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { System.err.println(getThreadName() + ": !!! Created external OpenGL context " + toHexString(ctx) + " for " + this); } GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } @@ -85,7 +85,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { } AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); WindowsWGLGraphicsConfiguration cfg; - final int pfdID = GDI.GetPixelFormat(hdc); + final int pfdID = WGLUtil.GetPixelFormat(hdc); if (0 == pfdID) { // This could have happened if the HDC was released right after the GL ctx made current (SWT), // WinXP-32bit will not be able to use this HDC afterwards. @@ -122,7 +122,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { lastContext = null; } - protected void makeCurrentImpl(boolean newCreated) throws GLException { + protected void makeCurrentImpl() throws GLException { } protected void releaseImpl() throws GLException { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java index ede504735..1e5991821 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java @@ -63,7 +63,7 @@ public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { if (0==hdc) { throw new GLException("Error: attempted to make an external GLDrawable without a drawable current, werr " + GDI.GetLastError()); } - int pfdID = GDI.GetPixelFormat(hdc); + int pfdID = WGLUtil.GetPixelFormat(hdc); if (pfdID == 0) { throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat, werr " + GDI.GetLastError()); } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java index 4f34c946a..6ad330ccc 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java @@ -42,7 +42,6 @@ package jogamp.opengl.windows.wgl; import javax.media.nativewindow.*; import javax.media.opengl.*; -import jogamp.opengl.*; public class WindowsOnscreenWGLDrawable extends WindowsWGLDrawable { protected WindowsOnscreenWGLDrawable(GLDrawableFactory factory, NativeSurface component) { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java index 97c63ea52..0f610495d 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java @@ -42,6 +42,8 @@ package jogamp.opengl.windows.wgl; import javax.media.opengl.*; +import jogamp.opengl.GLContextImpl; + public class WindowsPbufferWGLContext extends WindowsWGLContext { // State for render-to-texture and render-to-texture-rectangle support private boolean rtt; // render-to-texture? @@ -86,9 +88,9 @@ public class WindowsPbufferWGLContext extends WindowsWGLContext { } } - protected void makeCurrentImpl(boolean newCreated) throws GLException { - super.makeCurrentImpl(newCreated); - if (newCreated) { + protected boolean createImpl(GLContextImpl shareWith) { + boolean res = super.createImpl(shareWith); + if(res) { GLCapabilitiesImmutable capabilities = drawable.getChosenGLCapabilities(); // Initialize render-to-texture support if requested @@ -135,6 +137,7 @@ public class WindowsPbufferWGLContext extends WindowsWGLContext { } } } + return res; } public int getFloatingPointMode() { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java index 7be2c1ac7..0988f3eca 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java @@ -41,6 +41,7 @@ package jogamp.opengl.windows.wgl; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.SurfaceChangeable; import javax.media.opengl.GL; import javax.media.opengl.GLContext; @@ -51,6 +52,7 @@ import javax.media.opengl.GLProfile; import jogamp.nativewindow.windows.GDI; import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.windows.wgl.WindowsWGLDrawableFactory.SharedResource; import javax.media.opengl.GLCapabilitiesImmutable; @@ -60,27 +62,20 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { private long buffer; // pbuffer handle private int floatMode; - - protected WindowsPbufferWGLDrawable(GLDrawableFactory factory, NativeSurface target, - WindowsWGLDrawableFactory.SharedResource sharedResource) { - super(factory, target, true); - - if (DEBUG) { - System.out.println("Pbuffer config: " + getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration()); - } - - createPbuffer(sharedResource); - - if (DEBUG) { - System.err.println("Created pbuffer " + this); - } + + protected WindowsPbufferWGLDrawable(GLDrawableFactory factory, NativeSurface target) { + super(factory, target, false); } + protected void destroyImpl() { + setRealized(false); + } + protected void setRealizedImpl() { if(realized) { - throw new GLException("Recreation via setRealized not supported."); + createPbuffer(); } else { - destroyImpl(); + destroyPbuffer(); } } @@ -88,7 +83,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { return new WindowsPbufferWGLContext(this, shareWith); } - protected void destroyImpl() { + protected void destroyPbuffer() { NativeSurface ns = getNativeSurface(); if(0!=buffer) { WGLExt wglExt = cachedWGLExt; @@ -120,147 +115,154 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { return floatMode; } - protected void swapBuffersImpl() { - if(DEBUG) { - System.err.println("unhandled swapBuffersImpl() called for: "+this); + private void createPbuffer() { + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration(); + SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(config.getScreen().getDevice()); + NativeSurface sharedSurface = sharedResource.getDrawable().getNativeSurface(); + if (NativeSurface.LOCK_SURFACE_NOT_READY >= sharedSurface.lockSurface()) { + throw new NativeWindowException("Could not lock (sharedSurface): "+this); } - } - - private void createPbuffer(WindowsWGLDrawableFactory.SharedResource sharedResource) { - long parentHdc = sharedResource.getDrawable().getNativeSurface().getSurfaceHandle(); - WGLExt wglExt = sharedResource.getContext().getWGLExt(); + try { + long sharedHdc = sharedSurface.getSurfaceHandle(); + WGLExt wglExt = sharedResource.getContext().getWGLExt(); + + if (DEBUG) { + System.out.println("Pbuffer config: " + config); + } - int[] iattributes = new int [2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS]; - float[] fattributes = new float[1]; - int[] floatModeTmp = new int[1]; - int niattribs = 0; - int width, height; - - WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); - GLProfile glProfile = chosenCaps.getGLProfile(); - - if (DEBUG) { - System.out.println("Pbuffer parentHdc = " + toHexString(parentHdc)); - System.out.println("Pbuffer chosenCaps: " + chosenCaps); - } - - if(!WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(chosenCaps, - iattributes, sharedResource, -1, floatModeTmp)){ - throw new GLException("Pbuffer-related extensions not supported"); - } - - floatMode = floatModeTmp[0]; - boolean rtt = chosenCaps.getPbufferRenderToTexture(); - boolean rect = chosenCaps.getPbufferRenderToTextureRectangle(); - boolean useFloat = chosenCaps.getPbufferFloatingPointBuffers(); - // boolean ati = false; - - /** - if (useFloat) { - ati = (floatMode == GLPbuffer.ATI_FLOAT); - } */ - - int[] pformats = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; - int nformats; - int[] nformatsTmp = new int[1]; - if (!wglExt.wglChoosePixelFormatARB(parentHdc, - iattributes, 0, - fattributes, 0, - WindowsWGLGraphicsConfiguration.MAX_PFORMATS, - pformats, 0, - nformatsTmp, 0)) { - throw new GLException("pbuffer creation error: wglChoosePixelFormat() failed"); - } - nformats = nformatsTmp[0]; - if (nformats <= 0) { - throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format"); - } - - if (DEBUG) { - System.err.println("" + nformats + " suitable pixel formats found"); - for (int i = 0; i < nformats; i++) { - WGLGLCapabilities dbgCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, parentHdc, pformats[i], glProfile, false, true); - System.err.println("pixel format " + pformats[i] + " (index " + i + "): " + dbgCaps); - } - } - - int pfdid = 0; - long tmpBuffer = 0; - { - int whichFormat; - // Loop is a workaround for bugs in NVidia's recent drivers - for (whichFormat = 0; whichFormat < nformats; whichFormat++) { - int format = pformats[whichFormat]; - - // Create the p-buffer. - niattribs = 0; - - if (rtt) { - iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FORMAT_ARB; - if (useFloat) { - iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FLOAT_RGB_NV; - } else { - iattributes[niattribs++] = WGLExt.WGL_TEXTURE_RGBA_ARB; + int[] iattributes = new int [2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS]; + float[] fattributes = new float[1]; + int[] floatModeTmp = new int[1]; + int niattribs = 0; + int width, height; + + GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); + GLProfile glProfile = chosenCaps.getGLProfile(); + + if (DEBUG) { + System.out.println("Pbuffer parentHdc = " + toHexString(sharedHdc)); + System.out.println("Pbuffer chosenCaps: " + chosenCaps); + } + + if(!WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(chosenCaps, + iattributes, sharedResource, -1, floatModeTmp)){ + throw new GLException("Pbuffer-related extensions not supported"); + } + + floatMode = floatModeTmp[0]; + boolean rtt = chosenCaps.getPbufferRenderToTexture(); + boolean rect = chosenCaps.getPbufferRenderToTextureRectangle(); + boolean useFloat = chosenCaps.getPbufferFloatingPointBuffers(); + // boolean ati = false; + + /** + if (useFloat) { + ati = (floatMode == GLPbuffer.ATI_FLOAT); + } */ + + int[] pformats = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; + int nformats; + int[] nformatsTmp = new int[1]; + if (!wglExt.wglChoosePixelFormatARB(sharedHdc, + iattributes, 0, + fattributes, 0, + WindowsWGLGraphicsConfiguration.MAX_PFORMATS, + pformats, 0, + nformatsTmp, 0)) { + throw new GLException("pbuffer creation error: wglChoosePixelFormat() failed"); + } + nformats = nformatsTmp[0]; + if (nformats <= 0) { + throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format"); + } + + if (DEBUG) { + System.err.println("" + nformats + " suitable pixel formats found"); + for (int i = 0; i < nformats; i++) { + WGLGLCapabilities dbgCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, sharedHdc, pformats[i], glProfile, false, true); + System.err.println("pixel format " + pformats[i] + " (index " + i + "): " + dbgCaps); + } + } + + int pfdid = 0; + long tmpBuffer = 0; + { + int whichFormat; + // Loop is a workaround for bugs in NVidia's recent drivers + for (whichFormat = 0; whichFormat < nformats; whichFormat++) { + int format = pformats[whichFormat]; + + // Create the p-buffer. + niattribs = 0; + + if (rtt) { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FORMAT_ARB; + if (useFloat) { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FLOAT_RGB_NV; + } else { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_RGBA_ARB; + } + + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_TARGET_ARB; + iattributes[niattribs++] = rect ? WGLExt.WGL_TEXTURE_RECTANGLE_NV : WGLExt.WGL_TEXTURE_2D_ARB; + + iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB; + iattributes[niattribs++] = GL.GL_FALSE; + + iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; + iattributes[niattribs++] = GL.GL_FALSE; + } + + iattributes[niattribs++] = 0; + + tmpBuffer = wglExt.wglCreatePbufferARB(sharedHdc, format, getWidth(), getHeight(), iattributes, 0); + if (tmpBuffer != 0) { + // Done + break; + } } - - iattributes[niattribs++] = WGLExt.WGL_TEXTURE_TARGET_ARB; - iattributes[niattribs++] = rect ? WGLExt.WGL_TEXTURE_RECTANGLE_NV : WGLExt.WGL_TEXTURE_2D_ARB; - - iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB; - iattributes[niattribs++] = GL.GL_FALSE; - - iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; - iattributes[niattribs++] = GL.GL_FALSE; + + if (0 == tmpBuffer) { + throw new GLException("pbuffer creation error: wglCreatePbuffer() failed: tried " + nformats + + " pixel formats, last error was: " + wglGetLastError()); + } + pfdid = pformats[whichFormat]; + } + + // Get the device context. + long tmpHdc = wglExt.wglGetPbufferDCARB(tmpBuffer); + if (tmpHdc == 0) { + throw new GLException("pbuffer creation error: wglGetPbufferDC() failed"); + } + + NativeSurface ns = getNativeSurface(); + // Set up instance variables + buffer = tmpBuffer; + ((SurfaceChangeable)ns).setSurfaceHandle(tmpHdc); + cachedWGLExt = wglExt; + + // Re-query chosen pixel format + { + WGLGLCapabilities newCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, sharedHdc, pfdid, glProfile, false, true); + if(null == newCaps) { + throw new GLException("pbuffer creation error: unable to re-query chosen PFD ID: " + pfdid + ", hdc " + GLDrawableImpl.toHexString(tmpHdc)); } - - iattributes[niattribs++] = 0; - - tmpBuffer = wglExt.wglCreatePbufferARB(parentHdc, format, getWidth(), getHeight(), iattributes, 0); - if (tmpBuffer != 0) { - // Done - break; + if(newCaps.isOnscreen() || !newCaps.isPBuffer()) { + throw new GLException("Error: Selected Onscreen Caps for PBuffer: "+newCaps); } + config.setCapsPFD(newCaps); } - - if (0 == tmpBuffer) { - throw new GLException("pbuffer creation error: wglCreatePbuffer() failed: tried " + nformats + - " pixel formats, last error was: " + wglGetLastError()); - } - pfdid = pformats[whichFormat]; - } - - // Get the device context. - long tmpHdc = wglExt.wglGetPbufferDCARB(tmpBuffer); - if (tmpHdc == 0) { - throw new GLException("pbuffer creation error: wglGetPbufferDC() failed"); - } - - NativeSurface ns = getNativeSurface(); - // Set up instance variables - buffer = tmpBuffer; - ((SurfaceChangeable)ns).setSurfaceHandle(tmpHdc); - cachedWGLExt = wglExt; - - // Re-query chosen pixel format - { - WGLGLCapabilities newCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, parentHdc, pfdid, glProfile, false, true); - if(null == newCaps) { - throw new GLException("pbuffer creation error: unable to re-query chosen PFD ID: " + pfdid + ", hdc " + GLDrawableImpl.toHexString(tmpHdc)); - } - if(newCaps.isOnscreen() || !newCaps.isPBuffer()) { - throw new GLException("Error: Selected Onscreen Caps for PBuffer: "+newCaps); - } - config.setCapsPFD(newCaps); + + // Determine the actual width and height we were able to create. + int[] tmp = new int[1]; + wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_WIDTH_ARB, tmp, 0 ); + width = tmp[0]; + wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 ); + height = tmp[0]; + ((SurfaceChangeable)ns).surfaceSizeChanged(width, height); + } finally { + sharedSurface.unlockSurface(); } - - // Determine the actual width and height we were able to create. - int[] tmp = new int[1]; - wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_WIDTH_ARB, tmp, 0 ); - width = tmp[0]; - wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 ); - height = tmp[0]; - ((SurfaceChangeable)ns).setSize(width, height); } private static String wglGetLastError() { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java index 8f2ec74af..ff59e1518 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java @@ -55,7 +55,6 @@ import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; import jogamp.nativewindow.windows.GDI; import jogamp.opengl.GLContextImpl; -import jogamp.opengl.GLContextShareSet; import jogamp.opengl.GLDrawableImpl; public class WindowsWGLContext extends GLContextImpl { @@ -118,7 +117,7 @@ public class WindowsWGLContext extends GLContextImpl { public final boolean isGLReadDrawableAvailable() { if(!wglGLReadDrawableAvailableSet && null != getWGLExtProcAddressTable()) { WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); - AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration(); AbstractGraphicsDevice device = config.getScreen().getDevice(); switch( factory.isReadDrawableAvailable(device) ) { case 1: @@ -257,20 +256,19 @@ public class WindowsWGLContext extends GLContextImpl { * Creates and initializes an appropriate OpenGL context. Should only be * called by {@link #makeCurrentImpl()}. */ - protected boolean createImpl() { - WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); - AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + protected boolean createImpl(GLContextImpl shareWith) { + AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration(); AbstractGraphicsDevice device = config.getScreen().getDevice(); + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); GLCapabilitiesImmutable glCaps = drawable.getChosenGLCapabilities(); isGLReadDrawableAvailable(); // trigger setup wglGLReadDrawableAvailable // Windows can set up sharing of display lists after creation time - WindowsWGLContext other = (WindowsWGLContext) GLContextShareSet.getShareContext(this); long share = 0; - if (other != null) { - share = other.getHandle(); + if (null != shareWith) { + share = shareWith.getHandle(); if (share == 0) { throw new GLException("GLContextShareSet returned an invalid OpenGL context"); } @@ -298,7 +296,7 @@ public class WindowsWGLContext extends GLContextImpl { if (!WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx)) { throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: "+GDI.GetLastError()); } - setGLFunctionAvailability(true, true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION boolean isCreateContextAttribsARBAvailable = isFunctionAvailable("wglCreateContextAttribsARB"); WGL.wglMakeCurrent(0, 0); // release temp context @@ -334,7 +332,7 @@ public class WindowsWGLContext extends GLContextImpl { if(glCaps.getGLProfile().isGL3()) { WGL.wglMakeCurrent(0, 0); WGL.wglDeleteContext(temp_ctx); - throw new GLException("WindowsWGLContext.createContext failed, but context > GL2 requested "+getGLVersion()+", "); + throw new GLException("WindowsWGLContext.createContext ctx !ARB, context > GL2 requested "+getGLVersion()); } if(DEBUG) { System.err.println("WindowsWGLContext.createContext failed, fall back to !ARB context "+getGLVersion()); @@ -347,29 +345,26 @@ public class WindowsWGLContext extends GLContextImpl { WGL.wglDeleteContext(contextHandle); throw new GLException("Error making old context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError()); } + if(0!=share) { + // Only utilize the classic GDI 'wglShareLists' shared context method + // for traditional non ARB context. + if (!WGL.wglShareLists(share, contextHandle)) { + throw new GLException("wglShareLists(" + toHexString(share) + + ", " + toHexString(contextHandle) + ") failed: werr " + GDI.GetLastError()); + } + } if (DEBUG) { System.err.println(getThreadName() + ": createImpl: OK (old) share "+share); } } - if(0!=share) { - if (!WGL.wglShareLists(share, contextHandle)) { - throw new GLException("wglShareLists(" + toHexString(share) + - ", " + toHexString(contextHandle) + ") failed: werr " + GDI.GetLastError()); - } - } return true; } - protected void makeCurrentImpl(boolean newCreated) throws GLException { + protected void makeCurrentImpl() throws GLException { if (WGL.wglGetCurrentContext() != contextHandle) { if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { throw new GLException("Error making context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError() + ", " + this); - } else { - if (DEBUG && newCreated) { - System.err.println(getThreadName() + ": wglMakeCurrent(hdc " + toHexString(drawable.getHandle()) + - ", contextHandle " + toHexString(contextHandle) + ") succeeded"); - } } } } @@ -394,7 +389,7 @@ public class WindowsWGLContext extends GLContextImpl { } protected final void updateGLXProcAddressTable() { - final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); final String key = "WGL-"+adevice.getUniqueID(); if (DEBUG) { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java index 4ed9a00c3..b96e0cd9b 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java @@ -41,6 +41,7 @@ package jogamp.opengl.windows.wgl; import java.security.AccessController; + import javax.media.nativewindow.NativeSurface; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; @@ -67,30 +68,31 @@ public abstract class WindowsWGLDrawable extends GLDrawableImpl { } NativeSurface ns = getNativeSurface(); - WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration(); config.updateGraphicsConfiguration(getFactory(), ns, null); if (DEBUG) { System.err.println("!!! WindowsWGLDrawable.setRealized(true): "+config); } } - protected void swapBuffersImpl() { - long startTime = 0; + protected final void swapBuffersImpl() { + // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() + final long t0; if (PROFILING) { - startTime = System.currentTimeMillis(); + t0 = System.currentTimeMillis(); + } else { + t0 = 0; } - if (!GDI.SwapBuffers(getHandle()) && (GDI.GetLastError() != GDI.ERROR_SUCCESS)) { + if (!WGLUtil.SwapBuffers(getHandle()) && (GDI.GetLastError() != GDI.ERROR_SUCCESS)) { throw new GLException("Error swapping buffers"); } if (PROFILING) { - long endTime = System.currentTimeMillis(); - profilingSwapBuffersTime += (endTime - startTime); - int ticks = PROFILING_TICKS; - if (++profilingSwapBuffersTicks == ticks) { - System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + ticks + " calls (" + - ((float) profilingSwapBuffersTime / (float) ticks) + " ms/call)"); + profilingSwapBuffersTime += System.currentTimeMillis() - t0; + if (++profilingSwapBuffersTicks == PROFILING_TICKS) { + System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + PROFILING_TICKS + " calls (" + + ((float) profilingSwapBuffersTime / (float) PROFILING_TICKS) + " ms/call)"); profilingSwapBuffersTime = 0; profilingSwapBuffersTicks = 0; } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index cd22127a3..43c16240d 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -42,7 +42,6 @@ package jogamp.opengl.windows.wgl; import java.nio.Buffer; import java.nio.ShortBuffer; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -62,6 +61,7 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import javax.media.opengl.GLProfile.ShutdownType; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.nio.PointerBuffer; @@ -71,6 +71,7 @@ import com.jogamp.common.util.VersionNumber; import jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.windows.GDI; +import jogamp.nativewindow.windows.GDIUtil; import jogamp.nativewindow.windows.GDISurface; import jogamp.nativewindow.windows.RegisteredClassFactory; import jogamp.opengl.DesktopGLDynamicLookupHelper; @@ -80,60 +81,81 @@ import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.SharedResourceRunner; public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { - private static final DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper; + private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null; + + public WindowsWGLDrawableFactory() { + super(); - static { - DesktopGLDynamicLookupHelper tmp = null; - try { - tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); + synchronized(WindowsWGLDrawableFactory.class) { + if(null==windowsWGLDynamicLookupHelper) { + DesktopGLDynamicLookupHelper tmp = null; + try { + tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + windowsWGLDynamicLookupHelper = tmp; + if(null!=windowsWGLDynamicLookupHelper) { + WGL.getWGLProcAddressTable().reset(windowsWGLDynamicLookupHelper); + } } } - windowsWGLDynamicLookupHelper = tmp; + if(null!=windowsWGLDynamicLookupHelper) { - WGL.getWGLProcAddressTable().reset(windowsWGLDynamicLookupHelper); + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + WindowsWGLGraphicsConfigurationFactory.registerFactory(); + if(GLProfile.isAWTAvailable()) { + try { + ReflectionUtil.callStaticMethod("jogamp.opengl.windows.wgl.awt.WindowsAWTWGLGraphicsConfigurationFactory", + "registerFactory", null, null, getClass().getClassLoader()); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + } + + defaultDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + sharedMap = new HashMap<String, SharedResourceRunner.Resource>(); + + // Init shared resources off thread + // Will be released via ShutdownHook + sharedResourceRunner = new SharedResourceRunner(new SharedResourceImplementation()); + sharedResourceRunner.start(); } } - public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) { - return windowsWGLDynamicLookupHelper; - } - - public WindowsWGLDrawableFactory() { - super(); - - // Register our GraphicsConfigurationFactory implementations - // The act of constructing them causes them to be registered - new WindowsWGLGraphicsConfigurationFactory(); - if(GLProfile.isAWTAvailable()) { - try { - ReflectionUtil.createInstance("jogamp.opengl.windows.wgl.awt.WindowsAWTWGLGraphicsConfigurationFactory", - null, getClass().getClassLoader()); - } catch (JogampRuntimeException jre) { /* n/a .. */ } + protected final void destroy(ShutdownType shutdownType) { + if(null != sharedResourceRunner) { + sharedResourceRunner.stop(); + sharedResourceRunner = null; } + if(null != sharedMap) { + sharedMap.clear(); + sharedMap = null; + } + defaultDevice = null; + /** + * Pulling away the native library may cause havoc .. + * + if(ShutdownType.COMPLETE == shutdownType && null != windowsWGLDynamicLookupHelper) { + windowsWGLDynamicLookupHelper.destroy(); + windowsWGLDynamicLookupHelper = null; + } */ + + RegisteredClassFactory.shutdownSharedClasses(); + } - defaultDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); - - // Init shared resources off thread - // Will be released via ShutdownHook - sharedResourceImpl = new SharedResourceImplementation(); - sharedResourceRunner = new SharedResourceRunner(sharedResourceImpl); - sharedResourceThread = new Thread(sharedResourceRunner, Thread.currentThread().getName()+"-SharedResourceRunner"); - sharedResourceThread.setDaemon(true); // Allow JVM to exit, even if this one is running - sharedResourceThread.start(); + public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) { + return windowsWGLDynamicLookupHelper; } - WindowsGraphicsDevice defaultDevice; - SharedResourceImplementation sharedResourceImpl; - SharedResourceRunner sharedResourceRunner; - Thread sharedResourceThread; - HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); + private WindowsGraphicsDevice defaultDevice; + private SharedResourceRunner sharedResourceRunner; + private HashMap<String /*connection*/, SharedResourceRunner.Resource> sharedMap; - long processAffinityChanges = 0; - PointerBuffer procMask = PointerBuffer.allocateDirect(1); - PointerBuffer sysMask = PointerBuffer.allocateDirect(1); + private long processAffinityChanges = 0; + private PointerBuffer procMask = PointerBuffer.allocateDirect(1); + private PointerBuffer sysMask = PointerBuffer.allocateDirect(1); protected void enterThreadCriticalZone() { synchronized (sysMask) { @@ -251,15 +273,15 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } public SharedResourceRunner.Resource mapPut(String connection, SharedResourceRunner.Resource resource) { synchronized(sharedMap) { - return (SharedResourceRunner.Resource) sharedMap.put(connection, resource); + return sharedMap.put(connection, resource); } } public SharedResourceRunner.Resource mapGet(String connection) { synchronized(sharedMap) { - return (SharedResourceRunner.Resource) sharedMap.get(connection); + return sharedMap.get(connection); } } - public Collection/*<Resource>*/ mapValues() { + public Collection<SharedResourceRunner.Resource> mapValues() { synchronized(sharedMap) { return sharedMap.values(); } @@ -270,15 +292,12 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { sharedDevice.lock(); try { AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0); - if (null == absScreen) { - throw new GLException("Couldn't create shared screen for device: "+sharedDevice+", idx 0"); - } GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP); if (null == glp) { throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); } final int f_dim = 64; - long hwnd = GDI.CreateDummyWindow(0, 0, f_dim, f_dim); + long hwnd = GDIUtil.CreateDummyWindow(0, 0, f_dim, f_dim); WindowsDummyWGLDrawable sharedDrawable = WindowsDummyWGLDrawable.create(WindowsWGLDrawableFactory.this, glp, absScreen, hwnd, f_dim, f_dim, true); if (null == sharedDrawable) { throw new GLException("Couldn't create shared drawable for screen: "+absScreen+", "+glp); @@ -373,10 +392,21 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { final static String WGL_ARB_make_current_read = "WGL_ARB_make_current_read"; final static String wglMakeContextCurrent = "wglMakeContextCurrent"; - public final boolean getWasSharedContextCreated(AbstractGraphicsDevice device) { - SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); - if(null!=sr) { - return null != sr.getContext(); + protected final Thread getSharedResourceThread() { + return sharedResourceRunner.start(); + } + + protected final boolean createSharedResource(AbstractGraphicsDevice device) { + try { + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); + if(null!=sr) { + return null != sr.getContext(); + } + } catch (GLException gle) { + if(DEBUG) { + System.err.println("Catched Exception while WindowsWGL Shared Resource initialization"); + gle.printStackTrace(); + } } return false; } @@ -409,11 +439,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { return (SharedResource) sharedResourceRunner.getOrCreateShared(device); } - protected final void shutdownInstance() { - sharedResourceRunner.releaseAndWait(); - RegisteredClassFactory.shutdownSharedClasses(); - } - protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) { return WindowsWGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device); } @@ -429,40 +454,39 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - AbstractGraphicsConfiguration config = target.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsConfiguration config = target.getGraphicsConfiguration(); GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); if(!chosenCaps.isPBuffer()) { return new WindowsBitmapWGLDrawable(this, target); } // PBuffer GLDrawable Creation + GLDrawableImpl pbufferDrawable; final AbstractGraphicsDevice device = config.getScreen().getDevice(); + /** + * Similar to ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277, + * we need to have a context current on the same Display to create a PBuffer. + */ final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); - if(null==sr) { - throw new IllegalArgumentException("No shared resource for "+device); - } - final List returnList = new ArrayList(); - Runnable r = new Runnable() { - public void run() { - GLContext lastContext = GLContext.getCurrent(); - if (lastContext != null) { + if(null!=sr) { + GLContext lastContext = GLContext.getCurrent(); + if (lastContext != null) { lastContext.release(); - } - sr.context.makeCurrent(); - try { - GLDrawableImpl pbufferDrawable = new WindowsPbufferWGLDrawable(WindowsWGLDrawableFactory.this, target, sr); - returnList.add(pbufferDrawable); - } finally { + } + sr.context.makeCurrent(); + try { + pbufferDrawable = new WindowsPbufferWGLDrawable(WindowsWGLDrawableFactory.this, target); + } finally { sr.context.release(); if (lastContext != null) { lastContext.makeCurrent(); } - } } - }; - maybeDoSingleThreadedWorkaround(r); - return (GLDrawableImpl) returnList.get(0); + } else { + pbufferDrawable = new WindowsPbufferWGLDrawable(WindowsWGLDrawableFactory.this, target); + } + return pbufferDrawable; } /** @@ -489,7 +513,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); WrappedSurface ns = new WrappedSurface(WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( capsChosen, capsRequested, chooser, screen) ); - ns.setSize(width, height); + ns.surfaceSizeChanged(width, height); return ns; } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java index 989906514..d6788f1c9 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -37,7 +37,6 @@ import java.util.ArrayList; import java.util.List; import javax.media.nativewindow.AbstractGraphicsScreen; -import javax.media.nativewindow.DefaultGraphicsConfiguration; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.opengl.GL; @@ -48,13 +47,14 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLPbuffer; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.MutableGraphicsConfiguration; import jogamp.nativewindow.windows.DWM_BLURBEHIND; import jogamp.nativewindow.windows.GDI; import jogamp.nativewindow.windows.MARGINS; import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR; import jogamp.opengl.GLGraphicsConfigurationUtil; -public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { +public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { // Keep this under the same debug flag as the drawable factory for convenience protected static final boolean DEBUG = jogamp.opengl.Debug.debug("GraphicsConfiguration"); @@ -149,7 +149,7 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio * @see #isDetermined() */ public final void preselectGraphicsConfiguration(GLDrawableFactory factory, int[] pfdIDs) { - AbstractGraphicsDevice device = getNativeGraphicsConfiguration().getScreen().getDevice(); + AbstractGraphicsDevice device = getScreen().getDevice(); WindowsWGLGraphicsConfigurationFactory.preselectGraphicsConfiguration(chooser, factory, device, this, pfdIDs); } @@ -161,7 +161,7 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio throw new GLException("Error: HDC is null"); } - if (!GDI.SetPixelFormat(hdc, caps.getPFDID(), caps.getPFD())) { + if (!WGLUtil.SetPixelFormat(hdc, caps.getPFDID(), caps.getPFD())) { throw new GLException("Unable to set pixel format " + caps + " for device context " + toHexString(hdc) + ": error code " + GDI.GetLastError()); @@ -610,7 +610,7 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio } PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); - if (GDI.DescribePixelFormat(hdc, pfdID, PIXELFORMATDESCRIPTOR.size(), pfd) == 0) { + if (WGLUtil.DescribePixelFormat(hdc, pfdID, PIXELFORMATDESCRIPTOR.size(), pfd) == 0) { // remove displayable bits, since pfdID is non displayable drawableTypeBits = drawableTypeBits & ~(GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.BITMAP_BIT); if( 0 == drawableTypeBits ) { @@ -629,7 +629,7 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio // static int[] wglAllGDIPFIDs(long hdc) { - int numFormats = GDI.DescribePixelFormat(hdc, 1, 0, null); + int numFormats = WGLUtil.DescribePixelFormat(hdc, 1, 0, null); if (numFormats == 0) { throw new GLException("DescribePixelFormat: No formats - HDC 0x" + Long.toHexString(hdc) + ", LastError: " + GDI.GetLastError()); @@ -733,10 +733,10 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor(long hdc, int pfdID) { PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create(); - pfd.setNSize((short) pfd.size()); + pfd.setNSize((short) PIXELFORMATDESCRIPTOR.size()); pfd.setNVersion((short) 1); if(0 != hdc && 1 <= pfdID) { - if (GDI.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { + if (WGLUtil.DescribePixelFormat(hdc, pfdID, PIXELFORMATDESCRIPTOR.size(), pfd) == 0) { // Accelerated pixel formats that are non displayable if(DEBUG) { System.err.println("Info: Non displayable pixel format " + pfdID + " of device context: error code " + GDI.GetLastError()); diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index a485f8ce8..f02520136 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -67,8 +67,10 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat protected static final boolean DEBUG = jogamp.opengl.Debug.debug("GraphicsConfiguration"); static WGLGLCapabilities.PfdIDComparator PfdIDComparator = new WGLGLCapabilities.PfdIDComparator(); - WindowsWGLGraphicsConfigurationFactory() { - GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, this); + static void registerFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, new WindowsWGLGraphicsConfigurationFactory()); + } + private WindowsWGLGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( @@ -189,7 +191,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat if (0 == hdc) { throw new GLException("Error: HDC is null"); } - WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) ns.getGraphicsConfiguration(); if( !config.isExternal() ) { if( !config.isDetermined() ) { @@ -198,8 +200,8 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat // set PFD if not set yet int pfdID = -1; boolean set = false; - if ( 1 > ( pfdID = GDI.GetPixelFormat(hdc) ) ) { - if (!GDI.SetPixelFormat(hdc, config.getPixelFormatID(), config.getPixelFormat())) { + if ( 1 > ( pfdID = WGLUtil.GetPixelFormat(hdc) ) ) { + if (!WGLUtil.SetPixelFormat(hdc, config.getPixelFormatID(), config.getPixelFormat())) { throw new GLException("Unable to set pixel format " + config.getPixelFormatID() + " for device context " + toHexString(hdc) + ": error code " + GDI.GetLastError()); @@ -236,7 +238,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat } if(NativeSurface.LOCK_SURFACE_NOT_READY >= sharedDrawable.lockSurface()) { - throw new GLException("Surface not ready (lockSurface)"); + throw new GLException("Shared Surface not ready (lockSurface): "+device+" -> "+sharedDrawable); } try { long hdc = sharedDrawable.getHandle(); @@ -309,7 +311,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps boolean pixelFormatSet = false; // indicates a preset PFD ID [caps] - final int presetPFDID = extHDC ? -1 : GDI.GetPixelFormat(hdc) ; + final int presetPFDID = extHDC ? -1 : WGLUtil.GetPixelFormat(hdc) ; if ( 1 <= presetPFDID ) { // Pixelformat already set by either // - a previous preselectGraphicsConfiguration() call on the same HDC, @@ -431,7 +433,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps boolean pixelFormatSet = false; // indicates a preset PFD ID [caps] - if ( !extHDC && 1 <= ( pfdID = GDI.GetPixelFormat(hdc) ) ) { + if ( !extHDC && 1 <= ( pfdID = WGLUtil.GetPixelFormat(hdc) ) ) { // Pixelformat already set by either // - a previous preselectGraphicsConfiguration() call on the same HDC, // - the graphics driver, copying the HDC's pixelformat to the new one, @@ -455,7 +457,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(capsChosen, pfd); - pfdID = GDI.ChoosePixelFormat(hdc, pfd); + pfdID = WGLUtil.ChoosePixelFormat(hdc, pfd); int recommendedIndex = -1 ; if( 1 <= pfdID ) { // seek index .. diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java index 1f09180eb..0f9786f1d 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java @@ -62,8 +62,10 @@ import javax.media.opengl.GLDrawableFactory; public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { protected static final boolean DEBUG = jogamp.opengl.Debug.debug("GraphicsConfiguration"); - public WindowsAWTWGLGraphicsConfigurationFactory() { - GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, this); + public static void registerFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, new WindowsAWTWGLGraphicsConfigurationFactory()); + } + private WindowsAWTWGLGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( @@ -76,7 +78,7 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu } if(null==absScreen) { - absScreen = AWTGraphicsScreen.createScreenDevice(-1, AbstractGraphicsDevice.DEFAULT_UNIT); + absScreen = AWTGraphicsScreen.createDefault(); if(DEBUG) { System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: creating default device: "+absScreen); } @@ -122,12 +124,17 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu // otherwise no hardware accelerated PFD could be achieved. // - preselect with no constrains // - try to create dedicated GC - winConfig.preselectGraphicsConfiguration(drawableFactory, null); - if ( 1 <= winConfig.getPixelFormatID() ) { - chosenGC = Win32SunJDKReflection.graphicsConfigurationGet(device, winConfig.getPixelFormatID()); - if(DEBUG) { - System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: Found new AWT PFD ID "+winConfig.getPixelFormatID()+" -> "+winConfig); + try { + winConfig.preselectGraphicsConfiguration(drawableFactory, null); + if ( 1 <= winConfig.getPixelFormatID() ) { + chosenGC = Win32SunJDKReflection.graphicsConfigurationGet(device, winConfig.getPixelFormatID()); + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: Found new AWT PFD ID "+winConfig.getPixelFormatID()+" -> "+winConfig); + } } + } catch (GLException gle0) { + gle0.printStackTrace(); + // go on .. } if( null == chosenGC ) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/GLXUtil.java b/src/jogl/classes/jogamp/opengl/x11/glx/GLXUtil.java index e95c80205..33e85dd0b 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/GLXUtil.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/GLXUtil.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -32,14 +33,40 @@ package jogamp.opengl.x11.glx; -import javax.media.opengl.*; +import javax.media.nativewindow.x11.X11GraphicsDevice; +import javax.media.opengl.GLException; +import jogamp.opengl.Debug; + +import com.jogamp.common.util.VersionNumber; public class GLXUtil { - public static String getExtension(long display) { - return GLX.glXGetClientString(display, GLX.GLX_EXTENSIONS); - } + public static final boolean DEBUG = Debug.debug("GLXUtil"); + + public static VersionNumber getGLXServerVersionNumber(long display) { + int[] major = new int[1]; + int[] minor = new int[1]; + + if (!GLX.glXQueryVersion(display, major, 0, minor, 0)) { + throw new GLException("glXQueryVersion failed"); + } + // Work around bugs in ATI's Linux drivers where they report they + // only implement GLX version 1.2 on the server side + if (major[0] == 1 && minor[0] == 2) { + String str = GLX.glXGetClientString(display, GLX.GLX_VERSION); + try { + // e.g. "1.3" + major[0] = Integer.valueOf(str.substring(0, 1)).intValue(); + minor[0] = Integer.valueOf(str.substring(2, 3)).intValue(); + } catch (Exception e) { + major[0] = 1; + minor[0] = 2; + } + } + return new VersionNumber(major[0], minor[0], 0); + } + public static boolean isMultisampleAvailable(String extensions) { if (extensions != null) { return (extensions.indexOf("GLX_ARB_multisample") >= 0); @@ -47,16 +74,6 @@ public class GLXUtil { return false; } - public static boolean isMultisampleAvailable(long display) { - return isMultisampleAvailable(getExtension(display)); - } - - /** Workaround for apparent issue with ATI's proprietary drivers - where direct contexts still send GLX tokens for GL calls */ - public static String getVendorName(long display) { - return GLX.glXGetClientString(display, GLX.GLX_VENDOR); - } - public static boolean isVendorNVIDIA(String vendor) { return vendor != null && vendor.startsWith("NVIDIA") ; } @@ -65,38 +82,48 @@ public class GLXUtil { return vendor != null && vendor.startsWith("ATI") ; } - public static boolean isVendorATI(long display) { - return isVendorATI(getVendorName(display)); + public static boolean isClientMultisampleAvailable() { + return clientMultisampleAvailable; } - - public static boolean isVendorNVIDIA(long display) { - return isVendorNVIDIA(getVendorName(display)); + public static String getClientVendorName() { + return clientVendorName; } - - public static void getGLXVersion(long display, int major[], int minor[]) { - if(0 == display) { - throw new GLException("null display handle"); + public static VersionNumber getClientVersionNumber() { + return clientVersionNumber; + } + public static synchronized boolean initGLXClientDataSingleton(X11GraphicsDevice x11Device) { + if(null != clientVendorName) { + return false; } - if(major.length<1||minor.length<1) { - throw new GLException("passed int arrays size is not >= 1"); + if(DEBUG) { + System.err.println("initGLXClientDataSingleton: "+x11Device); + Thread.dumpStack(); } - - if (!GLX.glXQueryVersion(display, major, 0, minor, 0)) { - throw new GLException("glXQueryVersion failed"); + if(null == x11Device) { + throw new GLException("null X11GraphicsDevice"); } - - // Work around bugs in ATI's Linux drivers where they report they - // only implement GLX version 1.2 on the server side - if (major[0] == 1 && minor[0] == 2) { - String str = GLX.glXGetClientString(display, GLX.GLX_VERSION); - try { + if(0 == x11Device.getHandle()) { + throw new GLException("null X11GraphicsDevice display handle"); + } + + clientMultisampleAvailable = isMultisampleAvailable(GLX.glXGetClientString(x11Device.getHandle(), GLX.GLX_EXTENSIONS)); + clientVendorName = GLX.glXGetClientString(x11Device.getHandle(), GLX.GLX_VENDOR); + + int[] major = new int[1]; + int[] minor = new int[1]; + final String str = GLX.glXGetClientString(x11Device.getHandle(), GLX.GLX_VERSION); + try { // e.g. "1.3" major[0] = Integer.valueOf(str.substring(0, 1)).intValue(); minor[0] = Integer.valueOf(str.substring(2, 3)).intValue(); - } catch (Exception e) { + } catch (Exception e) { major[0] = 1; minor[0] = 2; - } } + clientVersionNumber = new VersionNumber(major[0], minor[0], 0); + return true; } + private static boolean clientMultisampleAvailable = false; + private static String clientVendorName = null; + private static VersionNumber clientVersionNumber = null; } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java index 68bdb4ab8..6be74c0e9 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java @@ -50,16 +50,16 @@ public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable { this.realized = true; WrappedSurface ns = (WrappedSurface) getNativeSurface(); - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)ns.getGraphicsConfiguration(); X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice(); long dpy = device.getHandle(); int scrn = screen.getIndex(); long visualID = config.getVisualID(); - dummyWindow = X11Util.CreateDummyWindow(dpy, scrn, visualID, f_dim, f_dim); + dummyWindow = X11Lib.CreateDummyWindow(dpy, scrn, visualID, f_dim, f_dim); ns.setSurfaceHandle( dummyWindow ); - ns.setSize(f_dim, f_dim); + ns.surfaceSizeChanged(f_dim, f_dim); updateHandle(); } @@ -83,8 +83,8 @@ public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable { protected void destroyImpl() { if(0!=dummyWindow) { destroyHandle(); - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - X11Util.DestroyDummyWindow(config.getScreen().getDevice().getHandle(), dummyWindow); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration(); + X11Lib.DestroyDummyWindow(config.getScreen().getDevice().getHandle(), dummyWindow); } } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index d0d9929a0..4a949ea74 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -53,7 +53,7 @@ public class X11ExternalGLXContext extends X11GLXContext { super(drawable, null); this.contextHandle = ctx; GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } @@ -72,7 +72,7 @@ public class X11ExternalGLXContext extends X11GLXContext { } int[] val = new int[1]; GLX.glXQueryContext(display, ctx, GLX.GLX_SCREEN, val, 0); - X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0]); + X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0], false); GLX.glXQueryContext(display, ctx, GLX.GLX_FBCONFIG_ID, val, 0); X11GLXGraphicsConfiguration cfg = null; @@ -95,7 +95,7 @@ public class X11ExternalGLXContext extends X11GLXContext { return new X11ExternalGLXContext(new Drawable(factory, ns), ctx); } - protected boolean createImpl() { + protected boolean createImpl(GLContextImpl shareWith) { return true; } @@ -116,7 +116,7 @@ public class X11ExternalGLXContext extends X11GLXContext { lastContext = null; } - protected void makeCurrentImpl(boolean newCreated) throws GLException { + protected void makeCurrentImpl() throws GLException { } protected void releaseImpl() throws GLException { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java index eb286cdf0..ca30fde3b 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java @@ -66,7 +66,7 @@ public class X11ExternalGLXDrawable extends X11GLXDrawable { } int[] val = new int[1]; GLX.glXQueryContext(display, context, GLX.GLX_SCREEN, val, 0); - X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0]); + X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0], false); GLX.glXQueryContext(display, context, GLX.GLX_FBCONFIG_ID, val, 0); X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]); @@ -85,7 +85,7 @@ public class X11ExternalGLXDrawable extends X11GLXDrawable { } WrappedSurface ns = new WrappedSurface(cfg); ns.setSurfaceHandle(drawable); - ns.setSize(w, h); + ns.surfaceSizeChanged(w, h); return new X11ExternalGLXDrawable(factory, ns); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index 904379058..c86001969 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -40,28 +40,33 @@ package jogamp.opengl.x11.glx; -import java.nio.*; -import java.util.*; - -import javax.media.opengl.*; -import javax.media.nativewindow.*; -import javax.media.nativewindow.x11.X11GraphicsDevice; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.util.HashMap; +import java.util.Map; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.x11.X11Lib; +import jogamp.nativewindow.x11.X11Util; +import jogamp.opengl.GLContextImpl; +import jogamp.opengl.GLDrawableImpl; import com.jogamp.common.nio.Buffers; -import com.jogamp.common.util.VersionNumber; -import jogamp.opengl.*; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; -import jogamp.nativewindow.x11.X11Util; public abstract class X11GLXContext extends GLContextImpl { protected static final boolean TRACE_CONTEXT_CURRENT = false; // true; private static final Map<String, String> functionNameMap; private static final Map<String, String> extensionNameMap; - private VersionNumber glXVersion; - private boolean glXVersionOneOneCapable; - private boolean glXVersionOneThreeCapable; private GLXExt _glXExt; // Table that holds the addresses of the native C-language entry points for // GLX extension functions. @@ -91,9 +96,6 @@ public abstract class X11GLXContext extends GLContextImpl { @Override protected void resetStates() { - glXVersion = null; - glXVersionOneOneCapable = false; - glXVersionOneThreeCapable = false; // no inner state _glXExt=null; glXExtProcAddressTable = null; hasSwapIntervalSGI = 0; @@ -125,25 +127,10 @@ public abstract class X11GLXContext extends GLContextImpl { protected Map<String, String> getExtensionNameMap() { return extensionNameMap; } - private final void initGLXVersion() { - if(null == glXVersion) { - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - X11GraphicsDevice device = (X11GraphicsDevice) config.getScreen().getDevice(); - - glXVersion = X11GLXDrawableFactory.getGLXVersion(device); - glXVersionOneOneCapable = ( null != glXVersion ) ? glXVersion.compareTo(GLDrawableFactoryImpl.versionOneOne) >= 0 : false ; - glXVersionOneThreeCapable = ( null != glXVersion ) ? glXVersion.compareTo(GLDrawableFactoryImpl.versionOneThree) >= 0 : false ; - } - } - public final boolean isGLXVersionGreaterEqualOneOne() { - initGLXVersion(); - return glXVersionOneOneCapable; - } - public final boolean isGLXVersionGreaterEqualOneThree() { - initGLXVersion(); - return glXVersionOneThreeCapable; + protected final boolean isGLXVersionGreaterEqualOneThree() { + return ((X11GLXDrawableFactory)drawable.getFactoryImpl()).isGLXVersionGreaterEqualOneThree(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice()); } - + public final boolean isGLReadDrawableAvailable() { return isGLXVersionGreaterEqualOneThree(); } @@ -154,10 +141,10 @@ public abstract class X11GLXContext extends GLContextImpl { try { if(TRACE_CONTEXT_CURRENT) { Throwable t = new Throwable(Thread.currentThread()+" - glXMakeContextCurrent("+toHexString(dpy)+", "+ - toHexString(writeDrawable)+", "+toHexString(readDrawable)+", "+toHexString(ctx)+") - GLX >= 1.3 "+ glXVersionOneThreeCapable); + toHexString(writeDrawable)+", "+toHexString(readDrawable)+", "+toHexString(ctx)+") - GLX >= 1.3 "+ isGLXVersionGreaterEqualOneThree()); t.printStackTrace(); } - if ( glXVersionOneThreeCapable ) { + if ( isGLXVersionGreaterEqualOneThree() ) { res = GLX.glXMakeContextCurrent(dpy, writeDrawable, readDrawable, ctx); } else if ( writeDrawable == readDrawable ) { res = GLX.glXMakeCurrent(dpy, writeDrawable, ctx); @@ -179,7 +166,7 @@ public abstract class X11GLXContext extends GLContextImpl { } protected void destroyContextARBImpl(long ctx) { - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration(); long display = config.getScreen().getDevice().getHandle(); glXMakeContextCurrent(display, 0, 0, 0); @@ -239,16 +226,16 @@ public abstract class X11GLXContext extends GLContextImpl { attribs.put(ctx_arb_attribs_idx_flags + 1, flags); } - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration(); AbstractGraphicsDevice device = config.getScreen().getDevice(); long display = device.getHandle(); try { // critical path, a remote display might not support this command, // hence we need to catch the X11 Error within this block. - X11Util.XSync(display, false); + X11Lib.XSync(display, false); ctx = _glXExt.glXCreateContextAttribsARB(display, config.getFBConfig(), share, direct, attribs); - X11Util.XSync(display, false); + X11Lib.XSync(display, false); } catch (RuntimeException re) { if(DEBUG) { Throwable t = new Throwable("Info: X11GLXContext.createContextARBImpl glXCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re); @@ -274,32 +261,29 @@ public abstract class X11GLXContext extends GLContextImpl { return ctx; } - protected boolean createImpl() { + protected boolean createImpl(GLContextImpl shareWith) { // covers the whole context creation loop incl createContextARBImpl and destroyContextARBImpl X11Util.setX11ErrorHandler(true, true); try { - return createImplRaw(); + return createImplRaw(shareWith); } finally { X11Util.setX11ErrorHandler(false, false); } } - private boolean createImplRaw() { + private boolean createImplRaw(GLContextImpl shareWith) { boolean direct = true; // try direct always isDirect = false; // fall back X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl(); - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration(); AbstractGraphicsDevice device = config.getScreen().getDevice(); X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContextImpl(device); long display = device.getHandle(); - isGLReadDrawableAvailable(); // trigger setup glXVersionOneThreeCapable - - X11GLXContext other = (X11GLXContext) GLContextShareSet.getShareContext(this); long share = 0; - if (other != null) { - share = other.getHandle(); + if (shareWith != null) { + share = shareWith.getHandle(); if (share == 0) { throw new GLException("GLContextShareSet returned an invalid OpenGL context"); } @@ -321,7 +305,7 @@ public abstract class X11GLXContext extends GLContextImpl { if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { throw new GLException("Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable); } - setGLFunctionAvailability(true, true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION isDirect = GLX.glXIsDirect(display, contextHandle); if (DEBUG) { System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+share+", direct "+isDirect+"/"+direct); @@ -351,7 +335,7 @@ public abstract class X11GLXContext extends GLContextImpl { if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx)) { throw new GLException("Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable); } - setGLFunctionAvailability(true, true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION boolean isCreateContextAttribsARBAvailable = isFunctionAvailable("glXCreateContextAttribsARB"); glXMakeContextCurrent(display, 0, 0, 0); // release temp context @@ -386,7 +370,7 @@ public abstract class X11GLXContext extends GLContextImpl { if(glp.isGL3()) { glXMakeContextCurrent(display, 0, 0, 0); GLX.glXDestroyContext(display, temp_ctx); - throw new GLException("X11GLXContext.createContextImpl failed, but context > GL2 requested - requested: "+glp+", current: "+getGLVersion()+", "); + throw new GLException("X11GLXContext.createContextImpl ctx !ARB, context > GL2 requested - requested: "+glp+", current: "+getGLVersion()+", "); } if(DEBUG) { System.err.println("X11GLXContext.createContextImpl failed, fall back to !ARB context "+getGLVersion()); @@ -410,7 +394,7 @@ public abstract class X11GLXContext extends GLContextImpl { return true; } - protected void makeCurrentImpl(boolean newCreated) throws GLException { + protected void makeCurrentImpl() throws GLException { long dpy = drawable.getNativeSurface().getDisplayHandle(); if (GLX.glXGetCurrentContext() != contextHandle) { @@ -422,13 +406,6 @@ public abstract class X11GLXContext extends GLContextImpl { } finally { X11Util.setX11ErrorHandler(false, false); } - if (DEBUG && newCreated) { - System.err.println(getThreadName() + ": glXMakeCurrent(display " + - toHexString(dpy)+ - ", drawable " + toHexString(drawable.getHandle()) + - ", drawableRead " + toHexString(drawableRead.getHandle()) + - ", context " + toHexString(contextHandle) + ") succeeded"); - } } } @@ -460,7 +437,7 @@ public abstract class X11GLXContext extends GLContextImpl { } protected final void updateGLXProcAddressTable() { - final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); final String key = "GLX-"+adevice.getUniqueID(); if (DEBUG) { @@ -493,10 +470,12 @@ public abstract class X11GLXContext extends GLContextImpl { protected final StringBuffer getPlatformExtensionsStringImpl() { StringBuffer sb = new StringBuffer(); if (DEBUG) { - System.err.println("!!! GLX Version "+glXVersion); + System.err.println("!!! GLX Version client version "+ GLXUtil.getClientVersionNumber()+ + ", server: "+ + ((X11GLXDrawableFactory)drawable.getFactoryImpl()).getGLXVersionNumber(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice())); } - if(isGLXVersionGreaterEqualOneOne()) { - final NativeSurface ns = drawable.getNativeSurface(); + final NativeSurface ns = drawable.getNativeSurface(); + if(((X11GLXDrawableFactory)drawable.getFactoryImpl()).isGLXVersionGreaterEqualOneOne(ns.getGraphicsConfiguration().getScreen().getDevice())) { { final String ret = GLX.glXGetClientString(ns.getDisplayHandle(), GLX.GLX_EXTENSIONS); if (DEBUG) { @@ -526,14 +505,14 @@ public abstract class X11GLXContext extends GLContextImpl { if (glExtensionName.equals("GL_ARB_pbuffer") || glExtensionName.equals("GL_ARB_pixel_format")) { return getGLDrawable().getFactory().canCreateGLPbuffer( - drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice() ); + drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice() ); } return super.isExtensionAvailable(glExtensionName); } @Override protected void setSwapIntervalImpl(int interval) { - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration(); GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); if(!glCaps.isOnscreen()) return; diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java index d2ce629df..28c02cd06 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java @@ -42,6 +42,7 @@ package jogamp.opengl.x11.glx; import javax.media.nativewindow.*; import javax.media.opengl.*; + import jogamp.opengl.*; public abstract class X11GLXDrawable extends GLDrawableImpl { @@ -55,7 +56,7 @@ public abstract class X11GLXDrawable extends GLDrawableImpl { protected void setRealizedImpl() { if(realized) { - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration(); config.updateGraphicsConfiguration(); if (DEBUG) { @@ -64,9 +65,10 @@ public abstract class X11GLXDrawable extends GLDrawableImpl { } } - protected void swapBuffersImpl() { - GLX.glXSwapBuffers(getNativeSurface().getDisplayHandle(), getHandle()); - } + protected final void swapBuffersImpl() { + // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() + GLX.glXSwapBuffers(getNativeSurface().getDisplayHandle(), getHandle()); + } //--------------------------------------------------------------------------- // Internals only below this point diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index 51316dc77..acced638f 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -37,115 +37,156 @@ package jogamp.opengl.x11.glx; +import java.nio.Buffer; +import java.nio.ShortBuffer; import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.nio.*; -import javax.media.nativewindow.*; -import javax.media.nativewindow.x11.*; -import javax.media.opengl.*; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.x11.X11GraphicsDevice; +import javax.media.nativewindow.x11.X11GraphicsScreen; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLProfile.ShutdownType; -import jogamp.opengl.*; - -import com.jogamp.common.JogampRuntimeException; -import com.jogamp.common.util.*; import jogamp.nativewindow.WrappedSurface; -import jogamp.nativewindow.x11.*; +import jogamp.nativewindow.x11.X11Lib; +import jogamp.nativewindow.x11.X11Util; +import jogamp.opengl.DesktopGLDynamicLookupHelper; +import jogamp.opengl.GLContextImpl; +import jogamp.opengl.GLDrawableFactoryImpl; +import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.SharedResourceRunner; + +import com.jogamp.common.util.VersionNumber; public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { - private static final DesktopGLDynamicLookupHelper x11GLXDynamicLookupHelper; + public static final VersionNumber versionOneZero = new VersionNumber(1, 0, 0); + public static final VersionNumber versionOneOne = new VersionNumber(1, 1, 0); + public static final VersionNumber versionOneTwo = new VersionNumber(1, 2, 0); + public static final VersionNumber versionOneThree = new VersionNumber(1, 3, 0); + public static final VersionNumber versionOneFour = new VersionNumber(1, 4, 0); - static { - DesktopGLDynamicLookupHelper tmp = null; - try { - tmp = new DesktopGLDynamicLookupHelper(new X11GLXDynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); + private static DesktopGLDynamicLookupHelper x11GLXDynamicLookupHelper = null; + + public X11GLXDrawableFactory() { + super(); + + synchronized(X11GLXDrawableFactory.class) { + if(null==x11GLXDynamicLookupHelper) { + DesktopGLDynamicLookupHelper tmp = null; + try { + tmp = new DesktopGLDynamicLookupHelper(new X11GLXDynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + x11GLXDynamicLookupHelper = tmp; + if(null!=x11GLXDynamicLookupHelper) { + GLX.getGLXProcAddressTable().reset(x11GLXDynamicLookupHelper); + } } } - x11GLXDynamicLookupHelper = tmp; - if(null!=x11GLXDynamicLookupHelper) { - GLX.getGLXProcAddressTable().reset(x11GLXDynamicLookupHelper); + + if(null!=x11GLXDynamicLookupHelper) { + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + X11GLXGraphicsConfigurationFactory.registerFactory(); + + defaultDevice = new X11GraphicsDevice(X11Util.getNullDisplayName(), AbstractGraphicsDevice.DEFAULT_UNIT); + sharedMap = new HashMap<String, SharedResourceRunner.Resource>(); + + // Init shared resources off thread + // Will be released via ShutdownHook + sharedResourceRunner = new SharedResourceRunner(new SharedResourceImplementation()); + sharedResourceRunner.start(); + } + } + + protected final void destroy(ShutdownType shutdownType) { + if(null != sharedResourceRunner) { + sharedResourceRunner.stop(); + sharedResourceRunner = null; } - } + if(null != sharedMap) { + sharedMap.clear(); + sharedMap = null; + } + defaultDevice = null; + /** + * Pulling away the native library may cause havoc .. + * + if(ShutdownType.COMPLETE == shutdownType && null != x11GLXDynamicLookupHelper) { + x11GLXDynamicLookupHelper.destroy(); + x11GLXDynamicLookupHelper = null; + } */ - public static VersionNumber getGLXVersion(X11GraphicsDevice device) { - int[] major = new int[1]; - int[] minor = new int[1]; - GLXUtil.getGLXVersion(device.getHandle(), major, minor); - return new VersionNumber(major[0], minor[0], 0); + // Don't really close pending Display connections, + // since this may trigger a JVM exception + X11Util.shutdown( false, DEBUG ); } public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) { return x11GLXDynamicLookupHelper; } - public X11GLXDrawableFactory() { - super(); - // Register our GraphicsConfigurationFactory implementations - // The act of constructing them causes them to be registered - new X11GLXGraphicsConfigurationFactory(); - if(GLProfile.isAWTAvailable()) { - try { - ReflectionUtil.createInstance("jogamp.opengl.x11.glx.awt.X11AWTGLXGraphicsConfigurationFactory", - null, getClass().getClassLoader()); - } catch (JogampRuntimeException jre) { /* n/a .. */ } - } - - defaultDevice = new X11GraphicsDevice(X11Util.getNullDisplayName(), AbstractGraphicsDevice.DEFAULT_UNIT); - - // Init shared resources off thread - // Will be released via ShutdownHook - sharedResourceImpl = new SharedResourceImplementation(); - sharedResourceRunner = new SharedResourceRunner(sharedResourceImpl); - sharedResourceThread = new Thread(sharedResourceRunner, Thread.currentThread().getName()+"-SharedResourceRunner"); - sharedResourceThread.setDaemon(true); // Allow JVM to exit, even if this one is running - sharedResourceThread.start(); - } - - X11GraphicsDevice defaultDevice; - SharedResourceImplementation sharedResourceImpl; - SharedResourceRunner sharedResourceRunner; - Thread sharedResourceThread; - HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); + private X11GraphicsDevice defaultDevice; + private SharedResourceRunner sharedResourceRunner; + private HashMap<String /* connection */, SharedResourceRunner.Resource> sharedMap; static class SharedResource implements SharedResourceRunner.Resource { X11GraphicsDevice device; X11GraphicsScreen screen; X11DummyGLXDrawable drawable; X11GLXContext context; - String glXVendorName; - boolean isGLXVendorATI; - boolean isGLXVendorNVIDIA; - VersionNumber glXVersion; + String glXServerVendorName; + boolean isGLXServerVendorATI; + boolean isGLXServerVendorNVIDIA; + VersionNumber glXServerVersion; + boolean glXServerVersionOneOneCapable; + boolean glXServerVersionOneThreeCapable; + boolean glXMultisampleAvailable; SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn, X11DummyGLXDrawable draw, X11GLXContext ctx, - VersionNumber glXVer, String glXVendor) { + VersionNumber glXServerVer, String glXServerVendor, boolean glXServerMultisampleAvail) { device = dev; screen = scrn; drawable = draw; context = ctx; - glXVersion = glXVer; - glXVendorName = glXVendor; - isGLXVendorATI = GLXUtil.isVendorATI(glXVendorName); - isGLXVendorNVIDIA = GLXUtil.isVendorNVIDIA(glXVendorName); + glXServerVersion = glXServerVer; + glXServerVersionOneOneCapable = glXServerVersion.compareTo(versionOneOne) >= 0 ; + glXServerVersionOneThreeCapable = glXServerVersion.compareTo(versionOneThree) >= 0 ; + glXServerVendorName = glXServerVendor; + isGLXServerVendorATI = GLXUtil.isVendorATI(glXServerVendorName); + isGLXServerVendorNVIDIA = GLXUtil.isVendorNVIDIA(glXServerVendorName); + glXMultisampleAvailable = glXServerMultisampleAvail; } final public AbstractGraphicsDevice getDevice() { return device; } final public AbstractGraphicsScreen getScreen() { return screen; } final public GLDrawableImpl getDrawable() { return drawable; } final public GLContextImpl getContext() { return context; } - final String getGLXVendorName() { return glXVendorName; } - final boolean isGLXVendorATI() { return isGLXVendorATI; } - final boolean isGLXVendorNVIDIA() { return isGLXVendorNVIDIA; } - final VersionNumber getGLXVersion() { return glXVersion; } - final boolean isGLXVersionGreaterEqualOneThree() { - return ( null != glXVersion ) ? glXVersion.compareTo(versionOneThree) >= 0 : false ; - } + final String getGLXVendorName() { return glXServerVendorName; } + final boolean isGLXVendorATI() { return isGLXServerVendorATI; } + final boolean isGLXVendorNVIDIA() { return isGLXServerVendorNVIDIA; } + final VersionNumber getGLXVersion() { return glXServerVersion; } + final boolean isGLXVersionGreaterEqualOneOne() { return glXServerVersionOneOneCapable; } + final boolean isGLXVersionGreaterEqualOneThree() { return glXServerVersionOneThreeCapable; } + final boolean isGLXMultisampleAvailable() { return glXMultisampleAvailable; } } class SharedResourceImplementation implements SharedResourceRunner.Implementation { @@ -156,27 +197,33 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } public SharedResourceRunner.Resource mapPut(String connection, SharedResourceRunner.Resource resource) { synchronized(sharedMap) { - return (SharedResourceRunner.Resource) sharedMap.put(connection, resource); + return sharedMap.put(connection, resource); } } public SharedResourceRunner.Resource mapGet(String connection) { synchronized(sharedMap) { - return (SharedResourceRunner.Resource) sharedMap.get(connection); + return sharedMap.get(connection); } } - public Collection/*<Resource>*/ mapValues() { + public Collection<SharedResourceRunner.Resource> mapValues() { synchronized(sharedMap) { return sharedMap.values(); } } public SharedResourceRunner.Resource createSharedResource(String connection) { - X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT); - sharedDevice.setCloseDisplay(true); + X11GraphicsDevice sharedDevice = + new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, + true); // own non-shared display connection, no locking + // new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, + // NativeWindowFactory.getNullToolkitLock(), true); // own non-shared display connection, no locking sharedDevice.lock(); try { - String glXVendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); - if(X11Util.ATI_HAS_XCLOSEDISPLAY_BUG && GLXUtil.isVendorATI(glXVendorName)) { + GLXUtil.initGLXClientDataSingleton(sharedDevice); + final String glXServerVendorName = GLX.glXQueryServerString(sharedDevice.getHandle(), 0, GLX.GLX_VENDOR); + final VersionNumber glXServerVersion = GLXUtil.getGLXServerVersionNumber(sharedDevice.getHandle()); + final boolean glXServerMultisampleAvailable = GLXUtil.isMultisampleAvailable(GLX.glXQueryServerString(sharedDevice.getHandle(), 0, GLX.GLX_EXTENSIONS)); + if(X11Util.ATI_HAS_XCLOSEDISPLAY_BUG && GLXUtil.isVendorATI(glXServerVendorName)) { X11Util.setMarkAllDisplaysUnclosable(true); X11Util.markDisplayUncloseable(sharedDevice.getHandle()); } @@ -195,7 +242,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable); } sharedContext.setSynchronized(true); - VersionNumber glXVersion = getGLXVersion(sharedDevice); boolean madeCurrent = false; sharedContext.makeCurrent(); try { @@ -207,11 +253,16 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { System.err.println("!!! SharedDevice: " + sharedDevice); System.err.println("!!! SharedScreen: " + sharedScreen); System.err.println("!!! SharedContext: " + sharedContext + ", madeCurrent " + madeCurrent); - System.err.println("!!! GLX Vendor: " + glXVendorName); - System.err.println("!!! GLX Version: " + glXVersion - + " >= 1.3: " + (glXVersion.compareTo(versionOneThree) >= 0)); + System.err.println("!!! GLX Server Vendor: " + glXServerVendorName); + System.err.println("!!! GLX Server Version: " + glXServerVersion); + System.err.println("!!! GLX Server Multisample: " + glXServerMultisampleAvailable); + System.err.println("!!! GLX Client Vendor: " + GLXUtil.getClientVendorName()); + System.err.println("!!! GLX Client Version: " + GLXUtil.getClientVersionNumber()); + System.err.println("!!! GLX Client Multisample: " + GLXUtil.isClientMultisampleAvailable()); } - return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext, glXVersion, glXVendorName); + return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext, + glXServerVersion, glXServerVendorName, + glXServerMultisampleAvailable && GLXUtil.isClientMultisampleAvailable()); } catch (Throwable t) { throw new GLException("X11GLXDrawableFactory - Could not initialize shared resources for "+connection, t); } finally { @@ -227,15 +278,18 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { System.err.println("!!! Screen : " + sr.screen); System.err.println("!!! Drawable: " + sr.drawable); System.err.println("!!! CTX : " + sr.context); + Thread.dumpStack(); } if (null != sr.context) { - // may cause JVM SIGSEGV: sharedContext.destroy(); + // may cause JVM SIGSEGV: + sr.context.destroy(); sr.context = null; } if (null != sr.drawable) { - // may cause JVM SIGSEGV: sharedDrawable.destroy(); + // may cause JVM SIGSEGV: + sr.drawable.destroy(); sr.drawable = null; } @@ -244,6 +298,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } if (null != sr.device) { + // may cause JVM SIGSEGV: sr.device.close(); sr.device = null; } @@ -261,10 +316,21 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return false; } - public final boolean getWasSharedContextCreated(AbstractGraphicsDevice device) { - SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); - if(null!=sr) { - return null != sr.getContext(); + protected final Thread getSharedResourceThread() { + return sharedResourceRunner.start(); + } + + protected final boolean createSharedResource(AbstractGraphicsDevice device) { + try { + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); + if(null!=sr) { + return null != sr.getContext(); + } + } catch (GLException gle) { + if(DEBUG) { + System.err.println("Catched Exception while X11GLX Shared Resource initialization"); + gle.printStackTrace(); + } } return false; } @@ -297,47 +363,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return (SharedResource) sharedResourceRunner.getOrCreateShared(device); } - public final String getGLXVendorName(AbstractGraphicsDevice device) { - if(null != device) { - SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); - if(null!=sr) { - return ((SharedResource)sr).getGLXVendorName(); - } - return GLXUtil.getVendorName(device.getHandle()); - } - return null; - } - - public final boolean isGLXVendorATI(AbstractGraphicsDevice device) { - if(null != device) { - SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); - if(null!=sr) { - return ((SharedResource)sr).isGLXVendorATI(); - } - return GLXUtil.isVendorATI(device.getHandle()); - } - return false; - } - - public final boolean isGLXVendorNVIDIA(AbstractGraphicsDevice device) { - if(null != device) { - SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); - if(null!=sr) { - return ((SharedResource)sr).isGLXVendorNVIDIA(); - } - return GLXUtil.isVendorNVIDIA(device.getHandle()); - } - return false; - } - - protected final void shutdownInstance() { - sharedResourceRunner.releaseAndWait(); - - // Don't really close pending Display connections, - // since this may trigger a JVM exception - X11Util.shutdown( false, DEBUG ); - } - protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) { return X11GLXGraphicsConfigurationFactory.getAvailableCapabilities(this, device); } @@ -353,7 +378,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - AbstractGraphicsConfiguration config = target.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsConfiguration config = target.getGraphicsConfiguration(); GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); if(!caps.isPBuffer()) { return new X11PixmapGLXDrawable(this, target); @@ -383,6 +408,43 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return pbufferDrawable; } + public final boolean isGLXMultisampleAvailable(AbstractGraphicsDevice device) { + if(null != device) { + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); + if(null!=sr) { + return sr.isGLXMultisampleAvailable(); + } + } + return false; + } + + public final VersionNumber getGLXVersionNumber(AbstractGraphicsDevice device) { + if(null != device) { + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); + if(null!=sr) { + return sr.getGLXVersion(); + } + if( device instanceof X11GraphicsDevice ) { + return GLXUtil.getGLXServerVersionNumber(device.getHandle()); + } + } + return null; + } + + public final boolean isGLXVersionGreaterEqualOneOne(AbstractGraphicsDevice device) { + if(null != device) { + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); + if(null!=sr) { + return sr.isGLXVersionGreaterEqualOneOne(); + } + if( device instanceof X11GraphicsDevice ) { + final VersionNumber glXServerVersion = GLXUtil.getGLXServerVersionNumber(device.getHandle()); + return glXServerVersion.compareTo(versionOneOne) >= 0; + } + } + return false; + } + public final boolean isGLXVersionGreaterEqualOneThree(AbstractGraphicsDevice device) { if(null != device) { SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); @@ -390,8 +452,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return sr.isGLXVersionGreaterEqualOneThree(); } if( device instanceof X11GraphicsDevice ) { - VersionNumber v = getGLXVersion( (X11GraphicsDevice) device); - return ( null != v ) ? v.compareTo(versionOneThree) >= 0 : false ; + final VersionNumber glXServerVersion = GLXUtil.getGLXServerVersionNumber(device.getHandle()); + return glXServerVersion.compareTo(versionOneThree) >= 0; } } return false; @@ -407,23 +469,28 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return isGLXVersionGreaterEqualOneThree(device); } - protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, + protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { - X11GraphicsScreen screen = null; - SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); - if(null!=sr) { - screen = (X11GraphicsScreen) sr.getScreen(); + if(null == deviceReq) { + throw new InternalError("deviceReq is null"); } - if(null==screen) { - return null; + final SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(deviceReq); + if(null==sr) { + throw new InternalError("No SharedResource for: "+deviceReq); } + final X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sr.getScreen(); + final AbstractGraphicsDevice sharedDevice = sharedScreen.getDevice(); // should be same .. + // create screen/device pair - Null X11 locking, due to private non-shared Display handle + final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(sharedDevice.getConnection()), AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock(), true); + final X11GraphicsScreen screen = new X11GraphicsScreen(device, sharedScreen.getIndex()); + WrappedSurface ns = new WrappedSurface( X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen) ); if(ns != null) { - ns.setSize(width, height); + ns.surfaceSizeChanged(width, height); } return ns; } @@ -475,8 +542,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } int[] size = new int[1]; - boolean res = X11Util.XF86VidModeGetGammaRampSize(display, - X11Util.DefaultScreen(display), + boolean res = X11Lib.XF86VidModeGetGammaRampSize(display, + X11Lib.DefaultScreen(display), size, 0); if (!res) { return 0; @@ -498,8 +565,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { rampData[i] = (short) (ramp[i] * 65535); } - boolean res = X11Util.XF86VidModeSetGammaRamp(display, - X11Util.DefaultScreen(display), + boolean res = X11Lib.XF86VidModeSetGammaRamp(display, + X11Lib.DefaultScreen(display), rampData.length, rampData, 0, rampData, 0, @@ -525,8 +592,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { rampData.limit(3 * size); ShortBuffer blueRampData = rampData.slice(); - boolean res = X11Util.XF86VidModeGetGammaRamp(display, - X11Util.DefaultScreen(display), + boolean res = X11Lib.XF86VidModeGetGammaRamp(display, + X11Lib.DefaultScreen(display), size, redRampData, greenRampData, @@ -562,8 +629,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { rampData.limit(3 * size); ShortBuffer blueRampData = rampData.slice(); - X11Util.XF86VidModeSetGammaRamp(display, - X11Util.DefaultScreen(display), + X11Lib.XF86VidModeSetGammaRamp(display, + X11Lib.DefaultScreen(display), size, redRampData, greenRampData, diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java index 68b8135d0..4d0c3eeca 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java @@ -35,13 +35,26 @@ package jogamp.opengl.x11.glx; import java.util.ArrayList; -import javax.media.nativewindow.*; -import javax.media.nativewindow.x11.*; -import javax.media.opengl.*; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.x11.X11GraphicsConfiguration; +import javax.media.nativewindow.x11.X11GraphicsScreen; +import javax.media.opengl.DefaultGLCapabilitiesChooser; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.x11.X11Lib; +import jogamp.nativewindow.x11.XRenderDirectFormat; +import jogamp.nativewindow.x11.XRenderPictFormat; +import jogamp.nativewindow.x11.XVisualInfo; +import jogamp.opengl.Debug; +import jogamp.opengl.GLGraphicsConfigurationUtil; import com.jogamp.common.nio.PointerBuffer; -import jogamp.opengl.*; -import jogamp.nativewindow.x11.*; public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implements Cloneable { protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); @@ -56,19 +69,20 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } static X11GLXGraphicsConfiguration create(GLProfile glp, X11GraphicsScreen x11Screen, int fbcfgID) { - long display = x11Screen.getDevice().getHandle(); + final long display = x11Screen.getDevice().getHandle(); if(0==display) { throw new GLException("Display null of "+x11Screen); } - int screen = x11Screen.getIndex(); - long fbcfg = glXFBConfigID2FBConfig(display, screen, fbcfgID); + final int screen = x11Screen.getIndex(); + final long fbcfg = glXFBConfigID2FBConfig(display, screen, fbcfgID); if(0==fbcfg) { throw new GLException("FBConfig null of "+toHexString(fbcfgID)); } if(null==glp) { glp = GLProfile.getDefault(x11Screen.getDevice()); } - X11GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, GLXUtil.isMultisampleAvailable(display)); + final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory(); + final X11GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(x11Screen.getDevice())); if(null==caps) { throw new GLException("GLCapabilities null of "+toHexString(fbcfg)); } @@ -100,10 +114,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } } - private static int nonZeroOrDontCare(int value) { - return value != 0 ? value : (int)GLX.GLX_DONT_CARE ; - } - static int[] GLCapabilities2AttribList(GLCapabilitiesImmutable caps, boolean forFBAttr, boolean isMultisampleAvailable, @@ -367,7 +377,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem int[] count = new int[1]; XVisualInfo template = XVisualInfo.create(); template.setVisualid(visualID); - XVisualInfo[] infos = X11Util.XGetVisualInfo(display, X11Lib.VisualIDMask, template, count, 0); + XVisualInfo[] infos = X11Lib.XGetVisualInfo(display, X11Lib.VisualIDMask, template, count, 0); if (infos == null || infos.length == 0) { return null; } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java index 0f8b94825..a72de8cd5 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -51,7 +51,6 @@ import javax.media.opengl.GLProfile; import com.jogamp.common.nio.PointerBuffer; import jogamp.nativewindow.x11.X11Lib; -import jogamp.nativewindow.x11.X11Util; import jogamp.nativewindow.x11.XVisualInfo; import jogamp.opengl.Debug; import jogamp.opengl.GLGraphicsConfigurationFactory; @@ -71,8 +70,10 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); static X11GLCapabilities.XVisualIDComparator XVisualIDComparator = new X11GLCapabilities.XVisualIDComparator(); - X11GLXGraphicsConfigurationFactory() { - GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.x11.X11GraphicsDevice.class, this); + static void registerFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.x11.X11GraphicsDevice.class, new X11GLXGraphicsConfigurationFactory()); + } + private X11GLXGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( @@ -101,18 +102,19 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF if(null == sharedResource) { throw new GLException("Shared resource for device n/a: "+device); } - X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sharedResource.getScreen(); - X11GLXDrawable sharedDrawable = (X11GLXDrawable) sharedResource.getDrawable(); - GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities(); - GLProfile glp = capsChosen.getGLProfile(); + final X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sharedResource.getScreen(); + final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(sharedScreen.getDevice()); + final X11GLXDrawable sharedDrawable = (X11GLXDrawable) sharedResource.getDrawable(); + final GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities(); + final GLProfile glp = capsChosen.getGLProfile(); List<GLCapabilitiesImmutable> availableCaps = null; if( sharedResource.isGLXVersionGreaterEqualOneThree() ) { - availableCaps = getAvailableGLCapabilitiesFBConfig(sharedScreen, glp); + availableCaps = getAvailableGLCapabilitiesFBConfig(sharedScreen, glp, isMultisampleAvailable); } if( null == availableCaps || availableCaps.isEmpty() ) { - availableCaps = getAvailableGLCapabilitiesXVisual(sharedScreen, glp); + availableCaps = getAvailableGLCapabilitiesXVisual(sharedScreen, glp, isMultisampleAvailable); } if( null != availableCaps && availableCaps.size() > 1 ) { Collections.sort(availableCaps, XVisualIDComparator); @@ -120,7 +122,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF return availableCaps; } - static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesFBConfig(X11GraphicsScreen x11Screen, GLProfile glProfile) { + static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesFBConfig(X11GraphicsScreen x11Screen, GLProfile glProfile, boolean isMultisampleAvailable) { PointerBuffer fbcfgsL = null; // Utilizing FBConfig @@ -129,7 +131,6 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF long display = absDevice.getHandle(); int screen = x11Screen.getIndex(); - boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); int[] count = { -1 }; ArrayList<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>(); @@ -150,17 +151,16 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF return availableCaps; } - static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesXVisual(X11GraphicsScreen x11Screen, GLProfile glProfile) { + static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesXVisual(X11GraphicsScreen x11Screen, GLProfile glProfile, boolean isMultisampleAvailable) { AbstractGraphicsDevice absDevice = x11Screen.getDevice(); long display = absDevice.getHandle(); int screen = x11Screen.getIndex(); - boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); int[] count = new int[1]; XVisualInfo template = XVisualInfo.create(); template.setScreen(screen); - XVisualInfo[] infos = X11Util.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0); + XVisualInfo[] infos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0); if (infos == null || infos.length<1) { throw new GLException("Error while enumerating available XVisualInfos"); } @@ -213,18 +213,20 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF } static X11GLXGraphicsConfiguration fetchGraphicsConfigurationFBConfig(X11GraphicsScreen x11Screen, int fbID, GLProfile glp) { - AbstractGraphicsDevice absDevice = x11Screen.getDevice(); - long display = absDevice.getHandle(); - int screen = x11Screen.getIndex(); + final AbstractGraphicsDevice absDevice = x11Screen.getDevice(); + final long display = absDevice.getHandle(); + final int screen = x11Screen.getIndex(); - long fbcfg = X11GLXGraphicsConfiguration.glXFBConfigID2FBConfig(display, screen, fbID); + final long fbcfg = X11GLXGraphicsConfiguration.glXFBConfigID2FBConfig(display, screen, fbID); if( 0 == fbcfg || !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfg ) ) { if(DEBUG) { System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed - GLX FBConfig invalid: ("+x11Screen+","+toHexString(fbID)+"): fbcfg: "+toHexString(fbcfg)); } return null; } - X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, GLXUtil.isMultisampleAvailable(display)); + final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory(); + + final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(absDevice)); return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser()); } @@ -242,9 +244,10 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF // AbstractGraphicsDevice absDevice = x11Screen.getDevice(); long display = absDevice.getHandle(); - int screen = x11Screen.getIndex(); - boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + + final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory(); + final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(absDevice); int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, true, isMultisampleAvailable, display, screen); int[] count = { -1 }; ArrayList/*<X11GLCapabilities>*/ availableCaps = new ArrayList(); @@ -321,9 +324,10 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF AbstractGraphicsDevice absDevice = x11Screen.getDevice(); long display = absDevice.getHandle(); - int screen = x11Screen.getIndex(); - boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + + final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory(); + final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(absDevice); int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, false, isMultisampleAvailable, display, screen); // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice @@ -341,7 +345,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF int[] count = new int[1]; XVisualInfo template = XVisualInfo.create(); template.setScreen(screen); - XVisualInfo[] infos = X11Util.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0); + XVisualInfo[] infos = X11Lib.XGetVisualInfo(display, X11Lib.VisualScreenMask, template, count, 0); if (infos == null || infos.length<1) { throw new GLException("Error while enumerating available XVisualInfos"); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java index 8ef642322..333486a5f 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java @@ -56,14 +56,16 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable { } @SuppressWarnings("unused") + @Override public long getHandle() { if(USE_GLXWINDOW && useGLXWindow) { return glXWindow; } - return getNativeSurface().getSurfaceHandle(); + return super.getHandle(); } @SuppressWarnings("unused") + @Override protected void destroyHandle() { if(USE_GLXWINDOW && 0!=glXWindow) { GLX.glXDestroyWindow(getNativeSurface().getDisplayHandle(), glXWindow); @@ -72,10 +74,10 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable { } } - /** must be locked already */ + @Override protected void updateHandle() { if(USE_GLXWINDOW) { - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration(); if(config.getFBConfig()>=0) { useGLXWindow=true; long dpy = getNativeSurface().getDisplayHandle(); diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java index 8ea989267..da7b535cb 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java @@ -48,24 +48,18 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { /* GLCapabilities caps, GLCapabilitiesChooser chooser, int width, int height */ - super(factory, target, true); - - if (DEBUG) { - System.out.println("Pbuffer config: " + getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration()); - } - - createPbuffer(); - - if (DEBUG) { - System.err.println("Created pbuffer " + this); - } + super(factory, target, false); } + protected void destroyImpl() { + setRealized(false); + } + protected void setRealizedImpl() { if(realized) { createPbuffer(); } else { - destroyImpl(); + destroyPbuffer(); } } @@ -73,7 +67,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { return new X11PbufferGLXContext(this, shareWith); } - protected void destroyImpl() { + protected void destroyPbuffer() { NativeSurface ns = getNativeSurface(); if (ns.getSurfaceHandle() != 0) { GLX.glXDestroyPbuffer(ns.getDisplayHandle(), ns.getSurfaceHandle()); @@ -82,11 +76,14 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { } private void createPbuffer() { - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration(); AbstractGraphicsScreen aScreen = config.getScreen(); AbstractGraphicsDevice aDevice = aScreen.getDevice(); long display = aDevice.getHandle(); - int screen = aScreen.getIndex(); + + if (DEBUG) { + System.out.println("Pbuffer config: " + config); + } if (display==0) { throw new GLException("Null display"); @@ -129,17 +126,15 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { int width = tmp[0]; GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_HEIGHT, tmp, 0); int height = tmp[0]; - ((SurfaceChangeable)ns).setSize(width, height); + ((SurfaceChangeable)ns).surfaceSizeChanged(width, height); + + if (DEBUG) { + System.err.println("Created pbuffer " + this); + } } public int getFloatingPointMode() { // Floating-point pbuffers currently require NVidia hardware on X11 return GLPbuffer.NV_FLOAT; } - - protected void swapBuffersImpl() { - if(DEBUG) { - System.err.println("unhandled swapBuffersImpl() called for: "+this); - } - } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java index ef8007de4..e19dfd1b3 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java @@ -55,7 +55,7 @@ public class X11PixmapGLXContext extends X11GLXContext { } public int getOffscreenContextReadBuffer() { - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities(); if (caps.getDoubleBuffered()) { return GL.GL_BACK; } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java index f5d321561..7dae20f80 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java @@ -48,15 +48,18 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable { private long pixmap; protected X11PixmapGLXDrawable(GLDrawableFactory factory, NativeSurface target) { - super(factory, target, true); - create(); + super(factory, target, false); } + protected void destroyImpl() { + setRealized(false); + } + protected void setRealizedImpl() { if(realized) { - create(); + createPixmap(); } else { - destroyImpl(); + destroyPixmap(); } } @@ -64,9 +67,9 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable { return new X11PixmapGLXContext(this, shareWith); } - private void create() { + private void createPixmap() { NativeSurface ns = getNativeSurface(); - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) ns.getGraphicsConfiguration(); XVisualInfo vis = config.getXVisualInfo(); int bitsPerPixel = vis.getDepth(); AbstractGraphicsScreen aScreen = config.getScreen(); @@ -74,14 +77,14 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable { long dpy = aDevice.getHandle(); int screen = aScreen.getIndex(); - pixmap = X11Util.XCreatePixmap(dpy, X11Util.RootWindow(dpy, screen), + pixmap = X11Lib.XCreatePixmap(dpy, X11Lib.RootWindow(dpy, screen), surface.getWidth(), surface.getHeight(), bitsPerPixel); if (pixmap == 0) { throw new GLException("XCreatePixmap failed"); } long drawable = GLX.glXCreateGLXPixmap(dpy, vis, pixmap); if (drawable == 0) { - X11Util.XFreePixmap(dpy, pixmap); + X11Lib.XFreePixmap(dpy, pixmap); pixmap = 0; throw new GLException("glXCreateGLXPixmap failed"); } @@ -93,7 +96,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable { } } - protected void destroyImpl() { + protected void destroyPixmap() { if (pixmap == 0) return; NativeSurface ns = getNativeSurface(); @@ -122,16 +125,10 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable { GLX.glXMakeCurrent(display, 0, 0); GLX.glXDestroyGLXPixmap(display, drawable); - X11Util.XFreePixmap(display, pixmap); + X11Lib.XFreePixmap(display, pixmap); drawable = 0; pixmap = 0; ((SurfaceChangeable)ns).setSurfaceHandle(0); display = 0; } - - protected void swapBuffersImpl() { - if(DEBUG) { - System.err.println("unhandled swapBuffersImpl() called for: "+this); - } - } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java deleted file mode 100644 index 9ee20d8ea..000000000 --- a/src/jogl/classes/jogamp/opengl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -package jogamp.opengl.x11.glx.awt; - -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import javax.media.nativewindow.*; -import javax.media.nativewindow.x11.*; -import javax.media.nativewindow.awt.*; -import javax.media.opengl.*; - -import jogamp.opengl.*; -import jogamp.nativewindow.jawt.x11.*; -import jogamp.nativewindow.x11.*; - -public class X11AWTGLXGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { - protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); - - public X11AWTGLXGraphicsConfigurationFactory() { - GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, this); - } - - protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( - CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { - GraphicsDevice device = null; - if (absScreen != null && - !(absScreen instanceof AWTGraphicsScreen)) { - throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects"); - } - - if(null==absScreen) { - absScreen = AWTGraphicsScreen.createScreenDevice(-1, AbstractGraphicsDevice.DEFAULT_UNIT); - } - AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen; - device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); - - if ( !(capsChosen instanceof GLCapabilitiesImmutable) ) { - throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilities objects - chosen"); - } - - if ( !(capsRequested instanceof GLCapabilitiesImmutable) ) { - throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilities objects - requested"); - } - - if (chooser != null && - !(chooser instanceof GLCapabilitiesChooser)) { - throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilitiesChooser objects"); - } - - if(DEBUG) { - System.err.println("X11AWTGLXGraphicsConfigurationFactory: got "+absScreen); - } - - long displayHandle = X11SunJDKReflection.graphicsDeviceGetDisplay(device); - boolean owner = false; - if(0==displayHandle) { - displayHandle = X11Util.openDisplay(null); - owner = true; - if(DEBUG) { - System.err.println(Thread.currentThread().getName() + " - X11AWTGLXGraphicsConfigurationFactory: create local X11 display"); - } - } else { - /** - * Using the AWT display handle works fine with NVidia. - * However we experienced different results w/ AMD drivers, - * some work, but some behave erratic. - * I.e. hangs in XQueryExtension(..) via X11GraphicsScreen. - */ - final String displayName = X11Util.XDisplayString(displayHandle); - if(DEBUG) { - System.err.println(Thread.currentThread().getName() + " - X11AWTGLXGraphicsConfigurationFactory: create X11 display @ "+displayName+" / 0x"+Long.toHexString(displayHandle)); - } - displayHandle = X11Util.openDisplay(displayName); - owner = true; - } - ((AWTGraphicsDevice)awtScreen.getDevice()).setSubType(NativeWindowFactory.TYPE_X11, displayHandle); - X11GraphicsDevice x11Device = new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT); - x11Device.setCloseDisplay(owner); - X11GraphicsScreen x11Screen = new X11GraphicsScreen(x11Device, awtScreen.getIndex()); - if(DEBUG) { - System.err.println("X11AWTGLXGraphicsConfigurationFactory: made "+x11Screen); - } - GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(x11Device); - GraphicsConfiguration[] configs = device.getConfigurations(); - - // - // Match the X11/GL Visual with AWT: - // - choose a config AWT agnostic and then - // - try to find the visual within the GraphicsConfiguration - // - // The resulting GraphicsConfiguration has to be 'forced' on the AWT native peer, - // ie. returned by GLCanvas's getGraphicsConfiguration() befor call by super.addNotify(). - // - X11GraphicsConfiguration x11Config = (X11GraphicsConfiguration) factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen); - if (x11Config == null) { - throw new GLException("Unable to choose a GraphicsConfiguration (1): "+capsChosen+",\n\t"+chooser+"\n\t"+x11Screen); - } - long visualID = x11Config.getVisualID(); - for (int i = 0; i < configs.length; i++) { - GraphicsConfiguration gc = configs[i]; - if (gc != null) { - if (X11SunJDKReflection.graphicsConfigurationGetVisualID(gc) == visualID) { - if(DEBUG) { - System.err.println("Found matching AWT visual: 0x"+Long.toHexString(visualID) +" -> "+x11Config); - } - return new AWTGraphicsConfiguration(awtScreen, - x11Config.getChosenCapabilities(), x11Config.getRequestedCapabilities(), - gc, x11Config); - } - } - } - - // try again using an AWT Colormodel compatible configuration - GraphicsConfiguration gc = device.getDefaultConfiguration(); - capsChosen = AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capsChosen, gc); - x11Config = (X11GraphicsConfiguration) factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen); - if (x11Config == null) { - throw new GLException("Unable to choose a GraphicsConfiguration (2): "+capsChosen+",\n\t"+chooser+"\n\t"+x11Screen); - } - visualID = x11Config.getVisualID(); - for (int i = 0; i < configs.length; i++) { - gc = configs[i]; - if (X11SunJDKReflection.graphicsConfigurationGetVisualID(gc) == visualID) { - if(DEBUG) { - System.err.println("Found matching default AWT visual: 0x"+Long.toHexString(visualID) +" -> "+x11Config); - } - return new AWTGraphicsConfiguration(awtScreen, - x11Config.getChosenCapabilities(), x11Config.getRequestedCapabilities(), - gc, x11Config); - } - } - - // Either we weren't able to reflectively introspect on the - // X11GraphicsConfig or something went wrong in the steps above; - // Let's take the default configuration as used on Windows and MacOSX then .. - if(DEBUG) { - System.err.println("!!! Using default configuration"); - } - - gc = device.getDefaultConfiguration(); - return new AWTGraphicsConfiguration(awtScreen, x11Config.getChosenCapabilities(), x11Config.getRequestedCapabilities(), gc, x11Config); - } -} diff --git a/src/jogl/native/GLDebugMessageHandler.c b/src/jogl/native/GLDebugMessageHandler.c index 509c6f695..fea9d90ce 100644 --- a/src/jogl/native/GLDebugMessageHandler.c +++ b/src/jogl/native/GLDebugMessageHandler.c @@ -35,21 +35,22 @@ typedef void (GLAPIENTRY* _local_GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenu JNIEXPORT jboolean JNICALL Java_jogamp_opengl_GLDebugMessageHandler_initIDs0 (JNIEnv *env, jclass clazz) { + jboolean res; JoglCommon_init(env); glDebugMessageARB = (*env)->GetMethodID(env, clazz, "glDebugMessageARB", "(IIIILjava/lang/String;)V"); glDebugMessageAMD = (*env)->GetMethodID(env, clazz, "glDebugMessageAMD", "(IIILjava/lang/String;)V"); - if ( NULL == glDebugMessageARB || NULL == glDebugMessageAMD ) { - return JNI_FALSE; - } - return JNI_TRUE; + res = ( NULL != glDebugMessageARB && NULL != glDebugMessageAMD ) ? JNI_TRUE : JNI_FALSE ; + + DBG_PRINT("GLDebugMessageHandler.initIDS0: OK: %d, ARB %p, AMD %p\n", res, glDebugMessageARB, glDebugMessageAMD); + + return res; } typedef struct { JavaVM *vm; int version; - JNIEnv *env; jobject obj; int extType; } DebugHandlerType; @@ -65,10 +66,12 @@ static void GLDebugMessageARBCallback(GLenum source, GLenum type, GLuint id, GLe JNIEnv *curEnv = NULL; JNIEnv *newEnv = NULL; int envRes ; - DBG_PRINT("GLDebugMessageARBCallback: 01 - %s\n", message); + 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) ) ) { @@ -107,9 +110,12 @@ static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severit 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) ) ) { @@ -117,6 +123,7 @@ static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severit return; } curEnv = newEnv; + DBG_PRINT("GLDebugMessageAMDCallback: 02 - attached .. \n"); } else if( JNI_OK != envRes ) { // oops .. fprintf(stderr, "GLDebugMessageAMDCallback: can't GetEnv: %d\n", envRes); @@ -128,7 +135,9 @@ static void GLDebugMessageAMDCallback(GLuint id, GLenum category, GLenum severit if( NULL != newEnv ) { // detached attached thread (*vm)->DetachCurrentThread(vm); + DBG_PRINT("GLDebugMessageAMDCallback: 04 - detached .. \n"); } + DBG_PRINT("GLDebugMessageAMDCallback: 0X\n"); /** * On Java 32bit on 64bit Windows, * the unit test com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT crashes after this point. @@ -152,9 +161,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_opengl_GLDebugMessageHandler_register0 } handle->vm = vm; handle->version = (*env)->GetVersion(env); - handle->env = 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); if(jogamp_opengl_GLDebugMessageHandler_EXT_ARB == extType) { _local_PFNGLDEBUGMESSAGECALLBACKARBPROC ptr_glDebugMessageCallbackARB; @@ -181,9 +191,9 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_GLDebugMessageHandler_unregister0 { DebugHandlerType * handle = (DebugHandlerType*) (intptr_t) jhandle; - if(env != handle->env) { - JoglCommon_throwNewRuntimeException(env, "wrong handle (env doesn't match)"); - } + DBG_PRINT("GLDebugMessageHandler.unregister0: vm %p, version 0x%X, jobject %p, extType %d\n", + handle->vm, handle->version, (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/macosx/ContextUpdater.h b/src/jogl/native/macosx/ContextUpdater.h index 3cf7315af..f00b2be57 100644 --- a/src/jogl/native/macosx/ContextUpdater.h +++ b/src/jogl/native/macosx/ContextUpdater.h @@ -25,17 +25,13 @@ This notification is sent whenever an NSView that has an attached NSSurface chan @interface ContextUpdater : NSObject { @protected + pthread_mutex_t resourceLock; NSView * view; NSRect viewRect; NSOpenGLContext *ctx; BOOL viewUpdated; } -- (void) lock; -- (void) lockInFunction:(char *)func atLine:(int)line; -- (void) unlock; -- (void) unlockInFunction:(char *)func atLine:(int)line; - - (id) initWithContext:(NSOpenGLContext *)context view: (NSView *)nsView; - (void) update:(NSNotification *)notification; diff --git a/src/jogl/native/macosx/ContextUpdater.m b/src/jogl/native/macosx/ContextUpdater.m index 21f98ad5e..d01eaf967 100644 --- a/src/jogl/native/macosx/ContextUpdater.m +++ b/src/jogl/native/macosx/ContextUpdater.m @@ -1,43 +1,26 @@ #import "ContextUpdater.h" #import <pthread.h> -@implementation ContextUpdater -{ -} - -static pthread_mutex_t resourceLock = PTHREAD_MUTEX_INITIALIZER; - -static void printLockDebugInfo(char *message, char *func, int line) -{ - fprintf(stderr, "%s in function: \"%s\" at line: %d\n", message, func, line); - fflush(NULL); -} - -- (void) lock -{ - pthread_mutex_lock(&resourceLock); -} +// #define VERBOSE_ON 1 -- (void) lockInFunction:(char *)func atLine:(int)line -{ - printLockDebugInfo("locked ", func, line); - [self lock]; -} +#ifdef VERBOSE_ON + #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) + // #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define DBG_PRINT(...) +#endif -- (void) unlock -{ - pthread_mutex_unlock(&resourceLock); -} +#ifndef CGL_VERSION_1_3 + #warning this SDK doesn't support OpenGL profile +#endif -- (void) unlockInFunction:(char *)func atLine:(int)line +@implementation ContextUpdater { - printLockDebugInfo("unlocked", func, line); - [self unlock]; } - (void) update:(NSNotification *)notification { - [self lock]; + pthread_mutex_lock(&resourceLock); NSRect r = [view frame]; if(viewRect.origin.x != r.origin.x || @@ -47,41 +30,47 @@ static void printLockDebugInfo(char *message, char *func, int line) viewUpdated = TRUE; viewRect = r; } - - [self unlock]; + + pthread_mutex_unlock(&resourceLock); } - (BOOL) needsUpdate { BOOL r; - [self lock]; + pthread_mutex_lock(&resourceLock); r = viewUpdated; viewUpdated = FALSE; - [self unlock]; + pthread_mutex_unlock(&resourceLock); return r; } - (id) initWithContext:(NSOpenGLContext *)context view: (NSView *)nsView { + DBG_PRINT("ContextUpdater::init.0 view %p, ctx %p\n", view, ctx); + pthread_mutex_init(&resourceLock, NULL); // fast non-recursive ctx = context; view = nsView; [ctx retain]; [view retain]; viewRect = [view frame]; - viewUpdated = FALSE; + viewUpdated = TRUE; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(update:) name:NSViewGlobalFrameDidChangeNotification object: view]; + DBG_PRINT("ContextUpdater::init.X\n"); return [super init]; } - (void) dealloc { + DBG_PRINT("ContextUpdater::dealloc.0 view %p, ctx %p\n", view, ctx); [[NSNotificationCenter defaultCenter] removeObserver:self]; [view release]; [ctx release]; + pthread_mutex_destroy(&resourceLock); + DBG_PRINT("ContextUpdater::dealloc.X\n"); [super dealloc]; } diff --git a/src/jogl/native/macosx/MacOSXCustomCGLCode.c b/src/jogl/native/macosx/MacOSXCustomCGLCode.c index c29be889d..f8b7a800f 100644 --- a/src/jogl/native/macosx/MacOSXCustomCGLCode.c +++ b/src/jogl/native/macosx/MacOSXCustomCGLCode.c @@ -5,8 +5,7 @@ #include </usr/include/machine/types.h> #include "macosx-window-system.h" -void CGLQueryPixelFormat(void* pixelFormat, int* iattrs, int niattrs, int* ivalues) { - CGLPixelFormatObj pix = (CGLPixelFormatObj) pixelFormat; +void CGLQueryPixelFormat(CGLPixelFormatObj fmt, int* iattrs, int niattrs, int* ivalues) { // FIXME: think about how specifying this might affect the API int virtualScreen = 0; @@ -14,7 +13,7 @@ void CGLQueryPixelFormat(void* pixelFormat, int* iattrs, int niattrs, int* ivalu GLint value; for (i = 0; i < niattrs && iattrs[i]>0; i++) { CGLPixelFormatAttribute attr = (CGLPixelFormatAttribute) iattrs[i]; - if ( kCGLNoError == CGLDescribePixelFormat(pix, virtualScreen, attr, &value) ) { + if ( kCGLNoError == CGLDescribePixelFormat(fmt, virtualScreen, attr, &value) ) { ivalues[i] = value; } else { ivalues[i] = 0; diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-nsview.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-nsview.m new file mode 100644 index 000000000..7233f40ce --- /dev/null +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-nsview.m @@ -0,0 +1,140 @@ + +@interface MyNSOpenGLLayer: NSOpenGLLayer +{ +@protected + NSOpenGLContext* ctxShared; + NSView* view; + NSOpenGLPixelFormat* fmt; +@public + volatile BOOL shallDraw; +} + +- (id) initWithContext: (NSOpenGLContext*) ctx + pixelFormat: (NSOpenGLPixelFormat*) pfmt + view: (NSView*) v + opaque: (Bool) opaque; + +@end + +@implementation MyNSOpenGLLayer + +- (id) initWithContext: (NSOpenGLContext*) _ctx + pixelFormat: (NSOpenGLPixelFormat*) _fmt + view: (NSView*) _view + opaque: (Bool) opaque +{ + self = [super init]; + ctxShared = _ctx; + [ctxShared retain]; + + fmt = _fmt; + [fmt retain]; + + view = _view; + [view retain]; + [self setView: view]; + [view setLayer: self]; + [view setWantsLayer: YES]; + + [self setAsynchronous: NO]; + // [self setAsynchronous: YES]; // FIXME: JAU + [self setNeedsDisplayOnBoundsChange: NO]; + [self setOpaque: opaque ? YES : NO]; + shallDraw = NO; + textureID = 0; + DBG_PRINT("MyNSOpenGLLayer::init %p, ctx %p, pfmt %p, view %p, opaque %d\n", self, ctx, fmt, view, opaque); + return self; +} + +- (void)dealloc +{ + [fmt release]; + [ctxShared release]; + [view release]; + DBG_PRINT("MyNSOpenGLLayer::dealloc %p\n", self); + [super dealloc]; +} + +- (void) setOpenGLContext: (NSOpenGLContext*) _ctx +{ + DBG_PRINT("MyNSOpenGLLayer::setOpenGLContext: %p %p -> %p\n", self, [self openGLContext], _ctx); + [super setOpenGLContext: _ctx]; +} + +- (void) setOpenGLPixelFormat: (NSOpenGLPixelFormat*) _fmt +{ + DBG_PRINT("MyNSOpenGLLayer::setOpenGLPixelFormat %p %p -> %p\n", self, fmt, _fmt); + [super setOpenGLPixelFormat: fmt]; +} + +- (NSOpenGLPixelFormat *) openGLPixelFormat +{ + return fmt; +} + +- (void) setView: (NSView*) v +{ + DBG_PRINT("MyNSOpenGLLayer::setView %p %p -> %p (ignored/propagated)\n", self, view, v); + [super setView: view]; // propagate +} + +- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask +{ + DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask %p %d -> %p\n", self, mask, fmt); + return fmt; +} + +- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat +{ + NSOpenGLContext* ctx = NULL; + if(NULL == ctx) { + int viewNotReady[] = { 0 }; + ctx = createContext(ctxShared, view, true, fmt, [self isOpaque], viewNotReady); + } + DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat %p, fmt %p/%p, view %p, shared %p -> %p\n", + self, fmt, pixelFormat, view, ctxShared, ctx); + return ctx; +} + +- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp +{ + DBG_PRINT("MyNSOpenGLLayer::canDrawInOpenGLContext %p: %d\n", self, self->shallDraw); + return self->shallDraw; +} + +- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp +{ + self->shallDraw = NO; + + DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p, ctx %p, pfmt %p\n", self, context, pixelFormat); + + [super drawInOpenGLContext: context pixelFormat: pixelFormat forLayerTime: timeInterval displayTime: timeStamp]; +} + +@end + +NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSView* view, Bool opaque) { + return [[MyNSOpenGLLayer alloc] initWithContext:ctx pixelFormat: fmt view: view opaque: opaque]; +} + +void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + l->shallDraw = YES; + [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:YES]; + // NSView* view = [l view]; + // [view setNeedsDisplay: YES]; // FIXME: JAU + // [view performSelectorOnMainThread:@selector(setNeedsDisplay:) withObject:YES waitUntilDone:YES]; + // [view performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:YES]; + DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l); + [pool release]; +} + +void releaseNSOpenGLLayer(NSOpenGLLayer* l) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [l release]; + [pool release]; +} + diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m new file mode 100644 index 000000000..fe896cc53 --- /dev/null +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m @@ -0,0 +1,480 @@ +#import "MacOSXWindowSystemInterface.h" +#import <QuartzCore/QuartzCore.h> +#import <pthread.h> +#include "timespec.h" + +// +// CADisplayLink only available on iOS >= 3.1, sad, since it's convenient. +// Use CVDisplayLink otherwise. +// +// #define HAS_CADisplayLink 1 +// + +// lock/sync debug output +// +// #define DBG_SYNC 1 +// +#ifdef DBG_SYNC + // #define SYNC_PRINT(...) NSLog(@ ## __VA_ARGS__) + #define SYNC_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define SYNC_PRINT(...) +#endif + +// fps debug output +// +// #define DBG_PERF 1 + +@interface MyNSOpenGLLayer: NSOpenGLLayer +{ +@protected + NSOpenGLPixelBuffer* pbuffer; + int texWidth; + int texHeight; + GLuint textureID; + GLint swapInterval; +#ifdef HAS_CADisplayLink + CADisplayLink* displayLink; +#else + CVDisplayLinkRef displayLink; +#endif + int tc; + struct timespec t0; +@public + pthread_mutex_t renderLock; + pthread_cond_t renderSignal; + BOOL shallDraw; +} + +- (id) setupWithContext: (NSOpenGLContext*) ctx + pixelFormat: (NSOpenGLPixelFormat*) pfmt + pbuffer: (NSOpenGLPixelBuffer*) p + opaque: (Bool) opaque + texWidth: (int) texWidth + texHeight: (int) texHeight; + +- (void)deallocTex; +- (void)disableAnimation; +- (void)releaseLayer; +- (void)dealloc; +- (int)getSwapInterval; +- (void)setSwapInterval:(int)interval; +- (void)tick; + +@end + +#ifndef HAS_CADisplayLink + +static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink, + const CVTimeStamp *inNow, + const CVTimeStamp *inOutputTime, + CVOptionFlags flagsIn, + CVOptionFlags *flagsOut, + void *displayLinkContext) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*)displayLinkContext; + pthread_mutex_lock(&l->renderLock); + #ifdef DBG_PERF + [l tick]; + #endif + pthread_cond_signal(&l->renderSignal); + SYNC_PRINT("-*-"); + pthread_mutex_unlock(&l->renderLock); + [pool release]; + return kCVReturnSuccess; +} + +#endif + +@implementation MyNSOpenGLLayer + +- (id) setupWithContext: (NSOpenGLContext*) _ctx + pixelFormat: (NSOpenGLPixelFormat*) _fmt + pbuffer: (NSOpenGLPixelBuffer*) p + opaque: (Bool) opaque + texWidth: (int) _texWidth + texHeight: (int) _texHeight; +{ + pthread_mutexattr_t renderLockAttr; + pthread_mutexattr_init(&renderLockAttr); + pthread_mutexattr_settype(&renderLockAttr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&renderLock, &renderLockAttr); // recursive + pthread_cond_init(&renderSignal, NULL); // no attribute + + // no animations for add/remove/swap sublayers etc + [self removeAnimationForKey: kCAOnOrderIn]; + [self removeAnimationForKey: kCAOnOrderOut]; + [self removeAnimationForKey: kCATransition]; + + pbuffer = p; + [pbuffer retain]; + + // instantiate a deactivated displayLink +#ifdef HAS_CADisplayLink + displayLink = [[CVDisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)] retain]; + [displayLink setPaused: YES]; +#else + CVReturn cvres; + { + int allDisplaysMask = 0; + int virtualScreen, accelerated, displayMask; + for (virtualScreen = 0; virtualScreen < [_fmt numberOfVirtualScreens]; virtualScreen++) { + [_fmt getValues:&displayMask forAttribute:NSOpenGLPFAScreenMask forVirtualScreen:virtualScreen]; + [_fmt getValues:&accelerated forAttribute:NSOpenGLPFAAccelerated forVirtualScreen:virtualScreen]; + if (accelerated) { + allDisplaysMask |= displayMask; + } + } + cvres = CVDisplayLinkCreateWithOpenGLDisplayMask(allDisplaysMask, &displayLink); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkCreateWithOpenGLDisplayMask %X failed: %d\n", self, allDisplaysMask, cvres); + displayLink = NULL; + } + } + if(NULL != displayLink) { + cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [_ctx CGLContextObj], [_fmt CGLPixelFormatObj]); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres); + displayLink = NULL; + } + } + if(NULL != displayLink) { + cvres = CVDisplayLinkSetOutputCallback(displayLink, renderMyNSOpenGLLayer, self); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetOutputCallback failed: %d\n", self, cvres); + displayLink = NULL; + } + } + if(NULL != displayLink) { + CVDisplayLinkStop(displayLink); + } +#endif + [self setAsynchronous: YES]; + + [self setNeedsDisplayOnBoundsChange: YES]; // FIXME: learn how to recreate on size change! + [self setOpaque: opaque ? YES : NO]; + texWidth = _texWidth; + texHeight = _texHeight; + textureID = 0; + swapInterval = -1; + shallDraw = NO; + + CGRect lRect = [self frame]; + + DBG_PRINT("MyNSOpenGLLayer::init %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d, frame: %lf/%lf %lfx%lf (refcnt %d)\n", + self, _ctx, _fmt, pbuffer, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight, + lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]); + return self; +} + +- (void)disableAnimation +{ + DBG_PRINT("MyNSOpenGLLayer::disableAnimation: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink); + pthread_mutex_lock(&renderLock); + [self setAsynchronous: NO]; + if(NULL != displayLink) { +#ifdef HAS_CADisplayLink + [displayLink setPaused: YES]; + [displayLink release]; +#else + if(NULL!=displayLink) { + CVDisplayLinkStop(displayLink); + CVDisplayLinkRelease(displayLink); + } +#endif + displayLink = NULL; + } + pthread_mutex_unlock(&renderLock); +} + +- (void)deallocTex +{ + pthread_mutex_lock(&renderLock); + NSOpenGLContext* context = [self openGLContext]; + DBG_PRINT("MyNSOpenGLLayer::deallocTex %p (refcnt %d) - context %p, pbuffer %p\n", self, (int)[self retainCount], context, pbuffer); + if(NULL != pbuffer) { + if(NULL!=context) { + [context makeCurrentContext]; + if(0 != textureID) { + glDeleteTextures(1, &textureID); + textureID = 0; + } + [context clearDrawable]; + } + [pbuffer release]; + pbuffer = NULL; + } + pthread_mutex_unlock(&renderLock); +} + +- (void)releaseLayer +{ + DBG_PRINT("MyNSOpenGLLayer::releaseLayer.0: %p (refcnt %d)\n", self, (int)[self retainCount]); + pthread_mutex_lock(&renderLock); + [self disableAnimation]; + [self deallocTex]; + [self release]; + DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p (refcnt %d)\n", self, (int)[self retainCount]); + pthread_mutex_unlock(&renderLock); +} + +- (void)dealloc +{ + DBG_PRINT("MyNSOpenGLLayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]); + // NSLog(@"MyNSOpenGLLayer::dealloc: %@",[NSThread callStackSymbols]); + + [self disableAnimation]; + [self deallocTex]; + pthread_cond_destroy(&renderSignal); + pthread_mutex_destroy(&renderLock); + [super dealloc]; + DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self); +} + +- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp +{ + // assume both methods 'canDrawInOpenGLContext' and 'drawInOpenGLContext' + // are called from the same thread subsequently + pthread_mutex_lock(&renderLock); + Bool res = NULL != pbuffer && YES == shallDraw; + if(!res) { + SYNC_PRINT("<0>"); + pthread_mutex_unlock(&renderLock); + } else { + SYNC_PRINT("<"); + } + return res; +} + +- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp +{ + [context makeCurrentContext]; + + /** + * v-sync doesn't works w/ NSOpenGLLayer's context .. well :( + * Using CVDisplayLink .. see setSwapInterval() below. + * + if(0 <= swapInterval) { + GLint si; + [context getValues: &si forParameter: NSOpenGLCPSwapInterval]; + if(si != swapInterval) { + DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p setSwapInterval: %d -> %d\n", self, si, swapInterval); + [context setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; + } + } */ + GLenum textureTarget = [pbuffer textureTarget]; + GLfloat tWidth, tHeight; + { + GLsizei pwidth = [pbuffer pixelsWide]; + GLsizei pheight = [pbuffer pixelsHigh]; + tWidth = textureTarget == GL_TEXTURE_2D ? (GLfloat)pwidth /(GLfloat)texWidth : pwidth; + tHeight = textureTarget == GL_TEXTURE_2D ? (GLfloat)pheight/(GLfloat)texHeight : pheight; + } + Bool texCreated = 0 == textureID; + + if(texCreated) { + glGenTextures(1, &textureID); + DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p, ctx %p, pfmt %p tex %dx%d -> %fx%f 0x%X: creating texID 0x%X\n", + self, context, pixelFormat, texWidth, texHeight, tWidth, tHeight, textureTarget, textureID); + + CGRect lRect = [self frame]; + DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p frame0: %lf/%lf %lfx%lf\n", + self, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height); + } + + glBindTexture(textureTarget, textureID); + + /** + if(texCreated) { + // proper tex size setup + glTexImage2D(textureTarget, 0, GL_RGB, texWidth, texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + } */ + + [context setTextureImageToPixelBuffer: pbuffer colorBuffer: GL_FRONT]; + + glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glEnable(textureTarget); + + static GLfloat verts[] = { + -1.0, -1.0, + -1.0, 1.0, + 1.0, 1.0, + 1.0, -1.0 + }; + + GLfloat tex[] = { + 0.0, 0.0, + 0.0, tHeight, + tWidth, tHeight, + tWidth, 0.0 + }; + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, verts); + glTexCoordPointer(2, GL_FLOAT, 0, tex); + + glDrawArrays(GL_QUADS, 0, 4); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glDisable(textureTarget); + glBindTexture(textureTarget, 0); + + [super drawInOpenGLContext: context pixelFormat: pixelFormat forLayerTime: timeInterval displayTime: timeStamp]; + shallDraw = NO; + if(0 >= swapInterval) { + pthread_cond_signal(&renderSignal); + SYNC_PRINT("*"); + } + SYNC_PRINT("1>"); + pthread_mutex_unlock(&renderLock); +} + +- (int)getSwapInterval +{ + return swapInterval; +} + +- (void)setSwapInterval:(int)interval +{ + DBG_PRINT("MyNSOpenGLLayer::setSwapInterval: %d\n", interval); + swapInterval = interval; + if(0 < swapInterval) { + tc = 0; + timespec_now(&t0); + + [self setAsynchronous: NO]; + #ifdef HAS_CADisplayLink + [displayLink setPaused: NO]; + [displayLink setFrameInterval: interval]; + #else + if(NULL!=displayLink) { + CVDisplayLinkStart(displayLink); + // FIXME: doesn't support interval .. + } + #endif + } else { + #ifdef HAS_CADisplayLink + [displayLink setPaused: YES]; + #else + if(NULL!=displayLink) { + CVDisplayLinkStop(displayLink); + } + #endif + [self setAsynchronous: YES]; + } +} + +-(void)tick +{ + tc++; + if(tc%60==0) { + struct timespec t1, td; + timespec_now(&t1); + timespec_subtract(&td, &t1, &t0); + long td_ms = timespec_milliseconds(&td); + fprintf(stderr, "NSOpenGLLayer: %ld ms / %d frames, %ld ms / frame, %f fps\n", + td_ms, tc, td_ms/tc, (tc * 1000.0) / (float)td_ms ); + fflush(NULL); + } +} + +@end + +NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, Bool opaque, int texWidth, int texHeight) { + // This simply crashes after dealloc() has been called .. ie. ref-count -> 0 too early ? + // However using alloc/init, actual dealloc happens at JAWT destruction, hence too later IMHO. + // return [[MyNSOpenGLLayer layer] setupWithContext:ctx pixelFormat: fmt pbuffer: p opaque: opaque texWidth: texWidth texHeight: texHeight]; + + return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx pixelFormat: fmt pbuffer: p opaque: opaque texWidth: texWidth texHeight: texHeight]; +} + +void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + pthread_mutex_lock(&l->renderLock); + [l setSwapInterval: interval]; + pthread_mutex_unlock(&l->renderLock); +} + +void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_ms) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + BOOL ready = NO; + int wr = 0; + pthread_mutex_lock(&l->renderLock); + SYNC_PRINT("{"); + do { + if([l getSwapInterval] <= 0) { + ready = !l->shallDraw; + } + if(NO == ready) { + if(0 < to_ms) { + struct timespec to_abs; + timespec_now(&to_abs); + timespec_addms(&to_abs, to_ms); + wr = pthread_cond_timedwait(&l->renderSignal, &l->renderLock, &to_abs); + #ifdef DBG_SYNC + struct timespec t1, td; + timespec_now(&t1); + timespec_subtract(&td, &t1, &to_abs); + long td_ms = timespec_milliseconds(&td); + fprintf(stderr, "%ld ms", td_ms); + #endif + } else { + pthread_cond_wait (&l->renderSignal, &l->renderLock); + } + ready = !l->shallDraw; + } + } while (NO == ready && 0 == wr) ; + SYNC_PRINT("-%d}", ready); + pthread_mutex_unlock(&l->renderLock); +} + +void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + @synchronized(l) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + pthread_mutex_lock(&l->renderLock); + SYNC_PRINT("["); + l->shallDraw = YES; + if([l getSwapInterval] > 0) { + // only trigger update if async mode is off (swapInterval>0) + if ( [NSThread isMainThread] == YES ) { + [l setNeedsDisplay]; + } else { + // can't wait, otherwise we may deadlock AWT + [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO]; + } + SYNC_PRINT("1]"); + } else { + SYNC_PRINT("0]"); + } + pthread_mutex_unlock(&l->renderLock); + // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l); + [pool release]; + } +} + +void releaseNSOpenGLLayer(NSOpenGLLayer* layer) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l); + + if ( [NSThread isMainThread] == YES ) { + [l releaseLayer]; + } else { + [l performSelectorOnMainThread:@selector(releaseLayer) withObject:nil waitUntilDone:NO]; + } + + DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.X: %p\n", l); + [pool release]; +} + diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.h b/src/jogl/native/macosx/MacOSXWindowSystemInterface.h new file mode 100644 index 000000000..138accb22 --- /dev/null +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.h @@ -0,0 +1,20 @@ +#import <Cocoa/Cocoa.h> +#import <OpenGL/gl.h> +#import <OpenGL/CGLTypes.h> +#import <jni.h> + +// #define VERBOSE_ON 1 + +#ifdef VERBOSE_ON + #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) + // #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define DBG_PRINT(...) +#endif + +#ifndef CGL_VERSION_1_3 + #warning this SDK doesn't support OpenGL profile +#endif + +#import "macosx-window-system.h" + diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m index 751fba9c0..b5979d53e 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m @@ -14,19 +14,10 @@ #endif */ -#import <Cocoa/Cocoa.h> -#import <OpenGL/gl.h> -#import <OpenGL/CGLTypes.h> -#import <jni.h> - -#ifndef CGL_VERSION_1_3 - #warning this SDK doesn't support OpenGL profile -#endif +#import "MacOSXWindowSystemInterface.h" #import "ContextUpdater.h" -#import "macosx-window-system.h" - // see MacOSXPbufferGLContext.java createPbuffer #define USE_GL_TEXTURE_RECTANGLE_EXT @@ -377,7 +368,7 @@ long validateParameter(NSOpenGLPixelFormatAttribute attribute, long value) return value; } -void* createPixelFormat(int* iattrs, int niattrs, int* ivalues) { +NSOpenGLPixelFormat* createPixelFormat(int* iattrs, int niattrs, int* ivalues) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; getRendererInfo(); @@ -390,6 +381,18 @@ void* createPixelFormat(int* iattrs, int niattrs, int* ivalues) { for (i = 0; i < niattrs && iattrs[i]>0; i++) { int attr = iattrs[i]; switch (attr) { + case NSOpenGLPFANoRecovery: + if (ivalues[i] != 0) { + attribs[idx++] = NSOpenGLPFANoRecovery; + } + break; + + case NSOpenGLPFAAccelerated: + if (ivalues[i] != 0) { + attribs[idx++] = NSOpenGLPFAAccelerated; + } + break; + case NSOpenGLPFAPixelBuffer: if (ivalues[i] != 0) { attribs[idx++] = NSOpenGLPFAPixelBuffer; @@ -451,9 +454,8 @@ void* createPixelFormat(int* iattrs, int niattrs, int* ivalues) { return fmt; } -void queryPixelFormat(void* pixelFormat, int* iattrs, int niattrs, int* ivalues) { +void queryPixelFormat(NSOpenGLPixelFormat* fmt, int* iattrs, int niattrs, int* ivalues) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSOpenGLPixelFormat* fmt = (NSOpenGLPixelFormat*) pixelFormat; GLint tmp; // FIXME: think about how specifying this might affect the API GLint virtualScreen = 0; @@ -468,16 +470,43 @@ void queryPixelFormat(void* pixelFormat, int* iattrs, int niattrs, int* ivalues) [pool release]; } -void deletePixelFormat(void* pixelFormat) { +void deletePixelFormat(NSOpenGLPixelFormat* fmt) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSOpenGLPixelFormat* fmt = (NSOpenGLPixelFormat*) pixelFormat; [fmt release]; [pool release]; } -void* createContext(void* shareContext, - void* view, - void* pixelFormat, +NSOpenGLContext* getCurrentContext() { + NSOpenGLContext *ctx = NULL; + + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + ctx = [NSOpenGLContext currentContext]; + [pool release]; + return ctx; +} + +CGLContextObj getCGLContext(NSOpenGLContext* ctx) { + void * cglContext = NULL; + + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + cglContext = [ctx CGLContextObj]; + [pool release]; + return cglContext; +} + +NSView* getNSView(NSOpenGLContext* ctx) { + NSView* view = NULL; + + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + view = [ctx view]; + [pool release]; + return view; +} + +NSOpenGLContext* createContext(NSOpenGLContext* share, + NSView* view, + Bool isBackingLayerView, + NSOpenGLPixelFormat* fmt, Bool opaque, int* viewNotReady) { @@ -485,27 +514,22 @@ void* createContext(void* shareContext, NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSView *nsView = NULL; - NSObject *nsObj = (NSObject*) view; - - if( nsObj != NULL && [nsObj isKindOfClass:[NSView class]] ) { - nsView = (NSView*)nsObj; - } - - if (nsView != NULL) - { + if (view != NULL) { Bool viewReady = true; - if ([nsView lockFocusIfCanDraw] == NO) - { - viewReady = false; + if(!isBackingLayerView) { + if ([view lockFocusIfCanDraw] == NO) { + DBG_PRINT("createContext [view lockFocusIfCanDraw] failed\n"); + viewReady = false; + } } - else - { - NSRect frame = [nsView frame]; - if ((frame.size.width == 0) || (frame.size.height == 0)) - { - [nsView unlockFocus]; + if(viewReady) { + NSRect frame = [view frame]; + if ((frame.size.width == 0) || (frame.size.height == 0)) { + if(!isBackingLayerView) { + [view unlockFocus]; + } + DBG_PRINT("createContext view.frame size %dx%d\n", (int)frame.size.width, (int)frame.size.height); viewReady = false; } } @@ -523,126 +547,95 @@ void* createContext(void* shareContext, } } - NSOpenGLContext* nsContext = [[NSOpenGLContext alloc] - initWithFormat: (NSOpenGLPixelFormat*) pixelFormat - shareContext: (NSOpenGLContext*) shareContext]; + NSOpenGLContext* ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:share]; - if (nsContext != nil) { - if (nsView != nil) { - if(!opaque) { - GLint zeroOpacity = 0; - [nsContext setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity]; - } - [nsContext setView:nsView]; - [nsView unlockFocus]; - } + if (ctx != nil) { + if (view != nil) { + if(!opaque) { + GLint zeroOpacity = 0; + [ctx setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity]; + } + [ctx setView:view]; + if(!isBackingLayerView) { + [view unlockFocus]; } + } + } [pool release]; - return nsContext; -} - -void * getCurrentContext() { - NSOpenGLContext *nsContext = NULL; - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - nsContext = [NSOpenGLContext currentContext]; - [pool release]; - return nsContext;; + return ctx; } -void * getCGLContext(void* nsJContext) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - void * cglContext = NULL; - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - cglContext = [nsContext CGLContextObj]; - [pool release]; - return cglContext; -} - -void * getNSView(void* nsJContext) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - void * view = NULL; - +Bool makeCurrentContext(NSOpenGLContext* ctx) { +#if 0 + // we issue the CGL Lock from Java upfront! NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - view = [nsContext view]; + CGLError cglError = CGLLockContext([ctx CGLContextObj]); + if(0 == cglError) { + [ctx makeCurrentContext]; + } [pool release]; - return view; -} - -Bool makeCurrentContext(void* nsJContext) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - + return 0 == cglError; +#else NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [nsContext makeCurrentContext]; + [ctx makeCurrentContext]; [pool release]; return true; +#endif } -Bool clearCurrentContext(void* nsJContext) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - +Bool clearCurrentContext(NSOpenGLContext* ctx) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSOpenGLContext *currentNSContext = [NSOpenGLContext currentContext]; - if( currentNSContext != nsContext ) { - [nsContext makeCurrentContext]; + if( currentNSContext != ctx ) { + [ctx makeCurrentContext]; } [NSOpenGLContext clearCurrentContext]; +#if 0 + // we issue the CGL Lock from Java upfront! + CGLUnlockContext([ctx CGLContextObj]); +#endif [pool release]; return true; } -Bool deleteContext(void* nsJContext, Bool releaseOnMainThread) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - +Bool deleteContext(NSOpenGLContext* ctx, Bool releaseOnMainThread) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [nsContext clearDrawable]; + [ctx clearDrawable]; if(releaseOnMainThread && NO == [NSThread isMainThread]) { - [nsContext performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:YES]; + [ctx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO]; } else { // would hangs for ~10s for 1 of a shared context set or offscreen context, set releaseOnMainThread=true ! - [nsContext release]; + [ctx release]; } [pool release]; return true; } -Bool flushBuffer(void* nsJContext) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - +Bool flushBuffer(NSOpenGLContext* ctx) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [nsContext flushBuffer]; + [ctx flushBuffer]; [pool release]; return true; } -void setContextOpacity(void* nsJContext, int opacity) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - - [nsContext setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity]; +void setContextOpacity(NSOpenGLContext* ctx, int opacity) { + [ctx setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity]; } -void updateContext(void* nsJContext) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - +void updateContext(NSOpenGLContext* ctx) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [nsContext update]; + [ctx update]; [pool release]; } -void copyContext(void* destContext, void* srcContext, int mask) { - NSOpenGLContext *src = (NSOpenGLContext*) srcContext; - NSOpenGLContext *dst = (NSOpenGLContext*) destContext; - [dst copyAttributesFromContext: src withMask: mask]; +void copyContext(NSOpenGLContext* dest, NSOpenGLContext* src, int mask) { + [dest copyAttributesFromContext: src withMask: mask]; } -void* updateContextRegister(void* nsJContext, void* nsJView) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - NSView *nsView = (NSView*)nsJView; - +void* updateContextRegister(NSOpenGLContext* ctx, NSView* view) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - ContextUpdater *contextUpdater = [[ContextUpdater alloc] initWithContext: nsContext view: nsView]; + ContextUpdater *contextUpdater = [[ContextUpdater alloc] initWithContext: ctx view: view]; [pool release]; return contextUpdater; } @@ -666,7 +659,7 @@ void updateContextUnregister(void* updater) { [pool release]; } -void* createPBuffer(int renderTarget, int internalFormat, int width, int height) { +NSOpenGLPixelBuffer* createPBuffer(int renderTarget, int internalFormat, int width, int height) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSOpenGLPixelBuffer* pBuffer = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:renderTarget @@ -678,35 +671,25 @@ void* createPBuffer(int renderTarget, int internalFormat, int width, int height) return pBuffer; } -Bool destroyPBuffer(void* buffer) { - NSOpenGLPixelBuffer *pBuffer = (NSOpenGLPixelBuffer*)buffer; - +Bool destroyPBuffer(NSOpenGLPixelBuffer* pBuffer) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [pBuffer release]; [pool release]; - return true; } -void setContextPBuffer(void* nsJContext, void* buffer) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - NSOpenGLPixelBuffer *pBuffer = (NSOpenGLPixelBuffer*)buffer; - +void setContextPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer* pBuffer) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [nsContext setPixelBuffer: pBuffer + [ctx setPixelBuffer: pBuffer cubeMapFace: 0 mipMapLevel: 0 - currentVirtualScreen: [nsContext currentVirtualScreen]]; + currentVirtualScreen: [ctx currentVirtualScreen]]; [pool release]; } -void setContextTextureImageToPBuffer(void* nsJContext, void* buffer, int colorBuffer) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; - NSOpenGLPixelBuffer *pBuffer = (NSOpenGLPixelBuffer*)buffer; - +void setContextTextureImageToPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer* pBuffer, GLenum colorBuffer) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [nsContext setTextureImageToPixelBuffer: pBuffer - colorBuffer: (unsigned long) colorBuffer]; + [ctx setTextureImageToPixelBuffer: pBuffer colorBuffer: colorBuffer]; [pool release]; } @@ -746,10 +729,9 @@ void* getProcAddress(const char *procname) { return NULL; } -void setSwapInterval(void* nsJContext, int interval) { - NSOpenGLContext *nsContext = (NSOpenGLContext*)nsJContext; +void setSwapInterval(NSOpenGLContext* ctx, int interval) { GLint swapInterval = interval; - [nsContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; + [ctx setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; } Bool setGammaRamp(int tableSize, float* redRamp, float* greenRamp, float* blueRamp) { diff --git a/src/jogl/native/timespec.c b/src/jogl/native/timespec.c new file mode 100644 index 000000000..74c1a6901 --- /dev/null +++ b/src/jogl/native/timespec.c @@ -0,0 +1,63 @@ +#include "timespec.h" +#include <sys/time.h> + +void timespec_now(struct timespec *ts) +{ + struct timeval tv; + + // not using clock_gettime() [of rt library] due to portability + gettimeofday(&tv, NULL); + ts->tv_sec = tv.tv_sec; + ts->tv_nsec = tv.tv_usec*1000; +} + +void timespec_addms(struct timespec *ts, long ms) +{ + int sec=ms/1000; + ms=ms-sec*1000; + + // perform the addition + ts->tv_nsec+=ms*1000000; + + // adjust the time + ts->tv_sec+=ts->tv_nsec/1000000000 + sec; + ts->tv_nsec=ts->tv_nsec%1000000000; +} + +void timespec_addns(struct timespec *ts, long ns) +{ + int sec=ns/1000000000; + ns=ns - sec*1000000000; + + // perform the addition + ts->tv_nsec+=ns; + + // adjust the time + ts->tv_sec+=ts->tv_nsec/1000000000 + sec; + ts->tv_nsec=ts->tv_nsec%1000000000; + +} + +int timespec_compare(struct timespec *a, struct timespec *b) +{ + if (a->tv_sec!=b->tv_sec) + return a->tv_sec-b->tv_sec; + return a->tv_nsec-b->tv_nsec; +} + +void timespec_subtract(struct timespec *r, struct timespec *a, struct timespec *b) +{ + r->tv_sec = a->tv_sec; + r->tv_nsec = a->tv_nsec - b->tv_nsec; + if (r->tv_nsec < 0) { + // borrow. + r->tv_nsec += 1000000000; + r->tv_sec --; + } + r->tv_sec = r->tv_sec - b->tv_sec; +} + +long timespec_milliseconds(struct timespec *a) +{ + return a->tv_sec*1000 + a->tv_nsec/1000000; +} diff --git a/src/jogl/native/timespec.h b/src/jogl/native/timespec.h new file mode 100644 index 000000000..671eb4716 --- /dev/null +++ b/src/jogl/native/timespec.h @@ -0,0 +1,19 @@ +#ifndef _timespec_h +#define _timespec_h + +#include <time.h> + +void timespec_now(struct timespec *ts); +void timespec_addms(struct timespec *ts, long ms); +void timespec_addns(struct timespec *ts, long ns); + +/** returns 0: a==b, >0: a>b, <0: a<b */ +int timespec_compare(struct timespec *a, struct timespec *b); + +/** computes r = a - b */ +void timespec_subtract(struct timespec *r, struct timespec *a, struct timespec *b); + +/** convert the timespec into milliseconds (may overflow) */ +long timespec_milliseconds(struct timespec *a); + +#endif /* _timespec_h */ |