aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/javax/media/opengl/GLContext.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/javax/media/opengl/GLContext.java')
-rw-r--r--src/jogl/classes/javax/media/opengl/GLContext.java1504
1 files changed, 1186 insertions, 318 deletions
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index e23fa74f9..9a4311772 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -42,16 +42,24 @@ package javax.media.opengl;
import java.nio.IntBuffer;
import java.util.HashMap;
-import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
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;
+import jogamp.opengl.GLContextShareSet;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.VersionNumberString;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
/** Abstraction for an OpenGL rendering context. In order to perform
OpenGL rendering, a context must be "made current" on the current
@@ -66,144 +74,331 @@ 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");
+
+ public static final boolean DEBUG = Debug.debug("GLContext");
public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
-
+ public static final boolean DEBUG_TRACE_SWITCH = DEBUG || TRACE_SWITCH;
+
+ /**
+ * If <code>true</code> (default), bootstrapping the available GL profiles
+ * will use the highest compatible GL context for each profile,
+ * hence skipping querying lower profiles if a compatible higher one is found:
+ * <ul>
+ * <li>4.2-core -> 4.2-core, 3.3-core</li>
+ * <li>4.2-comp -> 4.2-comp, 3.3-comp, 2</li>
+ * </ul>
+ * Otherwise the dedicated GL context would be queried and used:
+ * <ul>
+ * <li>4.2-core -> 4.2-core</li>
+ * <li>3.3-core -> 3.3-core</li>
+ * <li>4.2-comp -> 4.2-comp</li>
+ * <li>3.3-comp -> 3.3-comp</li>
+ * <li>3.0-comp -> 2</li>
+ * </ul>
+ * Using aliasing speeds up initialization about:
+ * <ul>
+ * <li>Linux x86_64 - Nvidia: 28%, 700ms down to 500ms</li>
+ * <li>Linux x86_64 - AMD : 40%, 1500ms down to 900ms</li>
+ * <p>
+ * Can be turned off with property <code>jogl.debug.GLContext.NoProfileAliasing</code>.
+ * </p>
+ */
+ public static final boolean PROFILE_ALIASING = !Debug.isPropertyDefined("jogl.debug.GLContext.NoProfileAliasing", true);
+
+ protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true);
+ protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true);
+
/** Reflects property jogl.debug.DebugGL. If true, the debug pipeline is enabled at context creation. */
- public final static boolean DEBUG_GL = Debug.isPropertyDefined("jogl.debug.DebugGL", true);
+ public static final boolean DEBUG_GL = Debug.isPropertyDefined("jogl.debug.DebugGL", true);
/** Reflects property jogl.debug.TraceGL. If true, the trace pipeline is enabled at context creation. */
- public final static boolean TRACE_GL = Debug.isPropertyDefined("jogl.debug.TraceGL", true);
-
- /** Indicates that the context was not made current during the last call to {@link #makeCurrent makeCurrent}. */
+ public static final boolean TRACE_GL = Debug.isPropertyDefined("jogl.debug.TraceGL", true);
+
+ /** Indicates that the context was not made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
public static final int CONTEXT_NOT_CURRENT = 0;
- /** Indicates that the context was made current during the last call to {@link #makeCurrent makeCurrent}. */
+ /** Indicates that the context was made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
public static final int CONTEXT_CURRENT = 1;
- /** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}. */
+ /** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
public static final int CONTEXT_CURRENT_NEW = 2;
- /** <code>ARB_create_context</code> related: created via ARB_create_context. Cache key value. */
+ /** Version 1.00, i.e. GLSL 1.00 for ES 2.0. */
+ public static final VersionNumber Version100 = new VersionNumber(1, 0, 0);
+ /** Version 1.10, i.e. GLSL 1.10 for GL 2.0. */
+ public static final VersionNumber Version110 = new VersionNumber(1, 10, 0);
+ /** Version 1.20, i.e. GLSL 1.20 for GL 2.1. */
+ public static final VersionNumber Version120 = new VersionNumber(1, 20, 0);
+ /** Version 1.30, i.e. GLSL 1.30 for GL 3.0. */
+ public static final VersionNumber Version130 = new VersionNumber(1, 30, 0);
+ /** Version 1.40, i.e. GLSL 1.40 for GL 3.1. */
+ public static final VersionNumber Version140 = new VersionNumber(1, 40, 0);
+ /** Version 1.50, i.e. GLSL 1.50 for GL 3.2. */
+ public static final VersionNumber Version150 = new VersionNumber(1, 50, 0);
+
+ /** Version 3.0. As an OpenGL version, it qualifies for desktop {@link #isGL2()} only, or ES 3.0. Or GLSL 3.00 for ES 3.0. */
+ public static final VersionNumber Version300 = new VersionNumber(3, 0, 0);
+
+ /** Version 3.1. As an OpenGL version, it qualifies for {@link #isGL3core()}, {@link #isGL3bc()} and {@link #isGL3()} */
+ public static final VersionNumber Version310 = new VersionNumber(3, 1, 0);
+
+ /** Version 3.2. As an OpenGL version, it qualifies for geometry shader */
+ public static final VersionNumber Version320 = new VersionNumber(3, 2, 0);
+
+ /** Version 4.3. As an OpenGL version, it qualifies for <code>GL_ARB_ES3_compatibility</code> */
+ public static final VersionNumber Version430 = new VersionNumber(4, 3, 0);
+
+ protected static final VersionNumber Version800 = new VersionNumber(8, 0, 0);
+
+ //
+ // Cached keys, bits [0..15]
+ //
+
+ /** Context option bits, full bit mask covering 16 bits [0..15], i.e. <code>0x0000FFFF</code>, {@value}. */
+ protected static final int CTX_IMPL_FULL_MASK = 0x0000FFFF;
+
+ /** Context option bits, cached bit mask covering 10 bits [0..9], i.e. <code>0x000003FF</code>, {@value}. Leaving 6 bits for non cached options, i.e. 10:6. */
+ protected static final int CTX_IMPL_CACHE_MASK = 0x000003FF;
+
+ /** <code>ARB_create_context</code> related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IS_ARB_CREATED = 1 << 0;
- /** <code>ARB_create_context</code> related: compatibility profile. Cache key value. */
+ /** <code>ARB_create_context</code> related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_PROFILE_COMPAT = 1 << 1;
- /** <code>ARB_create_context</code> related: core profile. Cache key value. */
+ /** <code>ARB_create_context</code> related: desktop core profile. Cache key value. See {@link #isGLCoreProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_PROFILE_CORE = 1 << 2;
- /** <code>ARB_create_context</code> related: ES profile. Cache key value. */
+ /** <code>ARB_create_context</code> related: ES profile. Cache key value. See {@link #isGLES()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_PROFILE_ES = 1 << 3;
- /** <code>ARB_create_context</code> related: flag forward compatible. Cache key value. */
+ /** <code>ARB_create_context</code> related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_OPTION_FORWARD = 1 << 4;
- /** <code>ARB_create_context</code> related: flag debug. Not a cache key. */
+ /** <code>ARB_create_context</code> related: flag debug. Cache key value. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
public static final int CTX_OPTION_DEBUG = 1 << 5;
-
- /** <code>GL_ARB_ES2_compatibility</code> implementation related: Context is compatible w/ ES2. Not a cache key. */
- protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
+ /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 6;
+
+ //
+ // Non cached keys, 6 bits [10..15]
+ //
- /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. */
- protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15;
-
- private static ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>();
+ /** <code>GL_ARB_ES2_compatibility</code> implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IMPL_ES2_COMPAT = 1 << 10;
- private HashMap<String, Object> attachedObjectsByString = new HashMap<String, Object>();
- private IntObjectHashMap attachedObjectsByInt = new IntObjectHashMap();
+ /** <code>GL_ARB_ES3_compatibility</code> implementation related: Context is compatible w/ ES3. Not a cache key. See {@link #isGLES3Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IMPL_ES3_COMPAT = 1 << 11;
- // RecursiveLock maintains a queue of waiting Threads, ensuring the longest waiting thread will be notified at unlock.
- protected RecursiveLock lock = LockFactory.createRecursiveLock();
+ /**
+ * Context supports basic FBO, details see {@link #hasBasicFBOSupport()}.
+ * Not a cache key.
+ * @see #hasBasicFBOSupport()
+ * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
+ */
+ protected static final int CTX_IMPL_FBO = 1 << 12;
+
+ /**
+ * Context supports <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points,
+ * see {@link #hasFP32CompatAPI()}.
+ * Not a cache key.
+ * @see #hasFP32CompatAPI()
+ * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
+ */
+ protected static final int CTX_IMPL_FP32_COMPAT_API = 1 << 13;
+
+ private static final ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>();
+
+ private final HashMap<String, Object> attachedObjects = new HashMap<String, Object>();
+
+ // RecursiveLock maintains a queue of waiting Threads, ensuring the longest waiting thread will be notified at unlock.
+ protected final RecursiveLock lock = LockFactory.createRecursiveLock();
/** The underlying native OpenGL context */
- protected long contextHandle;
+ protected volatile long contextHandle; // volatile: avoid locking for read-only access
protected GLContext() {
- resetStates();
+ resetStates(true);
}
-
- protected int ctxMajorVersion;
- protected int ctxMinorVersion;
+
+ protected VersionNumber ctxVersion;
protected int ctxOptions;
protected String ctxVersionString;
+ protected VersionNumberString ctxVendorVersion;
+ protected VersionNumber ctxGLSLVersion;
private int currentSwapInterval;
+ protected GLRendererQuirks glRendererQuirks;
+
+ /** Did the drawable association changed ? see {@link GLRendererQuirks#NoSetSwapIntervalPostRetarget} */
+ protected boolean drawableRetargeted;
- protected void resetStates() {
+ /**
+ * @param isInit true if called for class initialization, otherwise false (re-init or destruction).
+ */
+ protected void resetStates(boolean isInit) {
if (DEBUG) {
- System.err.println(getThreadName() + ": GLContext.resetStates()");
+ System.err.println(getThreadName() + ": GLContext.resetStates(isInit "+isInit+")");
// Thread.dumpStack();
}
- ctxMajorVersion=-1;
- ctxMinorVersion=-1;
+ ctxVersion = VersionNumberString.zeroVersion;
+ ctxVendorVersion = VersionNumberString.zeroVersion;
ctxOptions=0;
ctxVersionString=null;
- attachedObjectsByString.clear();
- attachedObjectsByInt.clear();
+ ctxGLSLVersion = VersionNumber.zeroVersion;
+ attachedObjects.clear();
contextHandle=0;
currentSwapInterval = -1;
+ glRendererQuirks = null;
+ drawableRetargeted = false;
+ }
+
+ /** Returns true if this GLContext is shared, otherwise false. */
+ public final boolean isShared() {
+ return GLContextShareSet.isShared(this);
+ }
+
+ /** Returns a new list of created GLContext shared with this GLContext. */
+ public final List<GLContext> getCreatedShares() {
+ return GLContextShareSet.getCreatedShares(this);
+ }
+
+ /** Returns a new list of destroyed GLContext shared with this GLContext. */
+ public final List<GLContext> getDestroyedShares() {
+ return GLContextShareSet.getDestroyedShares(this);
}
/**
- * Returns the GLDrawable to which this context may be used to
- * draw.
+ * Returns the instance of {@link GLRendererQuirks}, allowing one to determine workarounds.
+ * @return instance of {@link GLRendererQuirks} if context was made current once, otherwise <code>null</code>.
+ */
+ public final GLRendererQuirks getRendererQuirks() { return glRendererQuirks; }
+
+ /**
+ * Returns true if the <code>quirk</code> exist in {@link #getRendererQuirks()}, otherwise false.
+ * <p>
+ * Convenience method for:
+ * <pre>
+ * final GLRendererQuirks glrq = ctx.getRendererQuirks();
+ * boolean hasQuirk = null != glrq ? glrq.exist(quirk) : false ;
+ * </pre>
+ * </p>
+ * @param quirk the quirk to be tested, e.g. {@link GLRendererQuirks#NoDoubleBufferedPBuffer}.
+ * @throws IllegalArgumentException if the quirk is out of range
+ */
+ public final boolean hasRendererQuirk(int quirk) throws IllegalArgumentException {
+ return null != glRendererQuirks ? glRendererQuirks.exist(quirk) : false ;
+ }
+
+ /**
+ * Sets the read/write drawable for framebuffer operations.
+ * <p>
+ * If the arguments reflect the current state of this context
+ * this method is a no-operation and returns the old and current {@link GLDrawable}.
+ * </p>
+ * <p>
+ * If the context was current on this thread, it is being released before switching the drawable
+ * and made current afterwards. However the user shall take extra care that not other thread
+ * attempts to make this context current. Otherwise a race condition may happen.
+ * </p>
+ * @param readWrite The read/write drawable for framebuffer operations, maybe <code>null</code> to remove association.
+ * @param setWriteOnly Only change the write-drawable, if <code>setWriteOnly</code> is <code>true</code> and
+ * if the {@link #getGLReadDrawable() read-drawable} differs
+ * from the {@link #getGLDrawable() write-drawable}.
+ * Otherwise set both drawables, read and write.
+ * @return The previous read/write drawable
+ *
+ * @throws GLException in case <code>null</code> is being passed or
+ * this context is made current on another thread.
+ *
+ * @see #isGLReadDrawableAvailable()
+ * @see #setGLReadDrawable(GLDrawable)
+ * @see #getGLReadDrawable()
+ * @see #setGLDrawable(GLDrawable, boolean)
+ * @see #getGLDrawable()
+ */
+ public abstract GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly);
+
+ /**
+ * Returns the write-drawable this context uses for framebuffer operations.
+ * <p>
+ * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)},
+ * it equals to the write-drawable (default).
+ * </p>
+ * @see #setGLDrawable(GLDrawable, boolean)
+ * @see #setGLReadDrawable(GLDrawable)
*/
public abstract GLDrawable getGLDrawable();
/**
- * Return availability of GL read drawable.
- * @return true if a GL read drawable is supported with your driver, otherwise false.
+ * Query whether using a distinguished read-drawable is supported.
+ * @return true if using a read-drawable is supported with your driver/OS, otherwise false.
*/
public abstract boolean isGLReadDrawableAvailable();
/**
- * Set the read GLDrawable for read framebuffer operations.<br>
+ * Set the read-Drawable for read framebuffer operations.<br>
* The caller should query if this feature is supported via {@link #isGLReadDrawableAvailable()}.
+ * <p>
+ * If the context was current on this thread, it is being released before switching the drawable
+ * and made current afterwards. However the user shall take extra care that not other thread
+ * attempts to make this context current. Otherwise a race condition may happen.
+ * </p>
*
- * @param read the read GLDrawable for read framebuffer operations.
- * If null is passed, the default write drawable will be set.
+ * @param read the read-drawable for read framebuffer operations.
+ * If null is passed, the default write drawable will be set.
+ * @return the previous read-drawable
*
- * @throws GLException in case a read drawable is not supported
- * and the given drawable is not null and not equal to the internal write drawable.
+ * @throws GLException in case a read drawable is not supported or
+ * this context is made current on another thread.
*
* @see #isGLReadDrawableAvailable()
* @see #getGLReadDrawable()
*/
- public abstract void setGLReadDrawable(GLDrawable read);
+ public abstract GLDrawable setGLReadDrawable(GLDrawable read);
/**
- * Returns the read GLDrawable this context uses for read framebuffer operations.
+ * Returns the read-Drawable this context uses for read framebuffer operations.
+ * <p>
+ * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)},
+ * it equals to the write-drawable (default).
+ * </p>
* @see #isGLReadDrawableAvailable()
- * @see #setGLReadDrawable(javax.media.opengl.GLDrawable)
+ * @see #setGLReadDrawable(GLDrawable)
+ * @see #getGLReadDrawable()
*/
public abstract GLDrawable getGLReadDrawable();
/**
* Makes this GLContext current on the calling thread.
* <p>
+ * Recursive call to {@link #makeCurrent()} and hence {@link #release()} are supported.
+ * </p>
+ * <p>
* There are two return values that indicate success and one that
- * indicates failure. A return value of CONTEXT_CURRENT_NEW
- * indicates that that context has been made current, and that
- * this is the first time this context has been made current, or
- * that the state of the underlying context or drawable may have
- * changed since the last time this context was made current. In
- * this case, the application may wish to initialize the state. A
- * return value of CONTEXT_CURRENT indicates that the context has
- * been made currrent, with its previous state restored.
+ * indicates failure.
+ * </p>
+ * <p>
+ * A return value of {@link #CONTEXT_CURRENT_NEW}
+ * indicates that that context has been made current for the 1st time,
+ * or that the state of the underlying context or drawable has
+ * changed since the last time this context was current.
+ * In this case, the application may wish to initialize the render state.
+ * </p>
+ * <p>
+ * A return value of {@link #CONTEXT_CURRENT} indicates that the context has
+ * been made current, with its previous state restored.
* </p>
* <p>
* If the context could not be made current (for example, because
* the underlying drawable has not ben realized on the display) ,
- * a value of CONTEXT_NOT_CURRENT is returned.
+ * a value of {@link #CONTEXT_NOT_CURRENT} is returned.
* </p>
- * <p>
- * If the context is in use by another thread at the time of the
- * call, then if isSynchronized() is true the call will
- * block. If isSynchronized() is false, an exception will be
- * thrown and the context will remain current on the other thread.
+ * <p>
+ * This method is blocking, i.e. waits until another thread has
+ * released the context.
* </p>
* <p>
* The drawable's surface is being locked at entry
- * and unlocked at {@link #release()}
+ * and unlocked at {@link #release()}
* </p>
*
- * @return CONTEXT_CURRENT if the context was successfully made current
- * @return CONTEXT_CURRENT_NEW if the context was successfully made
- * current, but need to be initialized.
- *
- * @return CONTEXT_NOT_CURRENT if the context could not be made current.
+ * @return <ul>
+ * <li>{@link #CONTEXT_CURRENT_NEW} if the context was successfully made current the 1st time,</li>
+ * <li>{@link #CONTEXT_CURRENT} if the context was successfully made current,</li>
+ * <li>{@link #CONTEXT_NOT_CURRENT} if the context could not be made current.</li>
+ * </ul>
*
* @throws GLException if synchronization is disabled and the
* context is current on another thread, or because the context
@@ -215,8 +410,11 @@ public abstract class GLContext {
/**
* Releases control of this GLContext from the current thread.
* <p>
+ * Recursive call to {@link #release()} and hence {@link #makeCurrent()} are supported.
+ * </p>
+ * <p>
* The drawable's surface is being unlocked at exit,
- * assumed to be locked by {@link #makeCurrent()}.
+ * assumed to be locked by {@link #makeCurrent()}.
* </p>
*
* @throws GLException if the context had not previously been made
@@ -230,7 +428,7 @@ public abstract class GLContext {
* parameter indicates which groups of state variables are to be
* copied. <code>mask</code> contains the bitwise OR of the same
* symbolic names that are passed to the GL command {@link
- * GL#glPushAttrib glPushAttrib}. The single symbolic constant
+ * GL2#glPushAttrib glPushAttrib}. The single symbolic constant
* {@link GL2#GL_ALL_ATTRIB_BITS GL_ALL_ATTRIB_BITS} can be used to
* copy the maximum possible portion of rendering state. <P>
*
@@ -284,41 +482,66 @@ public abstract class GLContext {
* @return true if this GLContext is current on this thread
*/
public final boolean isCurrent() {
- return getCurrent() == this ;
+ return getCurrent() == this ;
}
/**
* @throws GLException if this GLContext is not current on this thread
*/
- public final void validateCurrent() throws GLException {
+ public final void validateCurrent() throws GLException {
if(getCurrent() != this) {
throw new GLException(getThreadName()+": This context is not current. Current context: "+getCurrent()+", this context "+this);
}
}
-
+
+ /** Returns a String representation of the {@link #makeCurrent()} result. */
+ public static final String makeCurrentResultToString(int res) {
+ switch(res) {
+ case CONTEXT_NOT_CURRENT: return "CONTEXT_NOT_CURRENT";
+ case CONTEXT_CURRENT: return "CONTEXT_CURRENT";
+ case CONTEXT_CURRENT_NEW: return "CONTEXT_NOT_CURRENT";
+ default: return "INVALID_VALUE";
+ }
+ }
+
/**
* Sets the thread-local variable returned by {@link #getCurrent}
* and has no other side-effects. For use by third parties adding
* new GLContext implementations; not for use by end users.
*/
protected static void setCurrent(GLContext cur) {
- if(TRACE_SWITCH) {
- System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - "+cur);
+ if( TRACE_SWITCH ) {
+ if(null == cur) {
+ System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - NULL");
+ } else {
+ System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - obj " + toHexString(cur.hashCode()) + ", ctx " + toHexString(cur.getHandle()));
+ }
}
currentContext.set(cur);
}
-
+
/**
* Destroys this OpenGL context and frees its associated
* 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>
+ * </p>
*/
public abstract void destroy();
/**
+ * Returns the implementing root GL instance of this GLContext's GL object,
+ * considering a wrapped pipelined hierarchy, see {@link GLBase#getDownstreamGL()}.
+ * @throws GLException if the root instance is not a GL implementation
+ * @see GLBase#getRootGL()
+ * @see GLBase#getDownstreamGL()
+ * @see #getGL()
+ * @see #setGL(GL)
+ */
+ public abstract GL getRootGL();
+
+ /**
* Returns the GL pipeline object for this GLContext.
*
* @return the aggregated GL instance, or null if this context was not yet made current.
@@ -333,12 +556,12 @@ public abstract class GLContext {
public abstract GL setGL(GL gl);
/**
- * Returns the native GL context handle
+ * Returns the underlying native OpenGL context handle
*/
public final long getHandle() { return contextHandle; }
- /**
- * Indicates whether the underlying OpenGL context has been created.
+ /**
+ * Indicates whether the underlying native OpenGL context has been created.
*/
public final boolean isCreated() {
return 0 != contextHandle;
@@ -347,44 +570,26 @@ public abstract class GLContext {
/**
* Returns the attached user object for the given name to this GLContext.
*/
- public final Object getAttachedObject(int name) {
- return attachedObjectsByInt.get(name);
- }
-
- /**
- * Returns the attached user object for the given name to this GLContext.
- */
public final Object getAttachedObject(String name) {
- return attachedObjectsByString.get(name);
- }
-
- /**
- * Sets the attached user object for the given name to this GLContext.
- * Returns the previously set object or null.
- */
- public final Object attachObject(int name, Object obj) {
- return attachedObjectsByInt.put(name, obj);
+ return attachedObjects.get(name);
}
- public final Object detachObject(int name) {
- return attachedObjectsByInt.remove(name);
- }
-
/**
* Sets the attached user object for the given name to this GLContext.
* Returns the previously set object or null.
*/
public final Object attachObject(String name, Object obj) {
- return attachedObjectsByString.put(name, obj);
+ return attachedObjects.put(name, obj);
}
public final Object detachObject(String name) {
- return attachedObjectsByString.remove(name);
+ return attachedObjects.remove(name);
}
-
+
/**
* Classname, GL, GLDrawable
*/
+ @Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
@@ -395,18 +600,21 @@ public abstract class GLContext {
}
public final StringBuilder append(StringBuilder sb) {
- sb.append("OpenGL ");
- sb.append(getGLVersionMajor());
- sb.append(".");
- sb.append(getGLVersionMinor());
- sb.append(", options 0x");
+ sb.append("Version ").append(getGLVersion()).append(" [GL ").append(getGLVersionNumber()).append(", vendor ").append(getGLVendorVersionNumber());
+ sb.append("], options 0x");
sb.append(Integer.toHexString(ctxOptions));
- sb.append(", ");
- sb.append(getGLVersion());
+ sb.append(", this ");
+ sb.append(toHexString(hashCode()));
sb.append(", handle ");
sb.append(toHexString(contextHandle));
- sb.append(", ");
+ sb.append(", isShared "+isShared()+", ");
sb.append(getGL());
+ sb.append(",\n\t quirks: ");
+ if(null != glRendererQuirks) {
+ glRendererQuirks.toString(sb);
+ } else {
+ sb.append("n/a");
+ }
if(getGLDrawable()!=getGLReadDrawable()) {
sb.append(",\n\tRead Drawable : ");
sb.append(getGLReadDrawable());
@@ -416,8 +624,6 @@ public abstract class GLContext {
sb.append(",\n\tDrawable: ");
sb.append(getGLDrawable());
}
- sb.append(", lock ");
- sb.append(lock.toString());
return sb;
}
@@ -433,7 +639,7 @@ public abstract class GLContext {
* javax.media.opengl.GL#glPolygonOffset(float,float)} is available).
*/
public abstract boolean isFunctionAvailable(String glFunctionName);
-
+
/**
* Returns true if the specified OpenGL extension can be
* successfully called using this GL context given the current host (OpenGL
@@ -445,10 +651,10 @@ public abstract class GLContext {
* "GL_VERTEX_PROGRAM_ARB").
*/
public abstract boolean isExtensionAvailable(String glExtensionName);
-
+
/** Returns the number of platform extensions */
public abstract int getPlatformExtensionCount();
-
+
/** Returns a non-null (but possibly empty) string containing the
space-separated list of available platform-dependent (e.g., WGL,
GLX) extensions. Can only be called while this context is
@@ -457,7 +663,7 @@ public abstract class GLContext {
/** Returns the number of OpenGL extensions */
public abstract int getGLExtensionCount();
-
+
/** Returns a non-null (but possibly empty) string containing the
space-separated list of available extensions.
Can only be called while this context is current.
@@ -479,8 +685,8 @@ public abstract class GLContext {
* @see GLAutoDrawable#setContextCreationFlags(int)
*/
public abstract void setContextCreationFlags(int flags);
-
- /**
+
+ /**
* Returns a valid OpenGL version string, ie<br>
* <pre>
* major.minor ([option]?[options,]*) - gl-version
@@ -509,7 +715,7 @@ public abstract class GLContext {
* <td>row 2, cell 1</td>
* <td>row 2, cell 2</td>
* </tr>
- * </table>
+ * </table>
*
* <table border="0">
* <tr><td></td> <td>ES2</td> <td><code>2.0 (ES profile, ES2 compatible, hardware) - 2.0 ES Profile</code></td></tr>
@@ -520,131 +726,495 @@ public abstract class GLContext {
* <tr><td>NV</td><td>GL3</td> <td><code>3.3 (Core profile, arb, hardware) - 3.3.0 NVIDIA 195.36.07.03</code></td></tr>
* <tr><td>NV</td><td>GL3bc</td> <td><code>3.3 (Compatibility profile, arb, hardware) - 3.3.0 NVIDIA 195.36.07.03</code></td></tr>
* <tr><td>NV</td><td>GL2</td> <td><code>3.0 (Compatibility profile, arb, ES2 compatible, hardware) - 3.0.0 NVIDIA 290.10</code></td></tr>
- * </table>
+ * </table>
*/
public final String getGLVersion() {
return ctxVersionString;
}
- public final int getGLVersionMajor() { return ctxMajorVersion; }
- public final int getGLVersionMinor() { return ctxMinorVersion; }
+ /**
+ * Returns this context OpenGL version.
+ * @see #getGLSLVersionNumber()
+ **/
+ public final VersionNumber getGLVersionNumber() { return ctxVersion; }
+ /**
+ * Returns the vendor's version, i.e. version number at the end of <code>GL_VERSION</code> not being the GL version.
+ * <p>
+ * In case no such version exists within <code>GL_VERSION</code>,
+ * the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+ * </p>
+ * <p>
+ * The vendor's version is usually the vendor's OpenGL driver version.
+ * </p>
+ */
+ public final VersionNumberString getGLVendorVersionNumber() { return ctxVendorVersion; }
public final boolean isGLCompatibilityProfile() { return ( 0 != ( CTX_PROFILE_COMPAT & ctxOptions ) ); }
public final boolean isGLCoreProfile() { return ( 0 != ( CTX_PROFILE_CORE & ctxOptions ) ); }
+ public final boolean isGLESProfile() { return ( 0 != ( CTX_PROFILE_ES & ctxOptions ) ); }
public final boolean isGLForwardCompatible() { return ( 0 != ( CTX_OPTION_FORWARD & ctxOptions ) ); }
public final boolean isGLDebugEnabled() { return ( 0 != ( CTX_OPTION_DEBUG & ctxOptions ) ); }
public final boolean isCreatedWithARBMethod() { return ( 0 != ( CTX_IS_ARB_CREATED & ctxOptions ) ); }
-
+
/**
- * @return true if this context is an ES2 context or implements
- * the extension <code>GL_ARB_ES2_compatibility</code>, otherwise false
+ * Returns the matching GLSL version number, queried by this context GL
+ * via {@link GL2ES2#GL_SHADING_LANGUAGE_VERSION} if &ge; ES2.0 or GL2.0,
+ * otherwise a static match is being utilized.
+ * <p>
+ * The context must have been current once,
+ * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+ * </p>
+ * <p>
+ * Examples w/ <code>major.minor</code>:
+ * <pre>
+ * 1.00 (ES 2.0), 3.00 (ES 3.0)
+ * 1.10 (GL 2.0), 1.20 (GL 2.1), 1.50 (GL 3.2),
+ * 3.30 (GL 3.3), 4.00 (GL 4.0), 4.10 (GL 4.1), 4.20 (GL 4.2)
+ * </pre >
+ * </p>
+ * <p>
+ * <i>Matching</i> could also refer to the maximum GLSL version usable by this context
+ * since <i>normal</i> GL implementations are capable of using a lower GLSL version as well.
+ * The latter is not true on OSX w/ a GL3 context.
+ * </p>
+ *
+ * @return GLSL version number if context has been made current at least once,
+ * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+ *
+ * @see #getGLVersionNumber()
+ */
+ public final VersionNumber getGLSLVersionNumber() {
+ return ctxGLSLVersion;
+ }
+
+ /**
+ * Returns the GLSL version string as to be used in a shader program, including a terminating newline '\n',
+ * i.e. for desktop
+ * <pre>
+ * #version 110
+ * ..
+ * #version 150
+ * #version 330
+ * ...
+ * </pre>
+ * And for ES:
+ * <pre>
+ * #version 100
+ * #version 300 es
+ * ..
+ * </pre>
+ * <p>
+ * If context has not been made current yet, a string of zero length is returned.
+ * </p>
+ * @see #getGLSLVersionNumber()
+ */
+ public final String getGLSLVersionString() {
+ if( ctxGLSLVersion.isZero() ) {
+ return "";
+ }
+ final int minor = ctxGLSLVersion.getMinor();
+ final String esSuffix = isGLES() && ctxGLSLVersion.compareTo(Version300) >= 0 ? " es" : "";
+ return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + esSuffix + "\n" ;
+ }
+
+ protected static final VersionNumber getStaticGLSLVersionNumber(int glMajorVersion, int glMinorVersion, int ctxOptions) {
+ if( 0 != ( CTX_PROFILE_ES & ctxOptions ) ) {
+ if( 3 == glMajorVersion ) {
+ return Version300; // ES 3.0 -> GLSL 3.00
+ } else if( 2 == glMajorVersion ) {
+ return Version100; // ES 2.0 -> GLSL 1.00
+ }
+ } else if( 1 == glMajorVersion ) {
+ return Version110; // GL 1.x -> GLSL 1.10
+ } else if( 2 == glMajorVersion ) {
+ switch ( glMinorVersion ) {
+ case 0: return Version110; // GL 2.0 -> GLSL 1.10
+ default: return Version120; // GL 2.1 -> GLSL 1.20
+ }
+ } else if( 3 == glMajorVersion && 2 >= glMinorVersion ) {
+ switch ( glMinorVersion ) {
+ case 0: return Version130; // GL 3.0 -> GLSL 1.30
+ case 1: return Version140; // GL 3.1 -> GLSL 1.40
+ default: return Version150; // GL 3.2 -> GLSL 1.50
+ }
+ }
+ // The new default: GL >= 3.3, ES >= 3.0
+ return new VersionNumber(glMajorVersion, glMinorVersion * 10, 0); // GL M.N -> GLSL M.N
+ }
+
+ /**
+ * @return true if this context is an ES2 context or implements
+ * the extension <code>GL_ARB_ES3_compatibility</code> or <code>GL_ARB_ES2_compatibility</code>, otherwise false
*/
public final boolean isGLES2Compatible() {
- return 0 != ( ctxOptions & CTX_IMPL_ES2_COMPAT ) ;
+ return 0 != ( ctxOptions & ( CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ) ) ;
}
-
+
+ /**
+ * Return true if this context is an ES3 context or implements
+ * the extension <code>GL_ARB_ES3_compatibility</code>, otherwise false.
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ */
+ public final boolean isGLES3Compatible() {
+ return 0 != ( ctxOptions & CTX_IMPL_ES3_COMPAT ) ;
+ }
+
+ /**
+ * @return true if impl. is a hardware rasterizer, otherwise false.
+ * @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile)
+ * @see GLProfile#isHardwareRasterizer()
+ */
+ public final boolean isHardwareRasterizer() {
+ return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
+ }
+
+ /**
+ * @return true if context supports GLSL, i.e. is either {@link #isGLES3()}, {@link #isGLES2()}, {@link #isGL3()} or {@link #isGL2()} <i>and</i> major-version > 1.
+ * @see GLProfile#hasGLSL()
+ */
public final boolean hasGLSL() {
- return isGL2ES2() ;
+ return isGLES3() ||
+ isGLES2() ||
+ isGL3() ||
+ isGL2() && ctxVersion.getMajor()>1 ;
+ }
+
+ /**
+ * Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>.
+ * <p>
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= 3.0 [core, compat] or implements the extensions
+ * <code>GL_ARB_ES2_compatibility</code>, <code>GL_ARB_framebuffer_object</code>, <code>GL_EXT_framebuffer_object</code> or <code>GL_OES_framebuffer_object</code>.
+ * </p>
+ * <p>
+ * Basic FBO support may only include one color attachment and no multisampling,
+ * as well as limited internal formats for renderbuffer.
+ * </p>
+ * @see #CTX_IMPL_FBO
+ */
+ public final boolean hasBasicFBOSupport() {
+ return 0 != ( ctxOptions & CTX_IMPL_FBO ) ;
+ }
+
+ /**
+ * Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>.
+ * <p>
+ * Full FBO is supported if the context is either GL >= 3.0 [ES, core, compat] or implements the extensions
+ * <code>ARB_framebuffer_object</code>, or all of
+ * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>,
+ * <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>.
+ * </p>
+ * <p>
+ * Full FBO support includes multiple color attachments and multisampling.
+ * </p>
+ */
+ public final boolean hasFullFBOSupport() {
+ return hasBasicFBOSupport() && !hasRendererQuirk(GLRendererQuirks.NoFullFBOSupport) &&
+ ( isGL3ES3() || // GL >= 3.0 [ES, core, compat]
+ isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
+ ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object*
+ isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
+ isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
+ isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil)
+ )
+ ) ;
}
-
+
+ /**
+ * Returns <code>true</code> if <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points available,
+ * otherwise <code>false</code>.
+ * @see #CTX_IMPL_FP32_COMPAT_API
+ */
+ public final boolean hasFP32CompatAPI() {
+ return 0 != ( ctxOptions & CTX_IMPL_FP32_COMPAT_API ) ;
+ }
+
+ /**
+ * Returns the maximum number of FBO RENDERBUFFER samples
+ * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false.
+ */
+ public final int getMaxRenderbufferSamples() {
+ if( hasFullFBOSupport() ) {
+ final GL gl = getGL();
+ final int[] val = new int[] { 0 } ;
+ try {
+ gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
+ final int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR == glerr) {
+ return val[0];
+ } else if(DEBUG) {
+ System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
+ }
+ } catch (GLException gle) { gle.printStackTrace(); }
+ }
+ return 0;
+ }
+
/** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns <code>true</code>. */
public boolean isNPOTTextureAvailable() {
- return isGL3() || isGLES2Compatible() || isExtensionAvailable(GL_ARB_texture_non_power_of_two);
+ return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
}
- private static final String GL_ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
-
+
public boolean isTextureFormatBGRA8888Available() {
- return isGL2GL3() ||
- isExtensionAvailable("GL_EXT_texture_format_BGRA8888") ||
- isExtensionAvailable("GL_IMG_texture_format_BGRA8888") ;
+ return isGL2GL3() ||
+ isExtensionAvailable(GLExtensions.EXT_texture_format_BGRA8888) ||
+ isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ;
}
+ /**
+ * Indicates whether this GLContext is capable of GL4bc. <p>Includes [ GL4bc ].</p>
+ * @see GLProfile#isGL4bc()
+ */
public final boolean isGL4bc() {
- return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
+ return 0 != (ctxOptions & CTX_IS_ARB_CREATED) &&
+ 0 != (ctxOptions & CTX_PROFILE_COMPAT) &&
+ ctxVersion.getMajor() >= 4;
}
+ /**
+ * Indicates whether this GLContext is capable of GL4. <p>Includes [ GL4bc, GL4 ].</p>
+ * @see GLProfile#isGL4()
+ */
public final boolean isGL4() {
- return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
+ return 0 != (ctxOptions & CTX_IS_ARB_CREATED) &&
+ 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) &&
+ ctxVersion.getMajor() >= 4;
}
+ /**
+ * Indicates whether this GLContext uses a GL4 core profile. <p>Includes [ GL4 ].</p>
+ */
+ public final boolean isGL4core() {
+ return 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
+ 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.getMajor() >= 4;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL3bc. <p>Includes [ GL4bc, GL3bc ].</p>
+ * @see GLProfile#isGL3bc()
+ */
public final boolean isGL3bc() {
- return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
- && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
+ return 0 != (ctxOptions & CTX_IS_ARB_CREATED) &&
+ 0 != (ctxOptions & CTX_PROFILE_COMPAT) &&
+ ctxVersion.compareTo(Version310) >= 0 ;
}
+ /**
+ * Indicates whether this GLContext is capable of GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3 ].</p>
+ * @see GLProfile#isGL3()
+ */
public final boolean isGL3() {
- return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
- && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
+ return 0 != (ctxOptions & CTX_IS_ARB_CREATED) &&
+ 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) &&
+ ctxVersion.compareTo(Version310) >= 0 ;
+ }
+
+ /**
+ * Indicates whether this GLContext uses a GL3 core profile. <p>Includes [ GL4, GL3 ].</p>
+ */
+ public final boolean isGL3core() {
+ return 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
+ 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version310) >= 0;
+ }
+
+ /**
+ * Indicates whether this GLContext uses a GL core profile. <p>Includes [ GL4, GL3, GLES3, GLES2 ].</p>
+ */
+ public final boolean isGLcore() {
+ return ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 2 ) ||
+ ( 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
+ 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version310) >= 0
+ ) ;
+ }
+
+ /**
+ * Indicates whether this GLContext allows CPU data sourcing (indices, vertices ..) as opposed to using a GPU buffer source (VBO),
+ * e.g. {@link GL2#glDrawElements(int, int, int, java.nio.Buffer)}.
+ * <p>Includes [GL2ES1, GLES2] == [ GL4bc, GL3bc, GL2, GLES1, GL2ES1, GLES2 ].</p>
+ * <p>See Bug 852 - https://jogamp.org/bugzilla/show_bug.cgi?id=852 </p>
+ */
+ public final boolean isCPUDataSourcingAvail() {
+ return isGL2ES1() || isGLES2();
}
+ /**
+ * Indicates whether this GLContext's native profile does not implement a default <i>vertex array object</i> (VAO),
+ * starting w/ OpenGL 3.1 core and GLES3.
+ * <p>Includes [ GL4, GL3, GLES3 ].</p>
+ * <pre>
+ Due to GL 3.1 core spec: E.1. DEPRECATED AND REMOVED FEATURES (p 296),
+ GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331)
+ there is no more default VAO buffer 0 bound, hence generating and binding one
+ to avoid INVALID_OPERATION at VertexAttribPointer.
+ More clear is GL 4.3 core spec: 10.4 (p 307).
+ * </pre>
+ * <pre>
+ GLES3 is included, since upcoming ES releases &gt; 3.0 may behave the same:
+ GL ES 3.0 spec F.1. Legacy Features (p 322).
+ * </pre>
+ * <p>
+ * If no default VAO is implemented in the native OpenGL profile,
+ * an own default VAO is being used, see {@link #getDefaultVAO()}.
+ * </p>
+ * @see #getDefaultVAO()
+ */
+ public final boolean hasNoDefaultVAO() {
+ return ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 3 ) ||
+ ( 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
+ 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
+ ctxVersion.compareTo(Version310) >= 0
+ ) ;
+ }
+
+ /**
+ * If this GLContext does not implement a default VAO, see {@link #hasNoDefaultVAO()},
+ * an <i>own default VAO</i> will be created and bound at context creation.
+ * <p>
+ * If this GLContext does implement a default VAO, i.e. {@link #hasNoDefaultVAO()}
+ * returns <code>false</code>, this method returns <code>0</code>.
+ * </p>
+ * <p>
+ * Otherwise this method returns the VAO object name
+ * representing this GLContext's <i>own default VAO</i>.
+ * </p>
+ * @see #hasNoDefaultVAO()
+ */
+ public abstract int getDefaultVAO();
+
+ /**
+ * Indicates whether this GLContext is capable of GL2. <p>Includes [ GL4bc, GL3bc, GL2 ].</p>
+ * @see GLProfile#isGL2()
+ */
public final boolean isGL2() {
- return ctxMajorVersion>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT);
+ return 0 != ( ctxOptions & CTX_PROFILE_COMPAT ) && ctxVersion.getMajor()>=1 ;
}
+ /**
+ * Indicates whether this GLContext is capable of GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p>
+ * @see GLProfile#isGL2GL3()
+ */
public final boolean isGL2GL3() {
return isGL2() || isGL3();
}
+ /**
+ * Indicates whether this GLContext is capable of GLES1. <p>Includes [ GLES1 ].</p>
+ * @see GLProfile#isGLES1()
+ */
public final boolean isGLES1() {
- return ctxMajorVersion==1 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
+ return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 1 ;
}
+ /**
+ * Indicates whether this GLContext is capable of GLES2. <p>Includes [ GLES2, GLES3 ].</p>
+ * @see GLProfile#isGLES2()
+ */
public final boolean isGLES2() {
- return ctxMajorVersion==2 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
+ if( 0 != ( ctxOptions & CTX_PROFILE_ES ) ) {
+ final int major = ctxVersion.getMajor();
+ return 2 == major || 3 == major;
+ }
+ return false;
}
+ /**
+ * Indicates whether this GLContext is capable of GLES3. <p>Includes [ GLES3 ].</p>
+ * @see GLProfile#isGLES3()
+ */
+ public final boolean isGLES3() {
+ return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 3 ;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GLES. <p>Includes [ GLES3, GLES1, GLES2 ].</p>
+ * @see GLProfile#isGLES()
+ */
public final boolean isGLES() {
return 0 != ( CTX_PROFILE_ES & ctxOptions ) ;
}
+ /**
+ * Indicates whether this GLContext is capable of GL2ES1. <p>Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].</p>
+ * @see GLProfile#isGL2ES1()
+ */
public final boolean isGL2ES1() {
- return isGL2() || isGLES1() ;
+ return isGLES1() || isGL2();
}
+ /**
+ * Indicates whether this GLContext is capable of GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GL2GL3, GL2ES2, GLES2 ].</p>
+ * @see GLProfile#isGL2ES2()
+ */
public final boolean isGL2ES2() {
- return isGL2GL3() || isGLES2() ;
+ return isGLES2() || isGL2GL3();
}
/**
- * Set the swap interval if the current context.
- * @param interval Should be &ge; 0. 0 Disables the vertical synchronisation,
+ * Indicates whether this GLContext is capable of GL2ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL3ES3, GL2, GL2GL3 ].</p>
+ * @see GLProfile#isGL2ES3()
+ * @see #isGL3ES3()
+ * @see #isGL2GL3()
+ */
+ public final boolean isGL2ES3() {
+ return isGL3ES3() || isGL2GL3();
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL3ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3 ].</p>
+ * @see GLProfile#isGL3ES3()
+ */
+ public final boolean isGL3ES3() {
+ return isGL4ES3() || isGL3();
+ }
+
+ /**
+ * Returns true if this profile is capable of GL4ES3, i.e. if {@link #isGLES3Compatible()} returns true.
+ * <p>Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]</p>
+ * @see GLProfile#isGL4ES3()
+ */
+ public final boolean isGL4ES3() {
+ return isGLES3Compatible() ;
+ }
+
+ /**
+ * Set the swap interval of the current context and attached drawable.
+ * @param interval Should be &ge; 0. 0 disables the vertical synchronization,
* where &ge; 1 is the number of vertical refreshes before a swap buffer occurs.
* A value &lt; 0 is ignored.
- * @return true if the operation was successful, otherwise false
- *
+ * @return true if the operation was successful, otherwise false
+ *
* @throws GLException if the context is not current.
*/
public final boolean setSwapInterval(int interval) throws GLException {
validateCurrent();
if(0<=interval) {
- if( setSwapIntervalImpl(interval) ) {
- currentSwapInterval = interval;
- return true;
+ if( !drawableRetargeted || !hasRendererQuirk(GLRendererQuirks.NoSetSwapIntervalPostRetarget) ) {
+ if( setSwapIntervalImpl(interval) ) {
+ currentSwapInterval = interval;
+ return true;
+ }
}
}
return false;
}
- protected boolean setSwapIntervalImpl(int interval) {
- return false;
- }
- /** Return the current swap interval.
+ protected boolean setSwapIntervalImpl(int interval) {
+ return false;
+ }
+ /** Return the current swap interval.
* <p>
* If the context has not been made current at all,
* the default value <code>-1</code> is returned.
* </p>
* <p>
- * The default value for a valid context is <code>1</code> for
- * an EGL based profile (ES1 or ES2) and <code>-1</code> (undefined)
- * for desktop.
+ * For a valid context the default value is <code>1</code>
+ * in case of an EGL based profile (ES1 or ES2) and <code>-1</code>
+ * (undefined) for desktop.
* </p>
*/
public final int getSwapInterval() {
- if(-1 == currentSwapInterval && this.isGLES()) {
- currentSwapInterval = 1;
- }
return currentSwapInterval;
}
protected final void setDefaultSwapInterval() {
@@ -652,9 +1222,9 @@ public abstract class GLContext {
currentSwapInterval = 1;
} else {
currentSwapInterval = -1;
- }
+ }
}
-
+
public final boolean queryMaxSwapGroups(int[] maxGroups, int maxGroups_offset,
int[] maxBarriers, int maxBarriers_offset) {
validateCurrent();
@@ -667,147 +1237,286 @@ public abstract class GLContext {
return joinSwapGroupImpl(group);
}
protected boolean joinSwapGroupImpl(int group) { /** nop per default .. **/ return false; }
- protected int currentSwapGroup = -1; // default: not set yet ..
+ protected int currentSwapGroup = -1; // default: not set yet ..
public int getSwapGroup() {
return currentSwapGroup;
}
public final boolean bindSwapBarrier(int group, int barrier) {
validateCurrent();
- return bindSwapBarrierImpl(group, barrier);
+ return bindSwapBarrierImpl(group, barrier);
}
protected boolean bindSwapBarrierImpl(int group, int barrier) { /** nop per default .. **/ return false; }
-
/**
- * @return The extension implementing the GLDebugOutput feature,
- * either <i>GL_ARB_debug_output</i> or <i>GL_AMD_debug_output</i>.
- * If unavailable or called before initialized via {@link #makeCurrent()}, <i>null</i> is returned.
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ */
+ public abstract int getBoundFramebuffer(int target);
+
+ /**
+ * Return the default draw framebuffer name.
+ * <p>
+ * May differ from it's default <code>zero</code>
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
+ * is being used.
+ * </p>
+ */
+ public abstract int getDefaultDrawFramebuffer();
+
+ /**
+ * Return the default read framebuffer name.
+ * <p>
+ * May differ from it's default <code>zero</code>
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
+ * is being used.
+ * </p>
+ */
+ public abstract int getDefaultReadFramebuffer();
+
+ /**
+ * Returns the default color buffer within the current bound
+ * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​,
+ * which will be used as the source for pixel reading commands,
+ * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} etc.
+ * <p>
+ * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
+ * otherwise this is {@link GL#GL_FRONT} for single buffer configurations
+ * and {@link GL#GL_BACK} for double buffer configurations.
+ * </p>
+ * <p>
+ * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+ * and {@link GL#GL_BACK} is the default.
+ * </p>
+ * <p>
+ * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i
+ * </p>
+ * <p>
+ * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead}
+ * for read-pixels and swap-buffers implications.
+ * </p>
+ */
+ public abstract int getDefaultReadBuffer();
+
+ /** Get the default pixel data type, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}. */
+ public abstract int getDefaultPixelDataType();
+
+ /** Get the default pixel data format, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}. */
+ public abstract int getDefaultPixelDataFormat();
+
+ /**
+ * @return The extension implementing the GLDebugOutput feature,
+ * either {@link GLExtensions#ARB_debug_output} or {@link GLExtensions#AMD_debug_output}.
+ * If unavailable or called before initialized via {@link #makeCurrent()}, <i>null</i> is returned.
*/
public abstract String getGLDebugMessageExtension();
/**
- * @return the current synchronous debug behavior via
- * @see #setSynchronous(boolean)
+ * @return the current synchronous debug behavior, set via {@link #setGLDebugSynchronous(boolean)}.
*/
public abstract boolean isGLDebugSynchronous();
-
+
/**
* Enables or disables the synchronous debug behavior via
- * {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB glEnable/glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB)},
- * if extension is {@link #GL_ARB_debug_output}.
- * There is no equivalent for {@link #GL_AMD_debug_output}.
- * <p> The default is <code>true</code>, ie {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB}.</p>
+ * {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS glEnable/glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS)},
+ * if extension is {@link GLExtensions#ARB_debug_output}.
+ * There is no equivalent for {@link GLExtensions#AMD_debug_output}.
+ * <p> The default is <code>true</code>, ie {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS}.</p>
+ * @link {@link #isGLDebugSynchronous()}
*/
public abstract void setGLDebugSynchronous(boolean synchronous);
-
+
/**
* @return true if the GLDebugOutput feature is enabled or not.
*/
public abstract boolean isGLDebugMessageEnabled();
-
+
/**
- * Enables or disables the GLDebugOutput feature of extension <i>GL_ARB_debug_output</i>
- * or <i>GL_AMD_debug_output</i>, if available.
- *
+ * Enables or disables the GLDebugOutput feature of extension {@link GLExtensions#ARB_debug_output}
+ * or {@link GLExtensions#AMD_debug_output}, if available.
+ *
* <p>To enable the GLDebugOutput feature {@link #enableGLDebugMessage(boolean) enableGLDebugMessage(true)}
* or {@link #setContextCreationFlags(int) setContextCreationFlags}({@link GLContext#CTX_OPTION_DEBUG})
* shall be called <b>before</b> context creation via {@link #makeCurrent()}!</p>
- *
- * <p>In case {@link GLAutoDrawable} are being used,
+ *
+ * <p>In case {@link GLAutoDrawable} are being used,
* {@link GLAutoDrawable#setContextCreationFlags(int) glAutoDrawable.setContextCreationFlags}({@link GLContext#CTX_OPTION_DEBUG})
* shall be issued before context creation via {@link #makeCurrent()}!</p>
- *
+ *
* <p>After context creation, the GLDebugOutput feature may be enabled or disabled at any time using this method.</p>
- *
+ *
* @param enable If true enables, otherwise disables the GLDebugOutput feature.
- *
+ *
* @throws GLException if this context is not current or GLDebugOutput registration failed (enable)
- *
+ *
* @see #setContextCreationFlags(int)
* @see #addGLDebugListener(GLDebugListener)
* @see GLAutoDrawable#setContextCreationFlags(int)
*/
public abstract void enableGLDebugMessage(boolean enable) throws GLException;
-
+
/**
* Add {@link GLDebugListener}.<br>
- *
- * @param listener {@link GLDebugListener} handling {@GLDebugMessage}s
- * @see #enableGLDebugMessage(boolean)
+ *
+ * @param listener {@link GLDebugListener} handling {@link GLDebugMessage}s
+ * @see #enableGLDebugMessage(boolean)
* @see #removeGLDebugListener(GLDebugListener)
*/
public abstract void addGLDebugListener(GLDebugListener listener);
-
+
/**
* Remove {@link GLDebugListener}.<br>
- *
- * @param listener {@link GLDebugListener} handling {@GLDebugMessage}s
- * @see #enableGLDebugMessage(boolean)
+ *
+ * @param listener {@link GLDebugListener} handling {@link GLDebugMessage}s
+ * @see #enableGLDebugMessage(boolean)
* @see #addGLDebugListener(GLDebugListener)
*/
public abstract void removeGLDebugListener(GLDebugListener listener);
-
+
/**
- * Generic entry for {@link GL2GL3#glDebugMessageControlARB(int, int, int, int, IntBuffer, boolean)}
+ * Generic entry for {@link GL2GL3#glDebugMessageControl(int, int, int, int, IntBuffer, boolean)}
* and {@link GL2GL3#glDebugMessageEnableAMD(int, int, int, IntBuffer, boolean)} of the GLDebugOutput feature.
- * @see #enableGLDebugMessage(boolean)
+ * @see #enableGLDebugMessage(boolean)
*/
public abstract void glDebugMessageControl(int source, int type, int severity, int count, IntBuffer ids, boolean enabled);
-
+
/**
- * Generic entry for {@link GL2GL3#glDebugMessageControlARB(int, int, int, int, int[], int, boolean)}
- * and {@link GL2GL3#glDebugMessageEnableAMD(int, int, int, int[], int, boolean)} of the GLDebugOutput feature.
- * @see #enableGLDebugMessage(boolean)
+ * Generic entry for {@link GL2GL3#glDebugMessageControl(int, int, int, int, int[], int, boolean)}
+ * and {@link GL2GL3#glDebugMessageEnableAMD(int, int, int, int[], int, boolean)} of the GLDebugOutput feature.
+ * @see #enableGLDebugMessage(boolean)
*/
public abstract void glDebugMessageControl(int source, int type, int severity, int count, int[] ids, int ids_offset, boolean enabled);
-
+
/**
- * Generic entry for {@link GL2GL3#glDebugMessageInsertARB(int, int, int, int, int, String)}
+ * Generic entry for {@link GL2GL3#glDebugMessageInsert(int, int, int, int, int, String)}
* and {@link GL2GL3#glDebugMessageInsertAMD(int, int, int, int, String)} of the GLDebugOutput feature.
- * @see #enableGLDebugMessage(boolean)
+ * @see #enableGLDebugMessage(boolean)
*/
public abstract void glDebugMessageInsert(int source, int type, int id, int severity, String buf);
-
+
public static final int GL_VERSIONS[][] = {
/* 0.*/ { -1 },
/* 1.*/ { 0, 1, 2, 3, 4, 5 },
/* 2.*/ { 0, 1 },
/* 3.*/ { 0, 1, 2, 3 },
- /* 4.*/ { 0, 1, 2 } };
+ /* 4.*/ { 0, 1, 2, 3, 4 } };
- public static final int getMaxMajor() {
- return GL_VERSIONS.length-1;
+ public static final int ES_VERSIONS[][] = {
+ /* 0.*/ { -1 },
+ /* 1.*/ { 0, 1 },
+ /* 2.*/ { 0 },
+ /* 3.*/ { 0 } };
+
+ public static final int getMaxMajor(int ctxProfile) {
+ return ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ? ES_VERSIONS.length-1 : GL_VERSIONS.length-1;
}
- public static final int getMaxMinor(int major) {
- if(1>major || major>=GL_VERSIONS.length) return -1;
- return GL_VERSIONS[major].length-1;
+ public static final int getMaxMinor(int ctxProfile, int major) {
+ if( 1>major ) {
+ return -1;
+ }
+ if( ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ) {
+ if( major>=ES_VERSIONS.length ) return -1;
+ return ES_VERSIONS[major].length-1;
+ } else {
+ if( major>=GL_VERSIONS.length ) return -1;
+ return GL_VERSIONS[major].length-1;
+ }
}
- public static final boolean isValidGLVersion(int major, int minor) {
- if(1>major || major>=GL_VERSIONS.length) return false;
- if(0>minor || minor>=GL_VERSIONS[major].length) return false;
+ /**
+ * Returns true, if the major.minor is not inferior to the lowest
+ * valid version and does not exceed the highest known major number by more than one.
+ * <p>
+ * The minor version number is ignored by the upper limit validation
+ * and the major version number may exceed by one.
+ * </p>
+ * <p>
+ * The upper limit check is relaxed since we don't want to cut-off
+ * unforseen new GL version since the release of JOGL.
+ * </p>
+ * <p>
+ * Hence it is important to iterate through GL version from the upper limit
+ * and {@link #decrementGLVersion(int, int[], int[])} until invalid.
+ * </p>
+ */
+ public static final boolean isValidGLVersion(int ctxProfile, int major, int minor) {
+ if( 1>major || 0>minor ) {
+ return false;
+ }
+ if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
+ if( major >= ES_VERSIONS.length + 1 ) return false;
+ } else {
+ if( major>=GL_VERSIONS.length + 1 ) return false;
+ }
return true;
}
- public static final boolean decrementGLVersion(int major[], int minor[]) {
- if(null==major || major.length<1 ||null==minor || minor.length<1) {
- throw new GLException("invalid array arguments");
- }
- int m = major[0];
- int n = minor[0];
- if(!isValidGLVersion(m, n)) return false;
-
- // decrement ..
- n -= 1;
- if(n < 0) {
- m -= 1;
- n = GL_VERSIONS[m].length-1;
+ /**
+ * Clip the given GL version to the maximum known valid version if exceeding.
+ * @return true if clipped, i.e. given value exceeds maximum, otherwise false.
+ */
+ public static final boolean clipGLVersion(int ctxProfile, int major[], int minor[]) {
+ final int m = major[0];
+ final int n = minor[0];
+
+ if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
+ if( m >= ES_VERSIONS.length ) {
+ major[0] = ES_VERSIONS.length - 1;
+ minor[0] = ES_VERSIONS[major[0]].length - 1;
+ return true;
+ }
+ if( n >= ES_VERSIONS[m].length ) {
+ minor[0] = ES_VERSIONS[m].length - 1;
+ return true;
+ }
+ } else if( m >= GL_VERSIONS.length ) { // !isES
+ major[0] = GL_VERSIONS.length - 1;
+ minor[0] = GL_VERSIONS[major[0]].length - 1;
+ return true;
+ } else if( n >= GL_VERSIONS[m].length ) { // !isES
+ minor[0] = GL_VERSIONS[m].length - 1;
+ return true;
}
- if(!isValidGLVersion(m, n)) return false;
- major[0]=m;
- minor[0]=n;
+ return false;
+ }
+ /**
+ * Decrement the given GL version by one
+ * and return true if still valid, otherwise false.
+ * <p>
+ * If the given version exceeds the maximum known valid version,
+ * it is {@link #clipGLVersion(int, int[], int[]) clipped} and
+ * true is returned.
+ * </p>
+ *
+ * @param ctxProfile
+ * @param major
+ * @param minor
+ * @return
+ */
+ public static final boolean decrementGLVersion(int ctxProfile, int major[], int minor[]) {
+ if( !clipGLVersion(ctxProfile, major, minor) ) {
+ int m = major[0];
+ int n = minor[0] - 1;
+ if(n < 0) {
+ if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
+ if( m >= 3 ) {
+ m -= 1;
+ } else {
+ m = 0; // major decr [1,2] -> 0
+ }
+ n = ES_VERSIONS[m].length-1;
+ } else {
+ m -= 1;
+ n = GL_VERSIONS[m].length-1;
+ }
+ }
+ if( !isValidGLVersion(ctxProfile, m, n) ) {
+ return false;
+ }
+ major[0]=m;
+ minor[0]=n;
+ }
return true;
}
@@ -832,48 +1541,53 @@ public abstract class GLContext {
//
/**
- * @see #getDeviceVersionAvailableKey(javax.media.nativewindow.AbstractGraphicsDevice, int, int)
+ * @see #getDeviceVersionAvailableKey(javax.media.nativewindow.AbstractGraphicsDevice, int, int)
*/
- protected static /*final*/ HashMap<String, Integer> deviceVersionAvailable = new HashMap<String, Integer>();
+ protected static final IdentityHashMap<String, Integer> deviceVersionAvailable = new IdentityHashMap<String, Integer>();
/**
* @see #getUniqueDeviceString(javax.media.nativewindow.AbstractGraphicsDevice)
*/
- private static /*final*/ HashSet<String> deviceVersionsAvailableSet = new HashSet<String>();
+ private static final IdentityHashMap<String, String> deviceVersionsAvailableSet = new IdentityHashMap<String, String>();
- protected static String getDeviceVersionAvailableKey(AbstractGraphicsDevice device, int major, int profile) {
- return device.getUniqueID() + "-" + toHexString(composeBits(major, profile, 0));
+ /** clears the device/context mappings as well as the GL/GLX proc address tables. */
+ protected static void shutdown() {
+ deviceVersionAvailable.clear();
+ deviceVersionsAvailableSet.clear();
+ GLContextImpl.shutdownImpl(); // well ..
}
protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) {
synchronized ( deviceVersionsAvailableSet ) {
- return deviceVersionsAvailableSet.contains(device.getUniqueID());
+ return deviceVersionsAvailableSet.containsKey(device.getUniqueID());
}
}
protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) {
synchronized ( deviceVersionsAvailableSet ) {
- String devKey = device.getUniqueID();
- if ( deviceVersionsAvailableSet.contains(devKey) ) {
+ final String devKey = device.getUniqueID();
+ if( null != deviceVersionsAvailableSet.put(devKey, devKey) ) {
throw new InternalError("Already set: "+devKey);
}
- deviceVersionsAvailableSet.add(devKey);
if (DEBUG) {
System.err.println(getThreadName() + ": createContextARB: SET mappedVersionsAvailableSet "+devKey);
+ System.err.println(GLContext.dumpAvailableGLVersions(null).toString());
}
}
}
-
- /** clears the device/context mappings as well as the GL/GLX proc address tables. */
- protected static void shutdown() {
- deviceVersionAvailable.clear();
- deviceVersionsAvailableSet.clear();
- GLContextImpl.shutdownImpl(); // well ..
+
+ /**
+ * Returns a unique String object using {@link String#intern()} for the given arguments,
+ * which object reference itself can be used as a key.
+ */
+ protected static String getDeviceVersionAvailableKey(AbstractGraphicsDevice device, int major, int profile) {
+ final String r = device.getUniqueID() + "-" + toHexString(composeBits(major, profile, 0));
+ return r.intern();
}
/**
- * Called by {@link jogamp.opengl.GLContextImpl#createContextARBMapVersionsAvailable} not intended to be used by
- * implementations. However, if {@link #createContextARB} is not being used within
+ * Called by {@link jogamp.opengl.GLContextImpl#createContextARBMapVersionsAvailable(int,int)} not intended to be used by
+ * implementations. However, if {@link jogamp.opengl.GLContextImpl#createContextARB(long, boolean)} is not being used within
* {@link javax.media.opengl.GLDrawableFactory#getOrCreateSharedContext(javax.media.nativewindow.AbstractGraphicsDevice)},
* GLProfile has to map the available versions.
*
@@ -889,12 +1603,47 @@ public abstract class GLContext {
validateProfileBits(profile, "profile");
validateProfileBits(resCtp, "resCtp");
- String key = getDeviceVersionAvailableKey(device, reqMajor, profile);
- Integer val = new Integer(composeBits(resMajor, resMinor, resCtp));
+ if(FORCE_NO_FBO_SUPPORT) {
+ resCtp &= ~CTX_IMPL_FBO ;
+ }
+ if(DEBUG) {
+ System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null));
+ // Thread.dumpStack();
+ }
+ final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, profile);
+ final Integer val = new Integer(composeBits(resMajor, resMinor, resCtp));
synchronized(deviceVersionAvailable) {
- val = deviceVersionAvailable.put( key, val );
+ return deviceVersionAvailable.put( objectKey, val );
}
- return val;
+ }
+
+ protected static StringBuilder dumpAvailableGLVersions(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ synchronized(deviceVersionAvailable) {
+ final Set<String> keys = deviceVersionAvailable.keySet();
+ boolean needsSeparator = false;
+ for(Iterator<String> i = keys.iterator(); i.hasNext(); ) {
+ if(needsSeparator) {
+ sb.append(Platform.getNewline());
+ }
+ final String key = i.next();
+ sb.append(key).append(": ");
+ final Integer valI = deviceVersionAvailable.get(key);
+ if(null != valI) {
+ final int bits32 = valI.intValue();
+ final int major = ( bits32 & 0xFF000000 ) >>> 24 ;
+ final int minor = ( bits32 & 0x00FF0000 ) >>> 16 ;
+ final int ctp = ( bits32 & 0x0000FFFF ) ;
+ sb.append(GLContext.getGLVersion(major, minor, ctp, null));
+ } else {
+ sb.append("n/a");
+ }
+ needsSeparator = true;
+ }
+ }
+ return sb;
}
/**
@@ -904,10 +1653,10 @@ public abstract class GLContext {
* @return the available GL version as encoded with {@link #composeBits(int, int, int), otherwise <code>null</code>
*/
protected static Integer getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int reqProfile) {
- String key = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
+ final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
Integer val;
synchronized(deviceVersionAvailable) {
- val = deviceVersionAvailable.get( key );
+ val = deviceVersionAvailable.get( objectKey );
}
return val;
}
@@ -919,55 +1668,109 @@ public abstract class GLContext {
* @param minor if not null, returns the used minor version
* @param ctp if not null, returns the used context profile
*/
- protected static boolean getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int reqProfile,
+ protected static boolean getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int reqProfile,
int[] major, int minor[], int ctp[]) {
- Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
+ final Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
if(null==valI) {
return false;
}
- int bits32 = valI.intValue();
+ final int bits32 = valI.intValue();
if(null!=major) {
- major[0] = ( bits32 & 0xFF000000 ) >> 24 ;
+ major[0] = ( bits32 & 0xFF000000 ) >>> 24 ;
}
if(null!=minor) {
- minor[0] = ( bits32 & 0x00FF0000 ) >> 16 ;
+ minor[0] = ( bits32 & 0x00FF0000 ) >>> 16 ;
}
if(null!=ctp) {
ctp[0] = ( bits32 & 0x0000FFFF ) ;
}
return true;
}
-
- /**
+
+ /**
* returns the highest GLProfile string regarding the implementation version and context profile bits.
* @throws GLException if version and context profile bits could not be mapped to a GLProfile
*/
- protected static String getGLProfile(int major, int minor, int ctp)
+ protected static String getGLProfile(int major, int minor, int ctp)
throws GLException {
- if(0 != ( CTX_PROFILE_COMPAT & ctp )) {
+ if(0 != ( CTX_PROFILE_COMPAT & ctp )) {
if(major >= 4) { return GLProfile.GL4bc; }
else if(major == 3 && minor >= 1) { return GLProfile.GL3bc; }
- else { return GLProfile.GL2; }
+ else { return GLProfile.GL2; }
} else if(0 != ( CTX_PROFILE_CORE & ctp )) {
if(major >= 4) { return GLProfile.GL4; }
- else if(major == 3 && minor >= 1) { return GLProfile.GL3; }
+ else if(major == 3 && minor >= 1) { return GLProfile.GL3; }
} else if(0 != ( CTX_PROFILE_ES & ctp )) {
- if(major == 2) { return GLProfile.GLES2; }
- else if(major == 1) { return GLProfile.GLES1; }
+ if(major == 3) { return GLProfile.GLES3; }
+ else if(major == 2) { return GLProfile.GLES2; }
+ else if(major == 1) { return GLProfile.GLES1; }
}
throw new GLException("Unhandled OpenGL version/profile: "+GLContext.getGLVersion(major, minor, ctp, null));
}
-
- /**
+
+ /**
+ * Returns the GLProfile's major version number at reqMajorCTP[0] and it's context property (CTP) at reqMajorCTP[1] for availability mapping request.
+ */
+ protected static final void getRequestMajorAndCompat(final GLProfile glp, int[/*2*/] reqMajorCTP) {
+ final GLProfile glpImpl = glp.getImpl();
+ if( glpImpl.isGL4() ) {
+ reqMajorCTP[0]=4;
+ } else if ( glpImpl.isGL3() || glpImpl.isGLES3() ) {
+ reqMajorCTP[0]=3;
+ } else if (glpImpl.isGLES1()) {
+ reqMajorCTP[0]=1;
+ } else /* if (glpImpl.isGL2() || glpImpl.isGLES2()) */ {
+ reqMajorCTP[0]=2;
+ }
+ if( glpImpl.isGLES() ) {
+ reqMajorCTP[1]=CTX_PROFILE_ES;
+ } else if( glpImpl.isGL2() ) { // incl GL3bc and GL4bc
+ reqMajorCTP[1]=CTX_PROFILE_COMPAT;
+ } else {
+ reqMajorCTP[1]=CTX_PROFILE_CORE;
+ }
+ }
+
+ /**
+ * @param device the device the context profile is being requested for
+ * @param GLProfile the GLProfile the context profile is being requested for
+ * @return the GLProfile's context property (CTP) if available, otherwise <code>0</code>
+ */
+ protected static final int getAvailableContextProperties(final AbstractGraphicsDevice device, final GLProfile glp) {
+ final int[] reqMajorCTP = new int[] { 0, 0 };
+ getRequestMajorAndCompat(glp, reqMajorCTP);
+
+ int _major[] = { 0 };
+ int _minor[] = { 0 };
+ int _ctp[] = { 0 };
+ if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1], _major, _minor, _ctp)) {
+ return _ctp[0];
+ }
+ return 0; // n/a
+ }
+
+ /**
+ * @param device the device the profile is being requested
* @param major Key Value either 1, 2, 3 or 4
* @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
- * @return the highest GLProfile string regarding the version and profile bits.
- * @throws GLException if version and context profile bits could not be mapped to a GLProfile
- */
- public static String getAvailableGLProfile(AbstractGraphicsDevice device, int reqMajor, int reqProfile)
+ * @return the highest GLProfile for the device regarding availability, version and profile bits.
+ */
+ protected static GLProfile getAvailableGLProfile(AbstractGraphicsDevice device, int reqMajor, int reqProfile)
+ throws GLException {
+ final String glpName = getAvailableGLProfileName(device, reqMajor, reqProfile);
+ return null != glpName ? GLProfile.get(device, glpName) : null;
+ }
+
+ /**
+ * @param device the device the profile is being requested
+ * @param major Key Value either 1, 2, 3 or 4
+ * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ * @return the highest GLProfile name for the device regarding availability, version and profile bits.
+ */
+ /* package */ static String getAvailableGLProfileName(AbstractGraphicsDevice device, int reqMajor, int reqProfile)
throws GLException {
int major[] = { 0 };
int minor[] = { 0 };
@@ -979,13 +1782,63 @@ public abstract class GLContext {
}
/**
+ * @param device the device the profile is being requested
+ * @param major Key Value either 1, 2, 3 or 4
+ * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ */
+ protected static String getAvailableGLVersionAsString(AbstractGraphicsDevice device, int major, int profile) {
+ int _major[] = { 0 };
+ int _minor[] = { 0 };
+ int _ctp[] = { 0 };
+ if(getAvailableGLVersion(device, major, profile, _major, _minor, _ctp)) {
+ return getGLVersion(_major[0], _minor[0], _ctp[0], null);
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if it is possible to create an <i>framebuffer object</i> (FBO).
+ * <p>
+ * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
+ * </p>
+ * <p>
+ * FBO support is queried as described in {@link #hasBasicFBOSupport()}.
+ * </p>
+ *
+ * @param device the device to request whether FBO is available for
+ * @param glp {@link GLProfile} to check for FBO capabilities
+ * @see GLContext#hasBasicFBOSupport()
+ */
+ public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) {
+ return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) );
+ }
+
+ /**
+ * @return <code>1</code> if using a hardware rasterizer, <code>0</code> if using a software rasterizer and <code>-1</code> if not determined yet.
+ * @see GLContext#isHardwareRasterizer()
+ * @see GLProfile#isHardwareRasterizer()
+ */
+ public static final int isHardwareRasterizer(AbstractGraphicsDevice device, GLProfile glp) {
+ final int r;
+ final int ctp = getAvailableContextProperties(device, glp);
+ if(0 == ctp) {
+ r = -1;
+ } else if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
+ r = 1;
+ } else {
+ r = 0;
+ }
+ return r;
+ }
+
+ /**
* @param device the device to request whether the profile is available for
* @param reqMajor Key Value either 1, 2, 3 or 4
* @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
* @param isHardware return value of one boolean, whether the profile is a hardware rasterizer or not
* @return true if the requested GL version is available regardless of a software or hardware rasterizer, otherwise false.
*/
- public static boolean isGLVersionAvailable(AbstractGraphicsDevice device, int reqMajor, int reqProfile, boolean isHardware[]) {
+ protected static boolean isGLVersionAvailable(AbstractGraphicsDevice device, int reqMajor, int reqProfile, boolean isHardware[]) {
Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
if(null==valI) {
return false;
@@ -1002,6 +1855,34 @@ public abstract class GLContext {
return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES, isHardware);
}
+ public static boolean isGLES3Available(AbstractGraphicsDevice device, boolean isHardware[]) {
+ return isGLVersionAvailable(device, 3, GLContext.CTX_PROFILE_ES, isHardware);
+ }
+
+ /**
+ * Returns true if a ES3 compatible profile is available,
+ * i.e. either a &ge; 4.3 context or a &ge; 3.1 context supporting <code>GL_ARB_ES3_compatibility</code>,
+ * otherwise false.
+ * <p>
+ * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * </p>
+ */
+ public static final boolean isGLES3CompatibleAvailable(AbstractGraphicsDevice device) {
+ int major[] = { 0 };
+ int minor[] = { 0 };
+ int ctp[] = { 0 };
+ boolean ok;
+
+ ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_ES, major, minor, ctp);
+ if( !ok ) {
+ ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, major, minor, ctp);
+ }
+ if( !ok ) {
+ ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_COMPAT, major, minor, ctp);
+ }
+ return 0 != ( ctp[0] & CTX_IMPL_ES3_COMPAT );
+ }
+
public static boolean isGL4bcAvailable(AbstractGraphicsDevice device, boolean isHardware[]) {
return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT, isHardware);
}
@@ -1022,21 +1903,7 @@ public abstract class GLContext {
return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT, isHardware);
}
- /**
- * @param major Key Value either 1, 2, 3 or 4
- * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
- */
- public static String getAvailableGLVersionAsString(AbstractGraphicsDevice device, int major, int profile) {
- int _major[] = { 0 };
- int _minor[] = { 0 };
- int _ctp[] = { 0 };
- if(getAvailableGLVersion(device, major, profile, _major, _minor, _ctp)) {
- return getGLVersion(_major[0], _minor[0], _ctp[0], null);
- }
- return null;
- }
-
- public static String getGLVersion(int major, int minor, int ctp, String gl_version) {
+ protected static String getGLVersion(int major, int minor, int ctp, String gl_version) {
boolean needColon = false;
StringBuilder sb = new StringBuilder();
sb.append(major);
@@ -1044,12 +1911,15 @@ public abstract class GLContext {
sb.append(minor);
sb.append(" (");
needColon = appendString(sb, "ES profile", needColon, 0 != ( CTX_PROFILE_ES & ctp ));
- needColon = appendString(sb, "Compatibility profile", needColon, 0 != ( CTX_PROFILE_COMPAT & ctp ));
+ needColon = appendString(sb, "Compat profile", needColon, 0 != ( CTX_PROFILE_COMPAT & ctp ));
needColon = appendString(sb, "Core profile", needColon, 0 != ( CTX_PROFILE_CORE & ctp ));
- needColon = appendString(sb, "forward", needColon, 0 != ( CTX_OPTION_FORWARD & ctp ));
+ needColon = appendString(sb, "forward", needColon, 0 != ( CTX_OPTION_FORWARD & ctp ));
needColon = appendString(sb, "arb", needColon, 0 != ( CTX_IS_ARB_CREATED & ctp ));
- needColon = appendString(sb, "debug", needColon, 0 != ( CTX_OPTION_DEBUG & ctp ));
- needColon = appendString(sb, "ES2 compatible", needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp ));
+ needColon = appendString(sb, "debug", needColon, 0 != ( CTX_OPTION_DEBUG & ctp ));
+ needColon = appendString(sb, "ES2 compat", needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp ));
+ needColon = appendString(sb, "ES3 compat", needColon, 0 != ( CTX_IMPL_ES3_COMPAT & ctp ));
+ needColon = appendString(sb, "FBO", needColon, 0 != ( CTX_IMPL_FBO & ctp ));
+ needColon = appendString(sb, "FP32 compat", needColon, 0 != ( CTX_IMPL_FP32_COMPAT_API & ctp ));
if( 0 != ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
needColon = appendString(sb, "software", needColon, true);
} else {
@@ -1064,9 +1934,9 @@ public abstract class GLContext {
}
//
- // internal string utils
+ // internal string utils
//
-
+
protected static String toHexString(int hex) {
return "0x" + Integer.toHexString(hex);
}
@@ -1085,10 +1955,8 @@ public abstract class GLContext {
}
return needColon;
}
-
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
}