diff options
Diffstat (limited to 'src/jogl/classes/javax/media')
-rw-r--r-- | src/jogl/classes/javax/media/opengl/GLBase.java | 11 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/GLContext.java | 74 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/GLDrawable.java | 6 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/GLDrawableFactory.java | 111 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/GLProfile.java | 287 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/GLUniformData.java | 6 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/awt/GLCanvas.java | 184 | ||||
-rw-r--r-- | src/jogl/classes/javax/media/opengl/awt/GLJPanel.java | 246 |
8 files changed, 522 insertions, 403 deletions
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]); } } |