From 78b4918b207e16b967e8335fb8ec1b31c706c507 Mon Sep 17 00:00:00 2001
From: Sven Gothel
+ * Can be turned off with property
+ * Returns this GLContext, if it is a shared master.
+ *
+ * Convenience method for:
+ * true
(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:
+ *
+ *
+ * Otherwise the dedicated GL context would be queried and used:
+ *
+ *
+ * Using aliasing speeds up initialization about:
+ *
+ *
jogl.debug.GLContext.NoProfileAliasing
.
+ * GL_ARB_ES3_compatibility
*/
+ public static final VersionNumber Version4_3 = new VersionNumber(4, 3, 0);
+
+ protected static final VersionNumber Version8_0 = new VersionNumber(8, 0, 0);
+
+ private static final String S_EMPTY = "";
+
+ //
+ // Cached keys, bits [0..15]
+ //
+
+ /** Context option bits, full bit mask covering 16 bits [0..15], i.e. 0x0000FFFF
, {@value}. */
+ protected static final int CTX_IMPL_FULL_MASK = 0x0000FFFF;
+
+ /** Context option bits, cached bit mask covering 10 bits [0..9], i.e. 0x000003FF
, {@value}. Leaving 6 bits for non cached options, i.e. 10:6. */
+ protected static final int CTX_IMPL_CACHE_MASK = 0x000003FF;
+
+ /** ARB_create_context
related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_IS_ARB_CREATED = 1 << 0;
+ /** ARB_create_context
related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_PROFILE_COMPAT = 1 << 1;
+ /** ARB_create_context
related: desktop core profile. Cache key value. See {@link #isGLCoreProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_PROFILE_CORE = 1 << 2;
+ /** ARB_create_context
related: ES profile. Cache key value. See {@link #isGLES()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_PROFILE_ES = 1 << 3;
+ /** ARB_create_context
related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ protected static final int CTX_OPTION_FORWARD = 1 << 4;
+ /** ARB_create_context
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;
+ /** 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]
+ //
+
+ /** GL_ARB_ES2_compatibility
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;
+
+ /** GL_ARB_ES3_compatibility
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;
+
+ /**
+ * 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 OES_single_precision
, 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 ThreadLocalnull
.
+ * null
.
+ */
+ public final GLRendererQuirks getRendererQuirks() { return glRendererQuirks; }
+
+ /**
+ * Returns true if the quirk
exist in {@link #getRendererQuirks()}, otherwise false.
+ *
+ * final GLRendererQuirks glrq = ctx.getRendererQuirks();
+ * boolean hasQuirk = null != glrq ? glrq.exist(quirk) : false ;
+ *
+ *
+ * If the arguments reflect the current state of this context + * this method is a no-operation and returns the old and current {@link GLDrawable}. + *
+ *+ * Remarks: + *
null
to remove association.
+ * @param setWriteOnly Only change the write-drawable, if setWriteOnly
is true
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 if operation succeeds
+ *
+ * @throws GLException in case null
is being passed,
+ * this context is made current on another thread
+ * or operation fails.
+ *
+ * @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.
+ * + * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)}, + * it equals to the write-drawable (default). + *
+ *+ * Method is only thread-safe while context is {@link #makeCurrent() made current}. + *
+ * @see #setGLDrawable(GLDrawable, boolean) + * @see #setGLReadDrawable(GLDrawable) + */ + public abstract GLDrawable getGLDrawable(); + + /** + * 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-Drawable for read framebuffer operations.+ * 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. + *
+ * + * @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 or + * this context is made current on another thread. + * + * @see #isGLReadDrawableAvailable() + * @see #getGLReadDrawable() + */ + public abstract GLDrawable setGLReadDrawable(GLDrawable read); + + /** + * Returns the read-Drawable this context uses for read framebuffer operations. + *+ * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)}, + * it equals to the write-drawable (default). + *
+ *+ * Method is only thread-safe while context is {@link #makeCurrent() made current}. + *
+ * @see #isGLReadDrawableAvailable() + * @see #setGLReadDrawable(GLDrawable) + * @see #getGLReadDrawable() + */ + public abstract GLDrawable getGLReadDrawable(); + + /** + * Makes this GLContext current on the calling thread. + *+ * Recursive call to {@link #makeCurrent()} and hence {@link #release()} are supported. + *
+ *+ * There are two return values that indicate success and one that + * indicates failure. + *
+ *+ * 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. + *
+ *+ * A return value of {@link #CONTEXT_CURRENT} indicates that the context has + * been made current, 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 {@link #CONTEXT_NOT_CURRENT} is returned. + *
+ *+ * This method is blocking, i.e. waits until another thread has + * released the context. + *
+ *+ * The drawable's surface is being locked at entry + * and unlocked at {@link #release()} + *
+ * + * @return+ * Recursive call to {@link #release()} and hence {@link #makeCurrent()} are supported. + *
+ *+ * 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
+ * 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. + * + * 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 { + final 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); + } + } + + /** Returns a String representation of the {@link #makeCurrent()} result. */ + public static final String makeCurrentResultToString(final int res) { + switch(res) { + case CONTEXT_NOT_CURRENT: return "CONTEXT_NOT_CURRENT"; + case CONTEXT_CURRENT: return "CONTEXT_CURRENT"; + case CONTEXT_CURRENT_NEW: return "CONTEXT_CURRENT_NEW"; + 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(final GLContext 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. + *
+ * 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_VERSION
not being the GL version.
+ *
+ * In case no such version exists within GL_VERSION
,
+ * the {@link VersionNumberString#zeroVersion zero version} instance is returned.
+ *
+ * The vendor's version is usually the vendor's OpenGL driver version. + *
+ */ + 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 ) ); } + + /** + * Returns the matching GLSL version number, queried by this context GL + * via {@link GL2ES2#GL_SHADING_LANGUAGE_VERSION} if ≥ ES2.0 or GL2.0, + * otherwise a static match is being utilized. + *+ * The context must have been current once, + * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned. + *
+ *
+ * Examples w/ major.minor
:
+ *
+ * 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) + *+ * + *
+ * Matching could also refer to the maximum GLSL version usable by this context + * since normal GL implementations are capable of using a lower GLSL version as well. + * The latter is not true on OSX w/ a GL3 context. + *
+ * + * @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 + *+ * #version 110 + * .. + * #version 150 core + * #version 330 compatibility + * ... + *+ * And for ES: + *
+ * #version 100 + * #version 300 es + * .. + *+ *
+ * If context has not been made current yet, a string of zero length is returned. + *
+ * @see #getGLSLVersionNumber() + */ + public final String getGLSLVersionString() { + if( ctxGLSLVersion.isZero() ) { + return S_EMPTY; + } + final int minor = ctxGLSLVersion.getMinor(); + final String profileOpt; + if( isGLES() ) { + profileOpt = ctxGLSLVersion.compareTo(Version3_0) >= 0 ? " es" : S_EMPTY; + } else if( isGLCoreProfile() ) { + profileOpt = ctxGLSLVersion.compareTo(Version1_50) >= 0 ? " core" : S_EMPTY; + } else if( isGLCompatibilityProfile() ) { + profileOpt = ctxGLSLVersion.compareTo(Version1_50) >= 0 ? " compatibility" : S_EMPTY; + } else { + throw new InternalError("Neither ES, Core nor Compat: "+this); // see validateProfileBits(..) + } + return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + profileOpt + "\n" ; + } + + protected static final VersionNumber getStaticGLSLVersionNumber(final int glMajorVersion, final int glMinorVersion, final int ctxOptions) { + if( 0 != ( CTX_PROFILE_ES & ctxOptions ) ) { + if( 3 == glMajorVersion ) { + return Version3_0; // ES 3.0 -> GLSL 3.00 + } else if( 2 == glMajorVersion ) { + return Version1_0; // ES 2.0 -> GLSL 1.00 + } + } else if( 1 == glMajorVersion ) { + return Version1_10; // GL 1.x -> GLSL 1.10 + } else if( 2 == glMajorVersion ) { + switch ( glMinorVersion ) { + case 0: return Version1_10; // GL 2.0 -> GLSL 1.10 + default: return Version1_20; // GL 2.1 -> GLSL 1.20 + } + } else if( 3 == glMajorVersion && 2 >= glMinorVersion ) { + switch ( glMinorVersion ) { + case 0: return Version1_30; // GL 3.0 -> GLSL 1.30 + case 1: return Version1_40; // GL 3.1 -> GLSL 1.40 + default: return Version1_50; // 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 extensionGL_ARB_ES3_compatibility
or GL_ARB_ES2_compatibility
, otherwise false
+ */
+ public final boolean isGLES2Compatible() {
+ return 0 != ( ctxOptions & ( CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ) ) ;
+ }
+
+ /**
+ * Return true if this context is an ES3 context or implements
+ * the extension GL_ARB_ES3_compatibility
, otherwise false.
+ * + * Includes [ GL ≥ 4.3, GL ≥ 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ] + *
+ */ + 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()} and major-version > 1. + * @see GLProfile#hasGLSL() + */ + public final boolean hasGLSL() { + return isGLES3() || + isGLES2() || + isGL3() || + isGL2() && ctxVersion.getMajor()>1 ; + } + + /** + * Returnstrue
if basic FBO support is available, otherwise false
.
+ *
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= 3.0 [core, compat] or implements the extensions
+ * GL_ARB_ES2_compatibility
, GL_ARB_framebuffer_object
, GL_EXT_framebuffer_object
or GL_OES_framebuffer_object
.
+ *
+ * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *
+ * @see #CTX_IMPL_FBO + */ + public final boolean hasBasicFBOSupport() { + return 0 != ( ctxOptions & CTX_IMPL_FBO ) ; + } + + /** + * Returnstrue
if full FBO support is available, otherwise false
.
+ *
+ * Full FBO is supported if the context is either GL >= 3.0 [ES, core, compat] or implements the extensions
+ * ARB_framebuffer_object
, or all of
+ * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
+ * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ *
+ * Full FBO support includes multiple color attachments and multisampling. + *
+ */ + 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) + ) + ) ; + } + + /** + * Returnstrue
if OES_single_precision
, fp32, fixed function point (FFP) compatibility entry points available,
+ * otherwise false
.
+ * @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(GL2ES3.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 (final GLException gle) { gle.printStackTrace(); }
+ }
+ return 0;
+ }
+
+ /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns true
. */
+ public boolean isNPOTTextureAvailable() {
+ return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
+ }
+
+ public boolean isTextureFormatBGRA8888Available() {
+ return isGL2GL3() ||
+ isExtensionAvailable(GLExtensions.EXT_texture_format_BGRA8888) ||
+ isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ;
+ }
+
+ /**
+ * Indicates whether this GLContext is capable of GL4bc. Includes [ GL4bc ].
+ * @see GLProfile#isGL4bc() + */ + public final boolean isGL4bc() { + return 0 != (ctxOptions & CTX_PROFILE_COMPAT) && + ctxVersion.getMajor() >= 4; + } + + /** + * Indicates whether this GLContext is capable of GL4.Includes [ GL4bc, GL4 ].
+ * @see GLProfile#isGL4() + */ + public final boolean isGL4() { + return 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) && + ctxVersion.getMajor() >= 4; + } + + /** + * Indicates whether this GLContext uses a GL4 core profile.Includes [ GL4 ].
+ */ + public final boolean isGL4core() { + return 0 != ( ctxOptions & CTX_PROFILE_CORE ) && + ctxVersion.getMajor() >= 4; + } + + /** + * Indicates whether this GLContext is capable of GL3bc.Includes [ GL4bc, GL3bc ].
+ * @see GLProfile#isGL3bc() + */ + public final boolean isGL3bc() { + return 0 != (ctxOptions & CTX_PROFILE_COMPAT) && + ctxVersion.compareTo(Version3_1) >= 0 ; + } + + /** + * Indicates whether this GLContext is capable of GL3.Includes [ GL4bc, GL4, GL3bc, GL3 ].
+ * @see GLProfile#isGL3() + */ + public final boolean isGL3() { + return 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) && + ctxVersion.compareTo(Version3_1) >= 0 ; + } + + /** + * Indicates whether this GLContext uses a GL3 core profile.Includes [ GL4, GL3 ].
+ */ + public final boolean isGL3core() { + return 0 != ( ctxOptions & CTX_PROFILE_CORE ) && + ctxVersion.compareTo(Version3_1) >= 0; + } + + /** + * Indicates whether this GLContext uses a GL core profile.Includes [ GL4, GL3, GLES3, GLES2 ].
+ */ + public final boolean isGLcore() { + return ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 2 ) || + ( 0 != ( ctxOptions & CTX_PROFILE_CORE ) && + ctxVersion.compareTo(Version3_1) >= 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)}. + *Includes [GL2ES1, GLES2] == [ GL4bc, GL3bc, GL2, GLES1, GL2ES1, GLES2 ].
+ *See Bug 852 - https://jogamp.org/bugzilla/show_bug.cgi?id=852
+ */ + public final boolean isCPUDataSourcingAvail() { + return isGL2ES1() || isGLES2(); + } + + /** + * Indicates whether this GLContext's native profile does not implement a default vertex array object (VAO), + * starting w/ OpenGL 3.1 core. + *Includes [ GL4, GL3 ].
+ *+ 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). + *+ *
+ ES 3.x is not included here.
+ Due to it's ES 2.0 backward compatibility it still supports the following features:
+ client side vertex arrays
+ default vertex array object
+
+ Binding a custom VAO with ES 3.0 would cause client side vertex arrays via {@link GL2ES1#glVertexPointer(int, int, int, java.nio.Buffer) glVertexPointer}
+ to produce GL_INVALID_OPERATION
.
+
+ However, they are marked deprecated:
+ GL ES 3.0 spec F.1. Legacy Features (p 322).
+ GL ES 3.1 spec F.1. Legacy Features (p 454).
+ *
+ * + * If no default VAO is implemented in the native OpenGL profile, + * an own default VAO is being used, see {@link #getDefaultVAO()}. + *
+ * @see #getDefaultVAO() + */ + public final boolean hasNoDefaultVAO() { + return // ES 3.x not included, see above. ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 3 ) || + ( 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) && + 0 != ( ctxOptions & CTX_PROFILE_CORE ) && + ctxVersion.compareTo(Version3_1) >= 0 + ) ; + } + + /** + * If this GLContext does not implement a default VAO, see {@link #hasNoDefaultVAO()}, + * an own default VAO will be created and bound at context creation. + *
+ * If this GLContext does implement a default VAO, i.e. {@link #hasNoDefaultVAO()}
+ * returns false
, this method returns 0
.
+ *
+ * Otherwise this method returns the VAO object name + * representing this GLContext's own default VAO. + *
+ * @see #hasNoDefaultVAO() + */ + public abstract int getDefaultVAO(); + + /** + * Indicates whether this GLContext is capable of GL2.Includes [ GL4bc, GL3bc, GL2 ].
+ * @see GLProfile#isGL2() + */ + public final boolean isGL2() { + return 0 != ( ctxOptions & CTX_PROFILE_COMPAT ) && ctxVersion.getMajor()>=1 ; + } + + /** + * Indicates whether this GLContext is capable of GL2GL3.Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].
+ * @see GLProfile#isGL2GL3() + */ + public final boolean isGL2GL3() { + return isGL2() || isGL3(); + } + + /** + * Indicates whether this GLContext is capable of GLES1.Includes [ GLES1 ].
+ * @see GLProfile#isGLES1() + */ + public final boolean isGLES1() { + return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 1 ; + } + + /** + * Indicates whether this GLContext is capable of GLES2.Includes [ GLES2, GLES3 ].
+ * @see GLProfile#isGLES2() + */ + public final boolean isGLES2() { + 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.Includes [ GLES3 ].
+ * @see GLProfile#isGLES3() + */ + public final boolean isGLES3() { + return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 3 ; + } + + /** + * Indicates whether this GLContext is capable of GLES.Includes [ GLES3, GLES1, GLES2 ].
+ * @see GLProfile#isGLES() + */ + public final boolean isGLES() { + return 0 != ( CTX_PROFILE_ES & ctxOptions ) ; + } + + /** + * Indicates whether this GLContext is capable of GL2ES1.Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].
+ * @see GLProfile#isGL2ES1() + */ + public final boolean isGL2ES1() { + return isGLES1() || isGL2(); + } + + /** + * Indicates whether this GLContext is capable of GL2ES2.Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GL2GL3, GL2ES2, GLES2 ].
+ * @see GLProfile#isGL2ES2() + */ + public final boolean isGL2ES2() { + return isGLES2() || isGL2GL3(); + } + + /** + * Indicates whether this GLContext is capable of GL2ES3.Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL3ES3, GL2, GL2GL3 ].
+ * @see GLProfile#isGL2ES3() + * @see #isGL3ES3() + * @see #isGL2GL3() + */ + public final boolean isGL2ES3() { + return isGL3ES3() || isGL2GL3(); + } + + /** + * Indicates whether this GLContext is capable of GL3ES3.Includes [ GL4bc, GL4, GL3bc, GL3, GLES3 ].
+ * @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. + *Includes [ GL ≥ 4.3, GL ≥ 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
+ * @see GLProfile#isGL4ES3() + */ + public final boolean isGL4ES3() { + return isGLES3Compatible() ; + } + + /** + * Set the swap interval of the current context and attached drawable. + * @param interval Should be ≥ 0. 0 disables the vertical synchronization, + * 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(final int interval) throws GLException { + validateCurrent(); + if(0<=interval) { + if( !drawableRetargeted || !hasRendererQuirk(GLRendererQuirks.NoSetSwapIntervalPostRetarget) ) { + if( setSwapIntervalImpl(interval) ) { + currentSwapInterval = interval; + return true; + } + } + } + return false; + } + protected boolean setSwapIntervalImpl(final 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.
+ *
+ * For a valid context the default value is 1
+ * in case of an EGL based profile (ES1 or ES2) and -1
+ * (undefined) for desktop.
+ *
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}. + *
+ */ + public abstract int getBoundFramebuffer(int target); + + /** + * Return the default draw framebuffer name. + *
+ * May differ from it's default zero
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
+ * is being used.
+ *
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}. + *
+ */ + public abstract int getDefaultDrawFramebuffer(); + + /** + * Return the default read framebuffer name. + *
+ * May differ from it's default zero
+ * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
+ * is being used.
+ *
+ * Method is only thread-safe while context is {@link #makeCurrent() made current}. + *
+ */ + 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. + *+ * 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. + *
+ *+ * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer + * and {@link GL#GL_BACK} is the default. + *
+ *+ * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i + *
+ *+ * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead} + * for read-pixels and swap-buffers implications. + *
+ *+ * Method is only thread-safe while context is {@link #makeCurrent() made current}. + *
+ */ + 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)}. + *+ * Method is only thread-safe while context is {@link #makeCurrent() made current}. + *
+ */ + 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)}. + *+ * Method is only thread-safe while context is {@link #makeCurrent() made current}. + *
+ */ + 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()}, null is returned. + */ + public abstract String getGLDebugMessageExtension(); + + /** + * @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 glEnable/glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS)}, + * if extension is {@link GLExtensions#ARB_debug_output}. + * There is no equivalent for {@link GLExtensions#AMD_debug_output}. + * The default is true
, ie {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS}.
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}.+ * The minor version number is ignored by the upper limit validation + * and the major version number may exceed by one. + *
+ *+ * The upper limit check is relaxed since we don't want to cut-off + * unforseen new GL version since the release of JOGL. + *
+ *+ * Hence it is important to iterate through GL version from the upper limit + * and {@link #decrementGLVersion(int, int[], int[])} until invalid. + *
+ */ + public static final boolean isValidGLVersion(final int ctxProfile, final int major, final 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; + } + + /** + * 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(final int ctxProfile, final int major[], final 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; + } + return false; + } + + /** + * Decrement the given GL version by one + * and return true if still valid, otherwise false. + *+ * If the given version exceeds the maximum known valid version, + * it is {@link #clipGLVersion(int, int[], int[]) clipped} and + * true is returned. + *
+ * + * @param ctxProfile + * @param major + * @param minor + * @return + */ + public static final boolean decrementGLVersion(final int ctxProfile, final int major[], final 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; + } + + protected static int composeBits(final int a8, final int b8, final int c16) { + return ( ( a8 & 0x000000FF ) << 24 ) | + ( ( b8 & 0x000000FF ) << 16 ) | + ( ( c16 & 0x0000FFFF ) ) ; + } + + private static void validateProfileBits(final int bits, final String argName) { + int num = 0; + if( 0 != ( CTX_PROFILE_COMPAT & bits ) ) { num++; } + if( 0 != ( CTX_PROFILE_CORE & bits ) ) { num++; } + if( 0 != ( CTX_PROFILE_ES & bits ) ) { num++; } + if(1!=num) { + throw new GLException("Internal Error: "+argName+": 1 != num-profiles: "+num); + } + } + + // + // version mapping + // + + /** + * @see #getDeviceVersionAvailableKey(com.jogamp.nativewindow.AbstractGraphicsDevice, int, int) + */ + protected static final IdentityHashMapnull
+ */
+ protected static Integer getAvailableGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile) {
+ final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
+ Integer val;
+ synchronized(deviceVersionAvailable) {
+ val = deviceVersionAvailable.get( objectKey );
+ }
+ 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(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile,
+ final int[] major, final int minor[], final int ctp[]) {
+
+ final Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
+ if(null==valI) {
+ return false;
+ }
+
+ final 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(final int major, final int minor, final 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 == 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, final 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 0
+ */
+ protected static final int getAvailableContextProperties(final AbstractGraphicsDevice device, final GLProfile glp) {
+ final int[] reqMajorCTP = new int[] { 0, 0 };
+ getRequestMajorAndCompat(glp, reqMajorCTP);
+
+ final int _major[] = { 0 };
+ final int _minor[] = { 0 };
+ final 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 for the device regarding availability, version and profile bits.
+ */
+ protected static GLProfile getAvailableGLProfile(final AbstractGraphicsDevice device, final int reqMajor, final 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(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)
+ throws GLException {
+ final int major[] = { 0 };
+ final int minor[] = { 0 };
+ final 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 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(final AbstractGraphicsDevice device, final int major, final int profile) {
+ final int _major[] = { 0 };
+ final int _minor[] = { 0 };
+ final 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 framebuffer object (FBO).
+ * + * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. + *
+ *+ * FBO support is queried as described in {@link #hasBasicFBOSupport()}. + *
+ * + * @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(final AbstractGraphicsDevice device, final GLProfile glp) { + return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) ); + } + + /** + * @return1
if using a hardware rasterizer, 0
if using a software rasterizer and -1
if not determined yet.
+ * @see GLContext#isHardwareRasterizer()
+ * @see GLProfile#isHardwareRasterizer()
+ */
+ public static final int isHardwareRasterizer(final AbstractGraphicsDevice device, final 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.
+ */
+ protected static boolean isGLVersionAvailable(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile, final boolean isHardware[]) {
+ final 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(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 1, GLContext.CTX_PROFILE_ES, isHardware);
+ }
+
+ public static boolean isGLES2Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES, isHardware);
+ }
+
+ public static boolean isGLES3Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
+ return isGLVersionAvailable(device, 3, GLContext.CTX_PROFILE_ES, isHardware);
+ }
+
+ /**
+ * Returns true if a ES3 compatible profile is available,
+ * i.e. either a ≥ 4.3 context or a ≥ 3.1 context supporting GL_ARB_ES3_compatibility
,
+ * otherwise false.
+ * + * Includes [ GL ≥ 4.3, GL ≥ 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ] + *
+ */ + public static final boolean isGLES3CompatibleAvailable(final AbstractGraphicsDevice device) { + final int major[] = { 0 }; + final int minor[] = { 0 }; + final 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 ) { + GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_COMPAT, major, minor, ctp); + } + return 0 != ( ctp[0] & CTX_IMPL_ES3_COMPAT ); + } + + public static boolean isGL4bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[]) { + return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT, isHardware); + } + + public static boolean isGL4Available(final AbstractGraphicsDevice device, final boolean isHardware[]) { + return isGLVersionAvailable(device, 4, CTX_PROFILE_CORE, isHardware); + } + + public static boolean isGL3bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[]) { + return isGLVersionAvailable(device, 3, CTX_PROFILE_COMPAT, isHardware); + } + + public static boolean isGL3Available(final AbstractGraphicsDevice device, final boolean isHardware[]) { + return isGLVersionAvailable(device, 3, CTX_PROFILE_CORE, isHardware); + } + + public static boolean isGL2Available(final AbstractGraphicsDevice device, final boolean isHardware[]) { + return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT, isHardware); + } + + protected static String getGLVersion(final int major, final int minor, final int ctp, final String gl_version) { + boolean needColon = false; + final 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, "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, "arb", needColon, 0 != ( CTX_IS_ARB_CREATED & 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 { + 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(final int hex) { + return "0x" + Integer.toHexString(hex); + } + + protected static String toHexString(final long hex) { + return "0x" + Long.toHexString(hex); + } + + private static boolean appendString(final StringBuilder sb, final String string, boolean needColon, final boolean condition) { + if(condition) { + if(needColon) { + sb.append(", "); + } + sb.append(string); + needColon=true; + } + return needColon; + } + + protected static String getThreadName() { return Thread.currentThread().getName(); } + +} + -- cgit v1.2.3