ARB_create_context
related: created via ARB_create_context. Cache key value. */
protected static final int CTX_IS_ARB_CREATED = 1 << 0;
/** ARB_create_context
related: compatibility profile. Cache key value. */
protected static final int CTX_PROFILE_COMPAT = 1 << 1;
/** ARB_create_context
related: core profile. Cache key value. */
protected static final int CTX_PROFILE_CORE = 1 << 2;
/** ARB_create_context
related: ES profile. Cache key value. */
protected static final int CTX_PROFILE_ES = 1 << 3;
/** ARB_create_context
related: flag forward compatible. Cache key value. */
protected static final int CTX_OPTION_FORWARD = 1 << 4;
/** ARB_create_context
related: flag debug. Not a cache key. */
public static final int CTX_OPTION_DEBUG = 1 << 5;
/** GL_ARB_ES2_compatibility
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. */
protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15;
private static ThreadLocal* 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. *
** 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. *
** 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. *
** The drawable's surface is being locked at entry * and unlocked at {@link #release()} *
* * @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. * * @throws GLException if synchronization is disabled and the * context is current on another thread, or because the context * could not be created or made current due to non-recoverable, * window system-specific errors. */ public abstract int makeCurrent() throws GLException; /** * Releases control of this GLContext from the current thread. ** The drawable's surface is being unlocked at exit, * assumed to be locked by {@link #makeCurrent()}. *
* * @throws GLException if the context had not previously been made * current on the current thread */ public abstract void release() throws GLException; /** * Copies selected groups of OpenGL state variables from the * supplied source context into this one. Themask
* parameter indicates which groups of state variables are to be
* copied. mask
contains the bitwise OR of the same
* symbolic names that are passed to the GL command {@link
* GL#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. * * Not all values for GL state can be copied. For example, pixel * pack and unpack state, render mode state, and select and feedback * state are not copied. The state that can be copied is exactly the * state that is manipulated by the GL command {@link * GL2#glPushAttrib glPushAttrib}.
* * On most platforms, this context may not be current to any thread, * including the calling thread, when this method is called. Some * platforms have additional requirements such as whether this * context or the source context must occasionally be made current * in order for the results of the copy to be seen; these * requirements are beyond the scope of this specification. * * @param source the source OpenGL context from which to copy state * @param mask a mask of symbolic names indicating which groups of state to copy * @throws GLException if an OpenGL-related error occurred */ public abstract void copy(GLContext source, int mask) throws GLException; /** * Returns the GL object bound to this thread current context. * If no context is current, throw an GLException * * @return the current context's GL object on this thread * @throws GLException if no context is current */ public static GL getCurrentGL() throws GLException { GLContext glc = getCurrent(); if(null==glc) { throw new GLException(getThreadName()+": No OpenGL context current on this thread"); } return glc.getGL(); } /** * Returns this thread current context. * If no context is current, returns null. * * @return the context current on this thread, or null if no context * is current. */ public static GLContext getCurrent() { return currentContext.get(); } /** * @return true if this GLContext is current on this thread */ public final boolean isCurrent() { return getCurrent() == this ; } /** * @throws GLException if this GLContext is not current on this thread */ public final void validateCurrent() throws GLException { if(getCurrent() != this) { throw new GLException(getThreadName()+": This context is not current. Current context: "+getCurrent()+", this context "+this); } } /** * 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); } currentContext.set(cur); } /** * Destroys this OpenGL context and frees its associated * resources. *
* The context may be current w/o recursion when calling destroy()
,
* in which case this method destroys the context and releases the lock.
*
* major.minor ([option]?[options,]*) - gl-version *
ES profile
ES profileCompatibility profile
Compatibility profile including fixed function pipeline and deprecated functionalityCore profile
Core profileforward
Forward profile excluding deprecated functionalityarb
refers to an ARB_create_context created contextdebug
refers to a debug contextES2 compatible
refers to an ES2 compatible implementationsoftware
refers to a software implementation of the rasterizerhardware
refers to a hardware implementation of the rasterizerrow 2, cell 1 | *row 2, cell 2 | *
ES2 | 2.0 (ES profile, ES2 compatible, hardware) - 2.0 ES Profile | |
ATI | GL2 | 3.0 (Compatibility profile, arb, hardware) - 3.2.9704 Compatibility Profile Context |
ATI | GL3 | 3.3 (Core profile, any, new, hardware) - 1.4 (3.2.9704 Compatibility Profile Context) |
ATI | GL3bc | 3.3 (Compatibility profile, arb, hardware) - 1.4 (3.2.9704 Compatibility Profile Context) |
NV | GL2 | 3.0 (Compatibility profile, arb, hardware) - 3.0.0 NVIDIA 195.36.07.03 |
NV | GL3 | 3.3 (Core profile, arb, hardware) - 3.3.0 NVIDIA 195.36.07.03 |
NV | GL3bc | 3.3 (Compatibility profile, arb, hardware) - 3.3.0 NVIDIA 195.36.07.03 |
NV | GL2 | 3.0 (Compatibility profile, arb, ES2 compatible, hardware) - 3.0.0 NVIDIA 290.10 |
GL_ARB_ES2_compatibility
, otherwise false
*/
public final boolean isGLES2Compatible() {
return 0 != ( ctxOptions & CTX_IMPL_ES2_COMPAT ) ;
}
public final boolean hasGLSL() {
return isGL2ES2() ;
}
/** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns true
. */
public boolean isNPOTTextureAvailable() {
return isGL3() || isGLES2Compatible() || isExtensionAvailable(GL_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") ;
}
public final boolean isGL4bc() {
return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & CTX_PROFILE_COMPAT);
}
public final boolean isGL4() {
return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
}
public final boolean isGL3bc() {
return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
&& 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & CTX_PROFILE_COMPAT);
}
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));
}
public final boolean isGL2() {
return ctxMajorVersion>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT);
}
public final boolean isGL2GL3() {
return isGL2() || isGL3();
}
public final boolean isGLES1() {
return ctxMajorVersion==1 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
}
public final boolean isGLES2() {
return ctxMajorVersion==2 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
}
public final boolean isGLES() {
return 0 != ( CTX_PROFILE_ES & ctxOptions ) ;
}
public final boolean isGL2ES1() {
return isGL2() || isGLES1() ;
}
public final boolean isGL2ES2() {
return isGL2GL3() || isGLES2() ;
}
/**
* Set the swap interval if the current context.
* @param interval Should be ≥ 0. 0 Disables the vertical synchronisation,
* where ≥ 1 is the number of vertical refreshes before a swap buffer occurs.
* A value < 0 is ignored.
* @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;
}
}
return false;
}
protected boolean setSwapIntervalImpl(int interval) {
return false;
}
/** Return the current swap interval.
*
* If the context has not been made current at all,
* the default value -1
is returned.
*
* The default value for a valid context is 1
for
* an EGL based profile (ES1 or ES2) and -1
(undefined)
* for desktop.
*
The default is true
, ie {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB}.
To enable the GLDebugOutput feature {@link #enableGLDebugMessage(boolean) enableGLDebugMessage(true)} * or {@link #setContextCreationFlags(int) setContextCreationFlags}({@link GLContext#CTX_OPTION_DEBUG}) * shall be called before context creation via {@link #makeCurrent()}!
* *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()}!
* *After context creation, the GLDebugOutput feature may be enabled or disabled at any time using this method.
* * @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}.null
*/
protected static Integer getAvailableGLVersion(AbstractGraphicsDevice device, int reqMajor, int reqProfile) {
String key = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
Integer val;
synchronized(deviceVersionAvailable) {
val = deviceVersionAvailable.get( key );
}
return val;
}
/**
* @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 major if not null, returns the used major version
* @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,
int[] major, int minor[], int ctp[]) {
Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
if(null==valI) {
return false;
}
int bits32 = valI.intValue();
if(null!=major) {
major[0] = ( bits32 & 0xFF000000 ) >> 24 ;
}
if(null!=minor) {
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)
throws GLException {
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 if(0 != ( CTX_PROFILE_CORE & ctp )) {
if(major >= 4) { return GLProfile.GL4; }
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; }
}
throw new GLException("Unhandled OpenGL version/profile: "+GLContext.getGLVersion(major, minor, ctp, null));
}
/**
* @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)
throws GLException {
int major[] = { 0 };
int minor[] = { 0 };
int ctp[] = { 0 };
if(GLContext.getAvailableGLVersion(device, reqMajor, reqProfile, major, minor, ctp)) {
return GLContext.getGLProfile(major[0], minor[0], ctp[0]);
}
return null;
}
/**
* @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[]) {
Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
if(null==valI) {
return false;
}
isHardware[0] = 0 == ( valI.intValue() & GLContext.CTX_IMPL_ACCEL_SOFT ) ;
return true;
}
public static boolean isGLES1Available(AbstractGraphicsDevice device, boolean isHardware[]) {
return isGLVersionAvailable(device, 1, GLContext.CTX_PROFILE_ES, isHardware);
}
public static boolean isGLES2Available(AbstractGraphicsDevice device, boolean isHardware[]) {
return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES, isHardware);
}
public static boolean isGL4bcAvailable(AbstractGraphicsDevice device, boolean isHardware[]) {
return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT, isHardware);
}
public static boolean isGL4Available(AbstractGraphicsDevice device, boolean isHardware[]) {
return isGLVersionAvailable(device, 4, CTX_PROFILE_CORE, isHardware);
}
public static boolean isGL3bcAvailable(AbstractGraphicsDevice device, boolean isHardware[]) {
return isGLVersionAvailable(device, 3, CTX_PROFILE_COMPAT, isHardware);
}
public static boolean isGL3Available(AbstractGraphicsDevice device, boolean isHardware[]) {
return isGLVersionAvailable(device, 3, CTX_PROFILE_CORE, isHardware);
}
public static boolean isGL2Available(AbstractGraphicsDevice device, boolean isHardware[]) {
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) {
boolean needColon = false;
StringBuilder sb = new StringBuilder();
sb.append(major);
sb.append(".");
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, "Core profile", needColon, 0 != ( CTX_PROFILE_CORE & 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 ));
if( 0 != ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
needColon = appendString(sb, "software", needColon, true);
} else {
needColon = appendString(sb, "hardware", needColon, true);
}
sb.append(")");
if(null!=gl_version) {
sb.append(" - ");
sb.append(gl_version);
}
return sb.toString();
}
//
// internal string utils
//
protected static String toHexString(int hex) {
return "0x" + Integer.toHexString(hex);
}
protected static String toHexString(long hex) {
return "0x" + Long.toHexString(hex);
}
private static boolean appendString(StringBuilder sb, String string, boolean needColon, boolean condition) {
if(condition) {
if(needColon) {
sb.append(", ");
}
sb.append(string);
needColon=true;
}
return needColon;
}
protected static String getThreadName() {
return Thread.currentThread().getName();
}
}