diff options
author | Sven Gothel <[email protected]> | 2010-10-29 03:30:25 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-10-29 03:30:25 +0200 |
commit | ef8da46af8ef42d04b9f0701f0d18e1277765d01 (patch) | |
tree | c5fd779e20de84de544669ef381c4756007a494d | |
parent | be82dc62e22bbbb76acd7af889908a272bda6d09 (diff) |
Promoted the shutdown hook from GLDrawableFactoryImpl to GLProfile.
Each GLDrawableFactory implementation provides a shutdownInstance() method,
issued by GLProfile.
8 files changed, 337 insertions, 225 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java index c0e554889..6837949d3 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java @@ -43,7 +43,6 @@ package com.jogamp.opengl.impl; import java.nio.*; import javax.media.nativewindow.*; import javax.media.opengl.*; -import java.security.*; /** Extends GLDrawableFactory with a few methods for handling typically software-accelerated offscreen rendering (Device @@ -53,6 +52,10 @@ import java.security.*; public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected static final boolean DEBUG = GLDrawableImpl.DEBUG; + protected GLDrawableFactoryImpl() { + super(); + } + /** * Returns the GLDynamicLookupHelper * @param profile if EGL/ES, profile <code>1</code> refers to ES1 and <code>2</code> to ES2, @@ -224,36 +227,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // protected abstract GLDrawableImpl getSharedDrawable(); protected abstract GLContextImpl getSharedContext(); - protected abstract void shutdown(); - - // Shutdown hook mechanism for the factory - private boolean factoryShutdownHookRegistered; - private Thread factoryShutdownHook; - private synchronized void registerFactoryShutdownHook() { - if (factoryShutdownHookRegistered) - return; - if (factoryShutdownHook == null) { - factoryShutdownHook = new Thread(new Runnable() { - public void run() { - synchronized (GLDrawableFactoryImpl.this) { - shutdown(); - } - } - }); - } - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - Runtime.getRuntime().addShutdownHook(factoryShutdownHook); - return null; - } - }); - factoryShutdownHookRegistered = true; - } - - protected GLDrawableFactoryImpl() { - super(); - registerFactoryShutdownHook(); - } protected void maybeDoSingleThreadedWorkaround(Runnable action) { if (Threading.isSingleThreaded() && diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java index 83e85b922..deb659ddf 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java @@ -111,7 +111,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } } - protected void shutdown() {} + protected void shutdownInstance() {} protected final GLDrawableImpl getSharedDrawable() { return null; } protected final GLContextImpl getSharedContext() { return null; } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java index 47e0e656f..f108ab327 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -84,7 +84,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } catch (JogampRuntimeException jre) { /* n/a .. */ } } - protected void shutdown() {} + protected void shutdownInstance() {} protected final GLDrawableImpl getSharedDrawable() { return null; } protected final GLContextImpl getSharedContext() { return null; } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java index eff01ca18..4a80990cb 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java @@ -39,13 +39,8 @@ package com.jogamp.opengl.impl.macosx.cgl.awt; -import java.lang.reflect.InvocationTargetException; -import java.nio.*; -import java.util.*; import javax.media.nativewindow.*; import javax.media.opengl.*; -import com.jogamp.opengl.impl.*; -import com.jogamp.opengl.impl.awt.*; import com.jogamp.opengl.impl.macosx.cgl.*; public class MacOSXAWTCGLDrawableFactory extends MacOSXCGLDrawableFactory { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java index 409e914b0..f59fb78c9 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java @@ -43,7 +43,6 @@ package com.jogamp.opengl.impl.windows.wgl; import java.nio.*; import java.util.*; import javax.media.nativewindow.*; -import javax.media.nativewindow.windows.*; import javax.media.opengl.*; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.*; @@ -118,7 +117,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { return sharedContext; } - protected void shutdown() { + protected void shutdownInstance() { if (DEBUG) { System.err.println("!!! Shutdown Shared:"); System.err.println("!!! CTX : "+sharedContext); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java index 2828a90f1..82f57f33e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java @@ -82,38 +82,11 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } catch (JogampRuntimeException jre) { /* n/a .. */ } // init shared resources .. + sharedResourcesRunner = new SharedResourcesRunner(); + sharedResourcesThread = new Thread(sharedResourcesRunner, Thread.currentThread().getName()+"-SharedResourcesRunner"); + sharedResourcesThread.start(); + sharedResourcesRunner.waitUntilInitialized(); - long tlsDisplay = X11Util.createThreadLocalDisplay(null); - X11Util.lockDefaultToolkit(tlsDisplay); // OK - try { - X11GraphicsDevice sharedDevice = new X11GraphicsDevice(tlsDisplay); - vendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); - isVendorATI = GLXUtil.isVendorATI(vendorName); - isVendorNVIDIA = GLXUtil.isVendorNVIDIA(vendorName); - sharedScreen = new X11GraphicsScreen(sharedDevice, 0); - sharedDrawable = new X11DummyGLXDrawable(sharedScreen, X11GLXDrawableFactory.this, GLProfile.getDefault()); - if(isVendorATI() && GLProfile.isAWTAvailable()) { - X11Util.markThreadLocalDisplayUncloseable(tlsDisplay); // failure to close with ATI and AWT usage - } - if(null==sharedScreen || null==sharedDrawable) { - throw new GLException("Couldn't init shared screen("+sharedScreen+")/drawable("+sharedDrawable+")"); - } - // We have to keep this within this thread, - // since we have a 'chicken-and-egg' problem otherwise on the <init> lock of this thread. - try{ - X11GLXContext ctx = (X11GLXContext) sharedDrawable.createContext(null); - ctx.makeCurrent(); - ctx.release(); - sharedContext = ctx; - } catch (Throwable t) { - throw new GLException("X11GLXDrawableFactory - Could not initialize shared resources", t); - } - if(null==sharedContext) { - throw new GLException("X11GLXDrawableFactory - Shared Context is null"); - } - } finally { - X11Util.unlockDefaultToolkit(tlsDisplay); // OK - } if (DEBUG) { System.err.println("!!! Vendor: "+vendorName+", ATI: "+isVendorATI+", NV: "+isVendorNVIDIA); System.err.println("!!! SharedScreen: "+sharedScreen); @@ -121,7 +94,124 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } } - private X11GraphicsScreen sharedScreen; + class SharedResourcesRunner implements Runnable { + boolean initialized = false; + boolean released = false; + boolean shouldRelease = false; + + public void waitUntilInitialized() { + synchronized (this) { + while (!this.initialized) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + } + } + + public void releaseAndWait() { + synchronized (this) { + this.shouldRelease = true; + this.notifyAll(); + + while (!this.released) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + } + } + + public void run() { + String threadName = Thread.currentThread().getName(); + synchronized (this) { + if (DEBUG) { + System.err.println(threadName+ " initializing START"); + } + long tlsDisplay = X11Util.createDisplay(null); + X11Util.lockDefaultToolkit(tlsDisplay); // OK + try { + X11GraphicsDevice sharedDevice = new X11GraphicsDevice(tlsDisplay); + vendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); + isVendorATI = GLXUtil.isVendorATI(vendorName); + isVendorNVIDIA = GLXUtil.isVendorNVIDIA(vendorName); + sharedScreen = new X11GraphicsScreen(sharedDevice, 0); + sharedDrawable = new X11DummyGLXDrawable(sharedScreen, X11GLXDrawableFactory.this, GLProfile.getDefault()); + /* if(isVendorATI() && GLProfile.isAWTAvailable()) { + X11Util.markDisplayUncloseable(tlsDisplay); // failure to close with ATI and AWT usage + } */ + if (null == sharedScreen || null == sharedDrawable) { + throw new GLException("Couldn't init shared screen(" + sharedScreen + ")/drawable(" + sharedDrawable + ")"); + } + // We have to keep this within this thread, + // since we have a 'chicken-and-egg' problem otherwise on the <init> lock of this thread. + try { + X11GLXContext ctx = (X11GLXContext) sharedDrawable.createContext(null); + ctx.makeCurrent(); + ctx.release(); + sharedContext = ctx; + } catch (Throwable t) { + throw new GLException("X11GLXDrawableFactory - Could not initialize shared resources", t); + } + if (null == sharedContext) { + throw new GLException("X11GLXDrawableFactory - Shared Context is null"); + } + } finally { + X11Util.unlockDefaultToolkit(tlsDisplay); // OK + } + + if (DEBUG) { + System.err.println(threadName+ " initializing DONE"); + } + initialized = true; + notifyAll(); + } + + if (DEBUG) { + System.err.println(threadName+ " release WAIT"); + } + + synchronized(this) { + while (!this.shouldRelease) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + if (DEBUG) { + System.err.println(threadName+ " release START"); + } + if (null != sharedContext) { + // may cause JVM SIGSEGV: sharedContext.destroy(); + sharedContext = null; + } + + if (null != sharedDrawable) { + // may cause JVM SIGSEGV: sharedDrawable.destroy(); + sharedDrawable = null; + } + if (null != sharedScreen) { + // may cause JVM SIGSEGV: + X11Util.closeDisplay(sharedScreen.getDevice().getHandle()); + sharedScreen = null; + } + + if (DEBUG) { + System.err.println(threadName+ " release END"); + } + released = true; + notifyAll(); + } + } + } + + Thread sharedResourcesThread = null; + SharedResourcesRunner sharedResourcesRunner=null; + private X11GraphicsScreen sharedScreen=null; + private X11DummyGLXDrawable sharedDrawable=null; + private X11GLXContext sharedContext=null; private String vendorName; private boolean isVendorATI; private boolean isVendorNVIDIA; @@ -130,9 +220,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { protected boolean isVendorATI() { return isVendorATI; } protected boolean isVendorNVIDIA() { return isVendorNVIDIA; } - private X11DummyGLXDrawable sharedDrawable=null; - private X11GLXContext sharedContext=null; - protected final GLDrawableImpl getSharedDrawable() { return sharedDrawable; } @@ -141,7 +228,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return sharedContext; } - protected void shutdown() { + protected void shutdownInstance() { if (DEBUG) { System.err.println("!!! Shutdown Shared:"); System.err.println("!!! CTX : "+sharedContext); @@ -149,22 +236,21 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { System.err.println("!!! Screen : "+sharedScreen); } - // don't free native resources from this point on, - // since we might be in a critical shutdown hook sequence + // may cause JVM SIGSEGV ? + // X11Util.closePendingDisplayConnections(); - if(null!=sharedContext) { - // may cause deadlock: sharedContext.destroy(); - sharedContext=null; - } + sharedResourcesRunner.releaseAndWait(); - if(null!=sharedDrawable) { - // may cause deadlock: sharedDrawable.destroy(); - sharedDrawable=null; + if(X11Util.getOpenDisplayConnectionNumber() > 0) { + System.err.println("X11GLXDrawableFactory.shutdown(): Open (no close attempt) X11 Display Connection"); + X11Util.dumpOpenDisplayConnections(); } - if(null!=sharedScreen) { - // may cause deadlock: X11Util.closeThreadLocalDisplay(sharedScreen.getDevice().getHandle()); - sharedScreen = null; + + if(X11Util.getPendingDisplayConnectionNumber()>0) { + System.err.println("X11GLXDrawableFactory.shutdown(): Pending X11 Display Connection"); + X11Util.dumpPendingDisplayConnections(); } + // don't close pending XDisplay, since this might be a different thread as the opener X11Util.shutdown( false, DEBUG ); } diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index f9f5f8324..d1bdcdda1 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -40,12 +40,17 @@ package javax.media.opengl; -import javax.media.nativewindow.*; - -import java.security.*; import com.jogamp.common.JogampRuntimeException; -import com.jogamp.common.util.*; -import com.jogamp.opengl.impl.*; +import com.jogamp.common.impl.Debug; +import com.jogamp.common.util.ReflectionUtil; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; /** <P> Provides a virtual machine- and operating system-independent mechanism for creating {@link GLDrawable}s. </P> @@ -69,10 +74,11 @@ import com.jogamp.opengl.impl.*; raising a {@link GLException}. The semantics of the rejection process are (unfortunately) left unspecified for now. The current implementation will cause a {@link GLException} to be raised - during the first repaint of the {@link GLCanvas} or {@link - GLJPanel} if the capabilities can not be met. Pbuffers are always - created immediately and their creation will fail with a {@link - GLException} if errors occur. </P> + during the first repaint of the {@link javax.media.opengl.awt.GLCanvas} or {@link + javax.media.opengl.awt.GLJPanel} if the capabilities can not be met.<br> + {@link javax.media.opengl.GLPbuffer} are always + created immediately and their creation will fail with a + {@link javax.media.opengl.GLException} if errors occur. </P> <P> The concrete GLDrawableFactory subclass instantiated by {@link #getFactory getFactory} can be changed by setting the system @@ -81,10 +87,6 @@ import com.jogamp.opengl.impl.*; */ public abstract class GLDrawableFactory { - /** Creates a new GLDrawableFactory instance. End users do not need - to call this method. */ - protected GLDrawableFactory() { - } private static final GLDrawableFactory eglFactory; private static final GLDrawableFactory nativeOSFactory; @@ -92,6 +94,8 @@ public abstract class GLDrawableFactory { static final String macosxFactoryClassNameCGL = "com.jogamp.opengl.impl.macosx.cgl.MacOSXCGLDrawableFactory"; static final String macosxFactoryClassNameAWTCGL = "com.jogamp.opengl.impl.macosx.cgl.awt.MacOSXAWTCGLDrawableFactory"; + protected static ArrayList/*<GLDrawableFactoryImpl>*/ glDrawableFactories = new ArrayList(); + /** * Instantiate singleton factories if available, EGLES1, EGLES2 and the OS native ones. */ @@ -146,6 +150,24 @@ public abstract class GLDrawableFactory { eglFactory = tmp; } + protected GLDrawableFactory() { + synchronized(glDrawableFactories) { + glDrawableFactories.add(this); + } + } + + protected static void shutdown() { + synchronized(glDrawableFactories) { + for(int i=0; i<glDrawableFactories.size(); i++) { + GLDrawableFactory factory = (GLDrawableFactory) glDrawableFactories.get(i); + factory.shutdownInstance(); + } + glDrawableFactories.clear(); + } + } + + protected abstract void shutdownInstance(); + /** * Returns the sole GLDrawableFactory instance. * diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index be5968409..233bebcb4 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -47,6 +47,7 @@ import com.jogamp.opengl.impl.DesktopGLDynamicLookupHelper; import java.util.HashMap; import java.util.Iterator; import java.security.*; +import java.util.ArrayList; import javax.media.opengl.fixedfunc.GLPointerFunc; import javax.media.nativewindow.NativeWindowFactory; @@ -63,6 +64,68 @@ public class GLProfile { public static final boolean DEBUG = Debug.debug("GLProfile"); + /** + * Static one time initialization of JOGL. + * <p> + * Applications shall call this methods <b>ASAP</b>, before any other UI invocation.<br> + * You may issue the call in your main function.<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> + * <P> + * Remark: NEWT is currently not affected by this behavior, ie always uses native multithreading.</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> + * <P> + * In case no explicit initialization was invoked and the implicit initialization didn't happen,<br> + * you may encounter the following exception: + * <pre> + * javax.media.opengl.GLException: No default profile available + * </pre></P> + * + * @param firstUIActionOnProcess Should be <code>true</code> if called before the first UI action of the running program, + * otherwise <code>false</code>. + */ + 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() { + public Object run() { + registerFactoryShutdownHook(); + initProfiles(firstUIActionOnProcess); + return null; + } + }); + + if(null==defaultGLProfile) { + throw new GLException("No profile available: "+array2String(GL_PROFILE_LIST_ALL)+", "+glAvailabilityToString()); + } + } + } + + /** + * Manual shutdown method, may be called after your last JOGL use + * within the running JVM.<br> + * This method is called via the JVM shutdown hook.<br> + * It releases all temporary created resources, ie issues {@link javax.media.opengl.GLDrawableFactory#shutdown()}.<br> + */ + public static synchronized void shutdown() { + if(initialized) { + initialized = false; + GLDrawableFactory.shutdown(); + } + } + // // Query platform available OpenGL implementation // @@ -77,16 +140,6 @@ public class GLProfile { public static final boolean isGL2ES1Available() { return null != mappedProfiles.get(GL2ES1); } public static final boolean isGL2ES2Available() { return null != mappedProfiles.get(GL2ES2); } - private static final void glAvailabilityToString(StringBuffer sb, int major, int profile) { - String str = GLContext.getGLVersionAvailable(major, profile); - if(null==str) { - throw new GLException("Internal Error"); - } - sb.append("["); - sb.append(str); - sb.append("]"); - } - public static final String glAvailabilityToString() { boolean avail; StringBuffer sb = new StringBuffer(); @@ -400,22 +453,52 @@ public class GLProfile { return usesNativeGLES2(profileImpl) || usesNativeGLES1(profileImpl); } - private static final String getGLImplBaseClassName(String profileImpl) { - if ( GL4bc.equals(profileImpl) || - GL4.equals(profileImpl) || - GL3bc.equals(profileImpl) || - GL3.equals(profileImpl) || - GL2.equals(profileImpl) ) { - return "com.jogamp.opengl.impl.gl4.GL4bc"; - } else if(GL2ES12.equals(profileImpl)) { - return "com.jogamp.opengl.impl.gl2es12.GL2ES12"; - } else if(GLES1.equals(profileImpl) || GL2ES1.equals(profileImpl)) { - return "com.jogamp.opengl.impl.es1.GLES1"; - } else if(GLES2.equals(profileImpl) || GL2ES2.equals(profileImpl)) { - return "com.jogamp.opengl.impl.es2.GLES2"; - } else { - throw new GLException("unsupported profile \"" + profileImpl + "\""); + /** @return {@link javax.media.nativewindow.NativeWindowFactory#isAWTAvailable()} and + JOGL's AWT part */ + public static boolean isAWTAvailable() { return isAWTAvailable; } + + public static String getGLTypeName(int type) { + switch (type) { + case GL.GL_UNSIGNED_BYTE: + return "GL_UNSIGNED_BYTE"; + case GL.GL_BYTE: + return "GL_BYTE"; + case GL.GL_UNSIGNED_SHORT: + return "GL_UNSIGNED_SHORT"; + case GL.GL_SHORT: + return "GL_SHORT"; + case GL.GL_FLOAT: + return "GL_FLOAT"; + case GL.GL_FIXED: + return "GL_FIXED"; + case javax.media.opengl.GL2ES2.GL_INT: + return "GL_INT"; + case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: + return "GL_UNSIGNED_INT"; + case javax.media.opengl.GL2.GL_DOUBLE: + return "GL_DOUBLE"; + case javax.media.opengl.GL2.GL_2_BYTES: + return "GL_2_BYTES"; + case javax.media.opengl.GL2.GL_3_BYTES: + return "GL_3_BYTES"; + case javax.media.opengl.GL2.GL_4_BYTES: + return "GL_4_BYTES"; + } + return null; + } + + public static String getGLArrayName(int array) { + switch(array) { + case GLPointerFunc.GL_VERTEX_ARRAY: + return "GL_VERTEX_ARRAY"; + case GLPointerFunc.GL_NORMAL_ARRAY: + return "GL_NORMAL_ARRAY"; + case GLPointerFunc.GL_COLOR_ARRAY: + return "GL_COLOR_ARRAY"; + case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: + return "GL_TEXTURE_COORD_ARRAY"; } + return null; } public final String getGLImplBaseClassName() { @@ -830,6 +913,10 @@ public class GLProfile { return "GLProfile[" + profile + "/" + profileImpl + "]"; } + static { + JVMUtil.initSingleton(); + } + // The intersection between desktop OpenGL and the union of the OpenGL ES profiles // This is here only to avoid having separate GL2ES1Impl and GL2ES2Impl classes private static final String GL2ES12 = "GL2ES12"; @@ -852,6 +939,12 @@ public class GLProfile { /** All GLProfiles */ private static /*final*/ HashMap/*<String, GLProfile>*/ mappedProfiles; + static boolean initialized = false; + + // Shutdown hook mechanism for the factory + private static boolean factoryShutdownHookRegistered = false; + private static Thread factoryShutdownHook = null; + /** * Tries the profiles implementation and native libraries. * Throws an GLException if no profile could be found at all. @@ -988,58 +1081,22 @@ public class GLProfile { } } - static { - JVMUtil.initSingleton(); - } - - static boolean initialized = false; - - /** - * Static one time initialization of JOGL. - * <p> - * Applications shall call this methods <b>ASAP</b>, before any other UI invocation.<br> - * You may issue the call in your main function.<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> - * <P> - * Remark: NEWT is currently not affected by this behavior, ie always uses native multithreading.</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> - * <P> - * In case no explicit initialization was invoked and the implicit initialization didn't happen,<br> - * you may encounter the following exception: - * <pre> - * javax.media.opengl.GLException: No default profile available - * </pre></P> - * - * @param firstUIActionOnProcess Should be <code>true</code> if called before the first UI action of the running program, - * otherwise <code>false</code>. - */ - 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() { - public Object run() { - initProfiles(firstUIActionOnProcess); - return null; - } - }); - - if(null==defaultGLProfile) { - throw new GLException("No profile available: "+array2String(GL_PROFILE_LIST_ALL)+", "+glAvailabilityToString()); - } + private static synchronized void registerFactoryShutdownHook() { + if (factoryShutdownHookRegistered) { + return; } + factoryShutdownHook = new Thread(new Runnable() { + public void run() { + GLDrawableFactory.shutdown(); + } + }); + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + Runtime.getRuntime().addShutdownHook(factoryShutdownHook); + return null; + } + }); + factoryShutdownHookRegistered = true; } private static void validateInitialization() { @@ -1064,6 +1121,16 @@ public class GLProfile { return msg.toString(); } + private static final void glAvailabilityToString(StringBuffer sb, int major, int profile) { + String str = GLContext.getGLVersionAvailable(major, profile); + if(null==str) { + throw new GLException("Internal Error"); + } + sb.append("["); + sb.append(str); + sb.append("]"); + } + private static HashMap computeProfileMap() { defaultGLProfile=null; HashMap/*<String, GLProfile>*/ _mappedProfiles = new HashMap(GL_PROFILE_LIST_ALL.length); @@ -1091,6 +1158,24 @@ public class GLProfile { return _mappedProfiles; } + private static final String getGLImplBaseClassName(String profileImpl) { + if ( GL4bc.equals(profileImpl) || + GL4.equals(profileImpl) || + GL3bc.equals(profileImpl) || + GL3.equals(profileImpl) || + GL2.equals(profileImpl) ) { + return "com.jogamp.opengl.impl.gl4.GL4bc"; + } else if(GL2ES12.equals(profileImpl)) { + return "com.jogamp.opengl.impl.gl2es12.GL2ES12"; + } else if(GLES1.equals(profileImpl) || GL2ES1.equals(profileImpl)) { + return "com.jogamp.opengl.impl.es1.GLES1"; + } else if(GLES2.equals(profileImpl) || GL2ES2.equals(profileImpl)) { + return "com.jogamp.opengl.impl.es2.GLES2"; + } else { + throw new GLException("unsupported profile \"" + profileImpl + "\""); + } + } + /** * Returns the profile implementation */ @@ -1149,54 +1234,6 @@ public class GLProfile { return null; } - /** @return {@link javax.media.nativewindow.NativeWindowFactory#isAWTAvailable()} and - JOGL's AWT part */ - public static boolean isAWTAvailable() { return isAWTAvailable; } - - public static String getGLTypeName(int type) { - switch (type) { - case GL.GL_UNSIGNED_BYTE: - return "GL_UNSIGNED_BYTE"; - case GL.GL_BYTE: - return "GL_BYTE"; - case GL.GL_UNSIGNED_SHORT: - return "GL_UNSIGNED_SHORT"; - case GL.GL_SHORT: - return "GL_SHORT"; - case GL.GL_FLOAT: - return "GL_FLOAT"; - case GL.GL_FIXED: - return "GL_FIXED"; - case javax.media.opengl.GL2ES2.GL_INT: - return "GL_INT"; - case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT: - return "GL_UNSIGNED_INT"; - case javax.media.opengl.GL2.GL_DOUBLE: - return "GL_DOUBLE"; - case javax.media.opengl.GL2.GL_2_BYTES: - return "GL_2_BYTES"; - case javax.media.opengl.GL2.GL_3_BYTES: - return "GL_3_BYTES"; - case javax.media.opengl.GL2.GL_4_BYTES: - return "GL_4_BYTES"; - } - return null; - } - - public static String getGLArrayName(int array) { - switch(array) { - case GLPointerFunc.GL_VERTEX_ARRAY: - return "GL_VERTEX_ARRAY"; - case GLPointerFunc.GL_NORMAL_ARRAY: - return "GL_NORMAL_ARRAY"; - case GLPointerFunc.GL_COLOR_ARRAY: - return "GL_COLOR_ARRAY"; - case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: - return "GL_TEXTURE_COORD_ARRAY"; - } - return null; - } - private GLProfile(String profile, String profileImpl) { this.profile = profile; this.profileImpl = profileImpl; |