1 /*
2  * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3  * Copyright (c) 2010 JogAmp Community. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * - Redistribution of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * - Redistribution in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of Sun Microsystems, Inc. or the names of
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * This software is provided "AS IS," without a warranty of any kind. ALL
21  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
22  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
23  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
24  * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
25  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
26  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
27  * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
28  * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
29  * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
30  * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
31  * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32  *
33  * You acknowledge that this software is not designed or intended for use
34  * in the design, construction, operation or maintenance of any nuclear
35  * facility.
36  *
37  * Sun gratefully acknowledges that this software was originally authored
38  * and developed by Kenneth Bradley Russell and Christopher John Kline.
39  */
40 
41 package com.jogamp.opengl;
42 
43 import java.nio.IntBuffer;
44 import java.util.HashMap;
45 import java.util.IdentityHashMap;
46 import java.util.Iterator;
47 import java.util.List;
48 import java.util.Set;
49 
50 import com.jogamp.nativewindow.AbstractGraphicsDevice;
51 import com.jogamp.nativewindow.NativeSurface;
52 
53 import jogamp.opengl.Debug;
54 import jogamp.opengl.GLContextImpl;
55 import jogamp.opengl.GLContextShareSet;
56 
57 import com.jogamp.common.os.Platform;
58 import com.jogamp.common.util.VersionNumber;
59 import com.jogamp.common.util.VersionNumberString;
60 import com.jogamp.common.util.locks.LockFactory;
61 import com.jogamp.common.util.locks.RecursiveLock;
62 import com.jogamp.opengl.GLExtensions;
63 import com.jogamp.opengl.GLRendererQuirks;
64 
65 /** Abstraction for an OpenGL rendering context. In order to perform
66     OpenGL rendering, a context must be "made current" on the current
67     thread. OpenGL rendering semantics specify that only one context
68     may be current on the current thread at any given time, and also
69     that a given context may be current on only one thread at any
70     given time. Because components can be added to and removed from
71     the component hierarchy at any time, it is possible that the
72     underlying OpenGL context may need to be destroyed and recreated
73     multiple times over the lifetime of a given component. This
74     process is handled by the implementation, and the GLContext
75     abstraction provides a stable object which clients can use to
76     refer to a given context. */
77 public abstract class GLContext {
78 
79   public static final boolean DEBUG = Debug.debug("GLContext");
80   public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true);
81   public static final boolean DEBUG_TRACE_SWITCH = DEBUG || TRACE_SWITCH;
82 
83   /**
84    * If <code>true</code> (default), bootstrapping the available GL profiles
85    * will use the highest compatible GL context for each profile,
86    * hence skipping querying lower profiles if a compatible higher one is found:
87    * <ul>
88    *   <li>4.2-core -> 4.2-core, 3.3-core</li>
89    *   <li>4.2-comp -> 4.2-comp, 3.3-comp, 2</li>
90    * </ul>
91    * Otherwise the dedicated GL context would be queried and used:
92    * <ul>
93    *   <li>4.2-core -> 4.2-core</li>
94    *   <li>3.3-core -> 3.3-core</li>
95    *   <li>4.2-comp -> 4.2-comp</li>
96    *   <li>3.3-comp -> 3.3-comp</li>
97    *   <li>3.0-comp -> 2</li>
98    * </ul>
99    * Using aliasing speeds up initialization about:
100    * <ul>
101    *   <li>Linux x86_64 - Nvidia: 28%,  700ms down to 500ms</li>
102    *   <li>Linux x86_64 - AMD   : 40%, 1500ms down to 900ms</li>
103    * <p>
104    * Can be turned off with property <code>jogl.debug.GLContext.NoProfileAliasing</code>.
105    * </p>
106    */
107   public static final boolean PROFILE_ALIASING = !Debug.isPropertyDefined("jogl.debug.GLContext.NoProfileAliasing", true);
108 
109   protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true);
110   protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true);
111   protected static final boolean FORCE_NO_COLOR_RENDERBUFFER = Debug.isPropertyDefined("jogl.fbo.force.nocolorrenderbuffer", true);
112 
113   /** Reflects property jogl.debug.DebugGL. If true, the debug pipeline is enabled at context creation. */
114   public static final boolean DEBUG_GL = Debug.isPropertyDefined("jogl.debug.DebugGL", true);
115   /** Reflects property jogl.debug.TraceGL. If true, the trace pipeline is enabled at context creation. */
116   public static final boolean TRACE_GL = Debug.isPropertyDefined("jogl.debug.TraceGL", true);
117 
118   /** Indicates that the context was not made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
119   public static final int CONTEXT_NOT_CURRENT = 0;
120   /** Indicates that the context was made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
121   public static final int CONTEXT_CURRENT     = 1;
122   /** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}, value {@value}. */
123   public static final int CONTEXT_CURRENT_NEW = 2;
124 
125   /** Version 1.00, i.e. GLSL 1.00 for ES 2.0. */
126   public static final VersionNumber Version1_0 =  new VersionNumber(1,  0, 0);
127   /** Version 1.10, i.e. GLSL 1.10 for GL 2.0. */
128   public static final VersionNumber Version1_10 = new VersionNumber(1, 10, 0);
129   /** Version 1.20, i.e. GLSL 1.20 for GL 2.1. */
130   public static final VersionNumber Version1_20 = new VersionNumber(1, 20, 0);
131   /** Version 1.30, i.e. GLSL 1.30 for GL 3.0. */
132   public static final VersionNumber Version1_30 = new VersionNumber(1, 30, 0);
133   /** Version 1.40, i.e. GLSL 1.40 for GL 3.1. */
134   public static final VersionNumber Version1_40 = new VersionNumber(1, 40, 0);
135   /** Version 1.50, i.e. GLSL 1.50 for GL 3.2. */
136   public static final VersionNumber Version1_50 = new VersionNumber(1, 50, 0);
137 
138   /** Version 1.1, i.e. GL 1.1 */
139   public static final VersionNumber Version1_1 = new VersionNumber(1, 1, 0);
140 
141   /** Version 1.2, i.e. GL 1.2 */
142   public static final VersionNumber Version1_2 = new VersionNumber(1, 2, 0);
143 
144   /** Version 1.4, i.e. GL 1.4 */
145   public static final VersionNumber Version1_4 = new VersionNumber(1, 4, 0);
146 
147   /** Version 1.5, i.e. GL 1.5 */
148   public static final VersionNumber Version1_5 = new VersionNumber(1, 5, 0);
149 
150   /** 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. */
151   public static final VersionNumber Version3_0 = new VersionNumber(3, 0, 0);
152 
153   /** Version 3.1. As an OpenGL version, it qualifies for {@link #isGL3core()}, {@link #isGL3bc()} and {@link #isGL3()} */
154   public static final VersionNumber Version3_1 = new VersionNumber(3, 1, 0);
155 
156   /** Version 3.2. As an OpenGL version, it qualifies for geometry shader */
157   public static final VersionNumber Version3_2 = new VersionNumber(3, 2, 0);
158 
159   /** Version 4.3. As an OpenGL version, it qualifies for <code>GL_ARB_ES3_compatibility</code> */
160   public static final VersionNumber Version4_3 = new VersionNumber(4, 3, 0);
161 
162   protected static final VersionNumber Version8_0 = new VersionNumber(8, 0, 0);
163 
164   private static final String S_EMPTY = "";
165 
166   //
167   // Cached keys, bits [0..15]
168   //
169 
170   /** Context option bits, full bit mask covering 16 bits [0..15], i.e. <code>0x0000FFFF</code>, {@value}. */
171   protected static final int CTX_IMPL_FULL_MASK = 0x0000FFFF;
172 
173   /** 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. */
174   protected static final int CTX_IMPL_CACHE_MASK = 0x000003FF;
175 
176   /** <code>ARB_create_context</code> related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
177   protected static final int CTX_IS_ARB_CREATED  = 1 <<  0;
178   /** <code>ARB_create_context</code> related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
179   protected static final int CTX_PROFILE_COMPAT  = 1 <<  1;
180   /** <code>ARB_create_context</code> related: desktop core profile. Cache key value. See {@link #isGLCoreProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
181   protected static final int CTX_PROFILE_CORE    = 1 <<  2;
182   /** <code>ARB_create_context</code> related: ES profile. Cache key value. See {@link #isGLES()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
183   protected static final int CTX_PROFILE_ES      = 1 <<  3;
184   /** <code>ARB_create_context</code> related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
185   protected static final int CTX_OPTION_FORWARD  = 1 <<  4;
186   /** <code>ARB_create_context</code> related: flag debug. Cache key value. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
187   public static final int CTX_OPTION_DEBUG       = 1 <<  5;
188   /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
189   protected static final int CTX_IMPL_ACCEL_SOFT = 1 <<  6;
190 
191   //
192   // Non cached keys, 6 bits [10..15]
193   //
194 
195   /** <code>GL_ARB_ES2_compatibility</code> implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
196   protected static final int CTX_IMPL_ES2_COMPAT  = 1 << 10;
197 
198   /** <code>GL_ARB_ES3_compatibility</code> implementation related: Context is compatible w/ ES3. Not a cache key. See {@link #isGLES3Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
199   protected static final int CTX_IMPL_ES3_COMPAT  = 1 << 11;
200 
201   /** <code>GL_ARB_ES3_1_compatibility</code> implementation related: Context is compatible w/ ES 3.1. Not a cache key. See {@link #isGLES31Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
202   protected static final int CTX_IMPL_ES31_COMPAT = 1 << 12;
203 
204   /** <code>GL_ARB_ES3_2_compatibility</code> implementation related: Context is compatible w/ ES 3.2. Not a cache key. See {@link #isGLES32Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
205   protected static final int CTX_IMPL_ES32_COMPAT = 1 << 13;
206 
207   /**
208    * Context supports basic FBO, details see {@link #hasBasicFBOSupport()}.
209    * Not a cache key.
210    * @see #hasBasicFBOSupport()
211    * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
212    */
213   protected static final int CTX_IMPL_FBO         = 1 << 14;
214 
215   /**
216    * Context supports <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points,
217    * see {@link #hasFP32CompatAPI()}.
218    * Not a cache key.
219    * @see #hasFP32CompatAPI()
220    * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
221    */
222   protected static final int CTX_IMPL_FP32_COMPAT_API = 1 << 15;
223 
224   private static final ThreadLocal<GLContext> currentContext = new ThreadLocal<GLContext>();
225 
226   private final HashMap<String, Object> attachedObjects = new HashMap<String, Object>();
227 
228   // RecursiveLock maintains a queue of waiting Threads, ensuring the longest waiting thread will be notified at unlock.
229   protected final RecursiveLock lock = LockFactory.createRecursiveLock(); // FIXME: Move to GLContextImpl when incr. minor version (incompatible change)
230 
231   /** The underlying native OpenGL context */
232   protected volatile long contextHandle; // volatile: avoid locking for read-only access
233 
GLContext()234   protected GLContext() {
235       resetStates(true);
236   }
237 
238   protected VersionNumber ctxVersion;
239   protected int ctxOptions;
240   protected String ctxVersionString;
241   protected VersionNumberString ctxVendorVersion;
242   protected VersionNumber ctxGLSLVersion;
243   protected GLRendererQuirks glRendererQuirks;
244 
245   /** Did the drawable association changed ? see {@link GLRendererQuirks#NoSetSwapIntervalPostRetarget} */
246   protected boolean drawableRetargeted;
247 
248   /**
249    * @param isInit true if called for class initialization, otherwise false (re-init or destruction).
250    */
resetStates(final boolean isInit)251   protected void resetStates(final boolean isInit) {
252       if (DEBUG) {
253         System.err.println(getThreadName() + ": GLContext.resetStates(isInit "+isInit+")");
254         // Thread.dumpStack();
255       }
256       ctxVersion = VersionNumberString.zeroVersion;
257       ctxVendorVersion = VersionNumberString.zeroVersion;
258       ctxOptions=0;
259       ctxVersionString=null;
260       ctxGLSLVersion = VersionNumber.zeroVersion;
261       attachedObjects.clear();
262       contextHandle=0;
263       glRendererQuirks = null;
264       drawableRetargeted = false;
265   }
266 
267   /** Returns true if this GLContext is shared, otherwise false. */
isShared()268   public final boolean isShared() {
269       return GLContextShareSet.isShared(this);
270   }
271 
272   /**
273    * Returns the shared master GLContext of this GLContext if shared, otherwise return <code>null</code>.
274    * <p>
275    * Returns this GLContext, if it is a shared master.
276    * </p>
277    * @since 2.2.1
278    */
getSharedMaster()279   public final GLContext getSharedMaster() {
280       return GLContextShareSet.getSharedMaster(this);
281   }
282 
283   /** Returns a new list of created GLContext shared with this GLContext. */
getCreatedShares()284   public final List<GLContext> getCreatedShares() {
285       return GLContextShareSet.getCreatedShares(this);
286   }
287 
288   /** Returns a new list of destroyed GLContext shared with this GLContext. */
getDestroyedShares()289   public final List<GLContext> getDestroyedShares() {
290       return GLContextShareSet.getDestroyedShares(this);
291   }
292 
293   /**
294    * Returns the instance of {@link GLRendererQuirks}, allowing one to determine workarounds.
295    * @return instance of {@link GLRendererQuirks} if context was made current once, otherwise <code>null</code>.
296    */
getRendererQuirks()297   public final GLRendererQuirks getRendererQuirks() { return glRendererQuirks; }
298 
299   /**
300    * Returns true if the <code>quirk</code> exist in {@link #getRendererQuirks()}, otherwise false.
301    * <p>
302    * Convenience method for:
303    * <pre>
304    *    final GLRendererQuirks glrq = ctx.getRendererQuirks();
305    *    boolean hasQuirk = null != glrq ? glrq.exist(quirk) : false ;
306    * </pre>
307    * </p>
308    * @param quirk the quirk to be tested, e.g. {@link GLRendererQuirks#NoDoubleBufferedPBuffer}.
309    * @throws IllegalArgumentException if the quirk is out of range
310    */
hasRendererQuirk(final int quirk)311   public final boolean hasRendererQuirk(final int quirk) throws IllegalArgumentException {
312       return null != glRendererQuirks ? glRendererQuirks.exist(quirk) : false ;
313   }
314 
315   /**
316    * Sets the read/write drawable for framebuffer operations, i.e. reassociation of the context's drawable.
317    * <p>
318    * If the arguments reflect the current state of this context
319    * this method is a no-operation and returns the old and current {@link GLDrawable}.
320    * </p>
321    * <p>
322    * Remarks:
323    * <ul>
324    *   <li>{@link GL#glFinish() glFinish()} is issued if context {@link #isCreated()} and a {@link #getGLDrawable() previous drawable} was bound before disassociation.</li>
325    *   <li>If the context was current on this thread, it is being released before drawable reassociation
326    *       and made current afterwards.</li>
327    *   <li>Implementation may issue {@link #makeCurrent()} and {@link #release()} while drawable reassociation.</li>
328    *   <li>The user shall take extra care of thread synchronization,
329    *       i.e. lock the involved {@link GLDrawable#getNativeSurface() drawable's} {@link NativeSurface}s
330    *       to avoid a race condition. In case {@link GLAutoDrawable auto-drawable's} are used,
331    *       their {@link GLAutoDrawable#getUpstreamLock() upstream-lock} must be locked beforehand
332    *       see <a href="GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
333    * </ul>
334    * </p>
335    * @param readWrite The read/write drawable for framebuffer operations, maybe <code>null</code> to remove association.
336    * @param setWriteOnly Only change the write-drawable, if <code>setWriteOnly</code> is <code>true</code> and
337    *                     if the {@link #getGLReadDrawable() read-drawable} differs
338    *                     from the {@link #getGLDrawable() write-drawable}.
339    *                     Otherwise set both drawables, read and write.
340    * @return The previous read/write drawable if operation succeeds
341    *
342    * @throws GLException in case <code>null</code> is being passed,
343    *                     this context is made current on another thread
344    *                     or operation fails.
345    *
346    * @see #isGLReadDrawableAvailable()
347    * @see #setGLReadDrawable(GLDrawable)
348    * @see #getGLReadDrawable()
349    * @see #setGLDrawable(GLDrawable, boolean)
350    * @see #getGLDrawable()
351    */
setGLDrawable(GLDrawable readWrite, boolean setWriteOnly)352   public abstract GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly);
353 
354   /**
355    * Returns the write-drawable this context uses for framebuffer operations.
356    * <p>
357    * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)},
358    * it equals to the write-drawable (default).
359    * </p>
360    * <p>
361    * Method is only thread-safe while context is {@link #makeCurrent() made current}.
362    * </p>
363    * @see #setGLDrawable(GLDrawable, boolean)
364    * @see #setGLReadDrawable(GLDrawable)
365    */
getGLDrawable()366   public abstract GLDrawable getGLDrawable();
367 
368   /**
369    * Query whether using a distinguished read-drawable is supported.
370    * @return true if using a read-drawable is supported with your driver/OS, otherwise false.
371    */
isGLReadDrawableAvailable()372   public abstract boolean isGLReadDrawableAvailable();
373 
374   /**
375    * Set the read-Drawable for read framebuffer operations.<br>
376    * The caller should query if this feature is supported via {@link #isGLReadDrawableAvailable()}.
377    * <p>
378    * If the context was current on this thread, it is being released before switching the drawable
379    * and made current afterwards. However the user shall take extra care that not other thread
380    * attempts to make this context current. Otherwise a race condition may happen.
381    * </p>
382    *
383    * @param read the read-drawable for read framebuffer operations.
384    *             If null is passed, the default write drawable will be set.
385    * @return the previous read-drawable
386    *
387    * @throws GLException in case a read drawable is not supported or
388    *                     this context is made current on another thread.
389    *
390    * @see #isGLReadDrawableAvailable()
391    * @see #getGLReadDrawable()
392    */
setGLReadDrawable(GLDrawable read)393   public abstract GLDrawable setGLReadDrawable(GLDrawable read);
394 
395   /**
396    * Returns the read-Drawable this context uses for read framebuffer operations.
397    * <p>
398    * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)},
399    * it equals to the write-drawable (default).
400    * </p>
401    * <p>
402    * Method is only thread-safe while context is {@link #makeCurrent() made current}.
403    * </p>
404    * @see #isGLReadDrawableAvailable()
405    * @see #setGLReadDrawable(GLDrawable)
406    * @see #getGLReadDrawable()
407    */
getGLReadDrawable()408   public abstract GLDrawable getGLReadDrawable();
409 
410   /**
411    * Makes this GLContext current on the calling thread.
412    * <p>
413    * Recursive call to {@link #makeCurrent()} and hence {@link #release()} are supported.
414    * </p>
415    * <p>
416    * There are two return values that indicate success and one that
417    * indicates failure.
418    * </p>
419    * <p>
420    * A return value of {@link #CONTEXT_CURRENT_NEW}
421    * indicates that that context has been made current for the 1st time,
422    * or that the state of the underlying context or drawable has
423    * changed since the last time this context was current.
424    * In this case, the application may wish to initialize the render state.
425    * </p>
426    * <p>
427    * A return value of {@link #CONTEXT_CURRENT} indicates that the context has
428    * been made current, with its previous state restored.
429    * </p>
430    * <p>
431    * If the context could not be made current (for example, because
432    * the underlying drawable has not ben realized on the display) ,
433    * a value of {@link #CONTEXT_NOT_CURRENT} is returned.
434    * </p>
435    * <p>
436    * This method is blocking, i.e. waits until another thread has
437    * released the context.
438    * </p>
439    * <p>
440    * The drawable's surface is being locked at entry
441    * and unlocked at {@link #release()}
442    * </p>
443    *
444    * @return <ul>
445    *           <li>{@link #CONTEXT_CURRENT_NEW} if the context was successfully made current the 1st time,</li>
446    *           <li>{@link #CONTEXT_CURRENT} if the context was successfully made current,</li>
447    *           <li>{@link #CONTEXT_NOT_CURRENT} if the context could not be made current.</li>
448    *         </ul>
449    *
450    * @throws GLException if the context could not be created
451    *         or made current due to non-recoverable, system-specific errors.
452    */
makeCurrent()453   public abstract int makeCurrent() throws GLException;
454 
455   /**
456    * Releases control of this GLContext from the current thread.
457    * <p>
458    * Recursive call to {@link #release()} and hence {@link #makeCurrent()} are supported.
459    * </p>
460    * <p>
461    * The drawable's surface is being unlocked at exit,
462    * assumed to be locked by {@link #makeCurrent()}.
463    * </p>
464    *
465    * @throws GLException if the context had not previously been made
466    * current on the current thread
467    */
release()468   public abstract void release() throws GLException;
469 
470   /**
471    * Copies selected groups of OpenGL state variables from the
472    * supplied source context into this one. The <code>mask</code>
473    * parameter indicates which groups of state variables are to be
474    * copied. <code>mask</code> contains the bitwise OR of the same
475    * symbolic names that are passed to the GL command {@link
476    * GL2#glPushAttrib glPushAttrib}. The single symbolic constant
477    * {@link GL2#GL_ALL_ATTRIB_BITS GL_ALL_ATTRIB_BITS} can be used to
478    * copy the maximum possible portion of rendering state. <P>
479    *
480    * Not all values for GL state can be copied. For example, pixel
481    * pack and unpack state, render mode state, and select and feedback
482    * state are not copied. The state that can be copied is exactly the
483    * state that is manipulated by the GL command {@link
484    * GL2#glPushAttrib glPushAttrib}. <P>
485    *
486    * On most platforms, this context may not be current to any thread,
487    * including the calling thread, when this method is called. Some
488    * platforms have additional requirements such as whether this
489    * context or the source context must occasionally be made current
490    * in order for the results of the copy to be seen; these
491    * requirements are beyond the scope of this specification.
492    *
493    * @param source the source OpenGL context from which to copy state
494    * @param mask a mask of symbolic names indicating which groups of state to copy
495 
496    * @throws GLException if an OpenGL-related error occurred
497    */
copy(GLContext source, int mask)498   public abstract void copy(GLContext source, int mask) throws GLException;
499 
500   /**
501    * Returns the GL object bound to this thread current context.
502    * If no context is current, throw an GLException
503    *
504    * @return the current context's GL object on this thread
505    * @throws GLException if no context is current
506    */
getCurrentGL()507   public static GL getCurrentGL() throws GLException {
508     final GLContext glc = getCurrent();
509     if(null==glc) {
510         throw new GLException(getThreadName()+": No OpenGL context current on this thread");
511     }
512     return glc.getGL();
513   }
514 
515   /**
516    * Returns this thread current context.
517    * If no context is current, returns null.
518    *
519    * @return the context current on this thread, or null if no context
520    * is current.
521    */
getCurrent()522   public static GLContext getCurrent() {
523     return currentContext.get();
524   }
525 
526   /**
527    * @return true if this GLContext is current on this thread
528    */
isCurrent()529   public final boolean isCurrent() {
530     return getCurrent() == this ;
531   }
532 
533   /**
534    * @throws GLException if this GLContext is not current on this thread
535    */
validateCurrent()536   public final void validateCurrent() throws GLException {
537     if(getCurrent() != this) {
538         throw new GLException(getThreadName()+": This context is not current. Current context: "+getCurrent()+", this context "+this);
539     }
540   }
541 
542   /** Returns a String representation of the {@link #makeCurrent()} result. */
makeCurrentResultToString(final int res)543   public static final String makeCurrentResultToString(final int res) {
544       switch(res) {
545           case CONTEXT_NOT_CURRENT:   return "CONTEXT_NOT_CURRENT";
546           case CONTEXT_CURRENT:       return "CONTEXT_CURRENT";
547           case CONTEXT_CURRENT_NEW:   return "CONTEXT_CURRENT_NEW";
548           default: return "INVALID_VALUE";
549       }
550   }
551 
552   /**
553    * Sets the thread-local variable returned by {@link #getCurrent}
554    * and has no other side-effects. For use by third parties adding
555    * new GLContext implementations; not for use by end users.
556    */
setCurrent(final GLContext cur)557   protected static void setCurrent(final GLContext cur) {
558     if( TRACE_SWITCH ) {
559        if(null == cur) {
560            System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - NULL");
561        } else {
562            System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - obj " + toHexString(cur.hashCode()) + ", ctx " + toHexString(cur.getHandle()));
563        }
564     }
565     currentContext.set(cur);
566   }
567 
568   /**
569    * Destroys this OpenGL context and frees its associated
570    * resources.
571    * <p>
572    * The context may be current w/o recursion when calling <code>destroy()</code>,
573    * in which case this method destroys the context and releases the lock.
574    * </p>
575    */
destroy()576   public abstract void destroy();
577 
578   /**
579    * Returns the implementing root GL instance of this GLContext's GL object,
580    * considering a wrapped pipelined hierarchy, see {@link GLBase#getDownstreamGL()}.
581    * @throws GLException if the root instance is not a GL implementation
582    * @see GLBase#getRootGL()
583    * @see GLBase#getDownstreamGL()
584    * @see #getGL()
585    * @see #setGL(GL)
586    */
getRootGL()587   public abstract GL getRootGL();
588 
589   /**
590    * Returns the GL pipeline object for this GLContext.
591    *
592    * @return the aggregated GL instance, or null if this context was not yet made current.
593    */
getGL()594   public abstract GL getGL();
595 
596   /**
597    * Sets the GL pipeline object for this GLContext.
598    *
599    * @return the set GL pipeline or null if not successful
600    */
setGL(GL gl)601   public abstract GL setGL(GL gl);
602 
603   /**
604    * Returns the underlying native OpenGL context handle
605    */
getHandle()606   public final long getHandle() { return contextHandle; }
607 
608   /**
609    * Indicates whether the underlying native OpenGL context has been created.
610    */
isCreated()611   public final boolean isCreated() {
612     return 0 != contextHandle;
613   }
614 
615   /**
616    * Returns the attached user object for the given name to this GLContext.
617    */
getAttachedObject(final String name)618   public final Object getAttachedObject(final String name) {
619     return attachedObjects.get(name);
620   }
621 
622   /**
623    * Sets the attached user object for the given name to this GLContext.
624    * Returns the previously set object or null.
625    */
attachObject(final String name, final Object obj)626   public final Object attachObject(final String name, final Object obj) {
627     return attachedObjects.put(name, obj);
628   }
629 
detachObject(final String name)630   public final Object detachObject(final String name) {
631       return attachedObjects.remove(name);
632   }
633 
634   /**
635    * Classname, GL, GLDrawable
636    */
637   @Override
toString()638   public String toString() {
639     final StringBuilder sb = new StringBuilder();
640     sb.append(getClass().getSimpleName());
641     sb.append(" [");
642     this.append(sb);
643     sb.append("] ");
644     return sb.toString();
645   }
646 
append(final StringBuilder sb)647   public final StringBuilder append(final StringBuilder sb) {
648     sb.append("Version ").append(getGLVersion()).append(" [GL ").append(getGLVersionNumber()).append(", vendor ").append(getGLVendorVersionNumber());
649     sb.append("], options 0x");
650     sb.append(Integer.toHexString(ctxOptions));
651     sb.append(", this ");
652     sb.append(toHexString(hashCode()));
653     sb.append(", handle ");
654     sb.append(toHexString(contextHandle));
655     sb.append(", isShared "+isShared()+", ");
656     sb.append(getGL());
657     sb.append(",\n\t quirks: ");
658     if(null != glRendererQuirks) {
659         glRendererQuirks.toString(sb);
660     } else {
661         sb.append("n/a");
662     }
663     if(getGLDrawable()!=getGLReadDrawable()) {
664         sb.append(",\n\tRead Drawable : ");
665         sb.append(getGLReadDrawable());
666         sb.append(",\n\tWrite Drawable: ");
667         sb.append(getGLDrawable());
668     } else {
669         sb.append(",\n\tDrawable: ");
670         sb.append(getGLDrawable());
671     }
672     return sb;
673   }
674 
675   /**
676    * Returns true if the specified OpenGL core- or extension-function can be
677    * successfully called using this GL context given the current host (OpenGL
678    * <i>client</i>) and display (OpenGL <i>server</i>) configuration.
679    *
680    * See {@link GL#isFunctionAvailable(String)} for more details.
681    *
682    * @param glFunctionName the name of the OpenGL function (e.g., use
683    * "glPolygonOffsetEXT" or "glPolygonOffset" to check if the {@link
684    * com.jogamp.opengl.GL#glPolygonOffset(float,float)} is available).
685    */
isFunctionAvailable(String glFunctionName)686   public abstract boolean isFunctionAvailable(String glFunctionName);
687 
688   /**
689    * Returns true if the specified OpenGL extension can be
690    * successfully called using this GL context given the current host (OpenGL
691    * <i>client</i>) and display (OpenGL <i>server</i>) configuration.
692    *
693    * See {@link GL#isExtensionAvailable(String)} for more details.
694    *
695    * @param glExtensionName the name of the OpenGL extension (e.g.,
696    * "GL_VERTEX_PROGRAM_ARB").
697    */
isExtensionAvailable(String glExtensionName)698   public abstract boolean isExtensionAvailable(String glExtensionName);
699 
700   /** Returns the number of platform extensions */
getPlatformExtensionCount()701   public abstract int getPlatformExtensionCount();
702 
703   /** Returns a non-null (but possibly empty) string containing the
704       space-separated list of available platform-dependent (e.g., WGL,
705       GLX) extensions. Can only be called while this context is
706       current. */
getPlatformExtensionsString()707   public abstract String getPlatformExtensionsString();
708 
709   /** Returns the number of OpenGL extensions */
getGLExtensionCount()710   public abstract int getGLExtensionCount();
711 
712   /** Returns a non-null (but possibly empty) string containing the
713       space-separated list of available extensions.
714       Can only be called while this context is current.
715       This is equivalent to
716       {@link com.jogamp.opengl.GL#glGetString(int) glGetString}({@link com.jogamp.opengl.GL#GL_EXTENSIONS GL_EXTENSIONS})
717    */
getGLExtensionsString()718   public abstract String getGLExtensionsString();
719 
720   /**
721    * @return Additional context creation flags, supported: {@link GLContext#CTX_OPTION_DEBUG}.
722    */
getContextCreationFlags()723   public abstract int getContextCreationFlags();
724 
725   /**
726    * @param flags Additional context creation flags, supported: {@link GLContext#CTX_OPTION_DEBUG}.
727    *              Unsupported flags are masked out.
728    *              Only affects this context state if not created yet via {@link #makeCurrent()}.
729    * @see #enableGLDebugMessage(boolean)
730    * @see GLAutoDrawable#setContextCreationFlags(int)
731    */
setContextCreationFlags(int flags)732   public abstract void setContextCreationFlags(int flags);
733 
734   /**
735    * Returns a valid OpenGL version string, ie<br>
736    * <pre>
737    *     major.minor ([option]?[options,]*) - gl-version
738    * </pre><br>
739    *
740    * <ul>
741    *   <li> options
742    *   <ul>
743    *     <li> <code>ES profile</code> ES profile</li>
744    *     <li> <code>Compatibility profile</code> Compatibility profile including fixed function pipeline and deprecated functionality</li>
745    *     <li> <code>Core profile</code> Core profile</li>
746    *     <li> <code>forward</code> Forward profile excluding deprecated functionality</li>
747    *     <li> <code>arb</code> refers to an ARB_create_context created context</li>
748    *     <li> <code>debug</code> refers to a debug context</li>
749    *     <li> <code>ES2 compatible</code> refers to an ES2 compatible implementation</li>
750    *     <li> <code>software</code> refers to a software implementation of the rasterizer</li>
751    *     <li> <code>hardware</code> refers to a hardware implementation of the rasterizer</li>
752    *   </ul></li>
753    *   <li> <i>gl-version</i> the GL_VERSION string</li>
754    * </ul>
755    *
756    * e.g.:
757    * <table border="0">
758    * <tr> <td></td> <td></td> </tr>
759    * <tr>
760    * <td>row 2, cell 1</td>
761    * <td>row 2, cell 2</td>
762    * </tr>
763    * </table>
764    *
765    * <table border="0">
766    *     <tr><td></td>   <td>ES2</td>  <td><code>2.0 (ES profile, ES2 compatible, hardware) - 2.0 ES Profile</code></td></tr>
767    *     <tr><td>ATI</td><td>GL2</td>  <td><code>3.0 (Compatibility profile, arb, hardware) - 3.2.9704 Compatibility Profile Context</code></td></tr>
768    *     <tr><td>ATI</td><td>GL3</td>  <td><code>3.3 (Core profile, any, new, hardware) - 1.4 (3.2.9704 Compatibility Profile Context)</code></td></tr>
769    *     <tr><td>ATI</td><td>GL3bc</td><td><code>3.3 (Compatibility profile, arb, hardware) - 1.4 (3.2.9704 Compatibility Profile Context)</code></td></tr>
770    *     <tr><td>NV</td><td>GL2</td>   <td><code>3.0 (Compatibility profile, arb, hardware) - 3.0.0 NVIDIA 195.36.07.03</code></td></tr>
771    *     <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>
772    *     <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>
773    *     <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>
774    * </table>
775    */
getGLVersion()776   public final String getGLVersion() {
777     return ctxVersionString;
778   }
779 
780   /**
781    * Returns this context OpenGL version.
782    * @see #getGLSLVersionNumber()
783    **/
getGLVersionNumber()784   public final VersionNumber getGLVersionNumber() { return ctxVersion; }
785   /**
786    * Returns the vendor's version, i.e. version number at the end of <code>GL_VERSION</code> not being the GL version.
787    * <p>
788    * In case no such version exists within <code>GL_VERSION</code>,
789    * the {@link VersionNumberString#zeroVersion zero version} instance is returned.
790    * </p>
791    * <p>
792    * The vendor's version is usually the vendor's OpenGL driver version.
793    * </p>
794    */
getGLVendorVersionNumber()795   public final VersionNumberString getGLVendorVersionNumber() { return ctxVendorVersion; }
isGLCompatibilityProfile()796   public final boolean isGLCompatibilityProfile() { return ( 0 != ( CTX_PROFILE_COMPAT & ctxOptions ) ); }
isGLCoreProfile()797   public final boolean isGLCoreProfile()          { return ( 0 != ( CTX_PROFILE_CORE   & ctxOptions ) ); }
isGLESProfile()798   public final boolean isGLESProfile()            { return ( 0 != ( CTX_PROFILE_ES     & ctxOptions ) ); }
isGLForwardCompatible()799   public final boolean isGLForwardCompatible()    { return ( 0 != ( CTX_OPTION_FORWARD & ctxOptions ) ); }
isGLDebugEnabled()800   public final boolean isGLDebugEnabled()         { return ( 0 != ( CTX_OPTION_DEBUG   & ctxOptions ) ); }
isCreatedWithARBMethod()801   public final boolean isCreatedWithARBMethod()   { return ( 0 != ( CTX_IS_ARB_CREATED & ctxOptions ) ); }
802 
803   /**
804    * Returns the matching GLSL version number, queried by this context GL
805    * via {@link GL2ES2#GL_SHADING_LANGUAGE_VERSION} if &ge; ES2.0 or GL2.0,
806    * otherwise a static match is being utilized.
807    * <p>
808    * The context must have been current once,
809    * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
810    * </p>
811    * <p>
812    * Examples w/ <code>major.minor</code>:
813    * <pre>
814    *    1.00 (ES 2.0), 3.00 (ES 3.0)
815    *    1.10 (GL 2.0), 1.20 (GL 2.1), 1.50 (GL 3.2),
816    *    3.30 (GL 3.3), 4.00 (GL 4.0), 4.10 (GL 4.1), 4.20 (GL 4.2)
817    * </pre >
818    * </p>
819    * <p>
820    * <i>Matching</i> could also refer to the maximum GLSL version usable by this context
821    * since <i>normal</i> GL implementations are capable of using a lower GLSL version as well.
822    * The latter is not true on OSX w/ a GL3 context.
823    * </p>
824    *
825    * @return GLSL version number if context has been made current at least once,
826    *         otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
827    *
828    * @see #getGLVersionNumber()
829    */
getGLSLVersionNumber()830   public final VersionNumber getGLSLVersionNumber() {
831       return ctxGLSLVersion;
832   }
833 
834   /**
835    * Returns the GLSL version string as to be used in a shader program, including a terminating newline '\n',
836    * i.e. for desktop
837    * <pre>
838    *    #version 110
839    *    ..
840    *    #version 150 core
841    *    #version 330 compatibility
842    *    ...
843    * </pre>
844    * And for ES:
845    * <pre>
846    *    #version 100
847    *    #version 300 es
848    *    ..
849    * </pre>
850    * <p>
851    * If context has not been made current yet, a string of zero length is returned.
852    * </p>
853    * @see #getGLSLVersionNumber()
854    */
getGLSLVersionString()855   public final String getGLSLVersionString() {
856       if( ctxGLSLVersion.isZero() ) {
857           return S_EMPTY;
858       }
859       final int minor = ctxGLSLVersion.getMinor();
860       final String profileOpt;
861       if( isGLES() ) {
862           profileOpt = ctxGLSLVersion.compareTo(Version3_0) >= 0 ? " es" : S_EMPTY;
863       } else if( isGLCoreProfile() ) {
864           profileOpt = ctxGLSLVersion.compareTo(Version1_50) >= 0 ? " core" : S_EMPTY;
865       } else if( isGLCompatibilityProfile() ) {
866           profileOpt = ctxGLSLVersion.compareTo(Version1_50) >= 0 ? " compatibility" : S_EMPTY;
867       } else {
868           throw new InternalError("Neither ES, Core nor Compat: "+this); // see validateProfileBits(..)
869       }
870       return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + profileOpt + "\n" ;
871   }
872 
getStaticGLSLVersionNumber(final int glMajorVersion, final int glMinorVersion, final int ctxOptions)873   protected static final VersionNumber getStaticGLSLVersionNumber(final int glMajorVersion, final int glMinorVersion, final int ctxOptions) {
874       if( 0 != ( CTX_PROFILE_ES & ctxOptions ) ) {
875           if( 3 == glMajorVersion ) {
876               return Version3_0;           // ES 3.0  ->  GLSL 3.00
877           } else if( 2 == glMajorVersion ) {
878               return Version1_0;           // ES 2.0  ->  GLSL 1.00
879           }
880       } else if( 1 == glMajorVersion ) {
881           return Version1_10;               // GL 1.x  ->  GLSL 1.10
882       } else if( 2 == glMajorVersion ) {
883           switch ( glMinorVersion ) {
884               case 0:  return Version1_10;  // GL 2.0  ->  GLSL 1.10
885               default: return Version1_20;  // GL 2.1  ->  GLSL 1.20
886           }
887       } else if( 3 == glMajorVersion && 2 >= glMinorVersion ) {
888           switch ( glMinorVersion ) {
889               case 0:  return Version1_30;  // GL 3.0  ->  GLSL 1.30
890               case 1:  return Version1_40;  // GL 3.1  ->  GLSL 1.40
891               default: return Version1_50;  // GL 3.2  ->  GLSL 1.50
892           }
893       }
894       // The new default: GL >= 3.3, ES >= 3.0
895       return new VersionNumber(glMajorVersion, glMinorVersion * 10, 0); // GL M.N  ->  GLSL M.N
896   }
897 
898   /**
899    * @return true if this context is an ES2 context or implements
900    *         the extension <code>GL_ARB_ES3_compatibility</code> or <code>GL_ARB_ES2_compatibility</code>, otherwise false
901    */
isGLES2Compatible()902   public final boolean isGLES2Compatible() {
903       return 0 != ( ctxOptions & ( CTX_IMPL_ES3_COMPAT | CTX_IMPL_ES2_COMPAT ) ) ;
904   }
905 
906   /**
907    * Return true if this context is an ES3 context or implements
908    * the extension <code>GL_ARB_ES3_compatibility</code>, otherwise false.
909    * <p>
910    * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
911    * </p>
912    */
isGLES3Compatible()913   public final boolean isGLES3Compatible() {
914       return 0 != ( ctxOptions & CTX_IMPL_ES3_COMPAT ) ;
915   }
916 
917   /**
918    * Return true if this context is an ES3 context &ge; 3.1 or implements
919    * the extension <code>GL_ARB_ES3_1_compatibility</code>, otherwise false.
920    * <p>
921    * Includes [ GL &ge; 4.5, GL &ge; 3.1 w/ GL_ARB_ES3_1_compatibility and GLES3 &ge; 3.1 ]
922    * </p>
923    */
isGLES31Compatible()924   public final boolean isGLES31Compatible() {
925       return 0 != ( ctxOptions & CTX_IMPL_ES31_COMPAT ) ;
926   }
927 
928   /**
929    * Return true if this context is an ES3 context &ge; 3.2 or implements
930    * the extension <code>GL_ARB_ES3_2_compatibility</code>, otherwise false.
931    * <p>
932    * Includes [ GL &ge; 4.5, GL &ge; 3.1 w/ GL_ARB_ES3_2_compatibility and GLES3 &ge; 3.2 ]
933    * </p>
934    */
isGLES32Compatible()935   public final boolean isGLES32Compatible() {
936       return 0 != ( ctxOptions & CTX_IMPL_ES32_COMPAT ) ;
937   }
938 
939   /**
940    * @return true if impl. is a hardware rasterizer, otherwise false.
941    * @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile)
942    * @see GLProfile#isHardwareRasterizer()
943    */
isHardwareRasterizer()944   public final boolean isHardwareRasterizer() {
945       return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
946   }
947 
948   /**
949    * @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.
950    * @see GLProfile#hasGLSL()
951    */
hasGLSL()952   public final boolean hasGLSL() {
953       return isGLES3() ||
954              isGLES2() ||
955              isGL3() ||
956              isGL2() && ctxVersion.getMajor()>1 ;
957   }
958 
959   /**
960    * Returns <code>true</code> if basic FBO support is available, otherwise <code>false</code>.
961    * <p>
962    * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= 3.0 [core, compat] or implements the extensions
963    * <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>.
964    * </p>
965    * <p>
966    * Basic FBO support may only include one color attachment and no multisampling,
967    * as well as limited internal formats for renderbuffer.
968    * </p>
969    * @see #CTX_IMPL_FBO
970    */
hasBasicFBOSupport()971   public final boolean hasBasicFBOSupport() {
972       return 0 != ( ctxOptions & CTX_IMPL_FBO ) ;
973   }
974 
975   /**
976    * Returns <code>true</code> if full FBO support is available, otherwise <code>false</code>.
977    * <p>
978    * Full FBO is supported if the context is either GL >= 3.0 [ES, core, compat] or implements the extensions
979    * <code>ARB_framebuffer_object</code>, or all of
980    * <code>EXT_framebuffer_object</code>, <code>EXT_framebuffer_multisample</code>,
981    * <code>EXT_framebuffer_blit</code>, <code>GL_EXT_packed_depth_stencil</code>.
982    * </p>
983    * <p>
984    * Full FBO support includes multiple color attachments and multisampling.
985    * </p>
986    */
hasFullFBOSupport()987   public final boolean hasFullFBOSupport() {
988       return hasBasicFBOSupport() && !hasRendererQuirk(GLRendererQuirks.NoFullFBOSupport) &&
989              ( isGL3ES3() ||                                                      // GL >= 3.0 [ES, core, compat]
990                isExtensionAvailable(GLExtensions.ARB_framebuffer_object) ||       // ARB_framebuffer_object
991                ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) &&     // All EXT_framebuffer_object*
992                  isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
993                  isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
994                  isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil)
995                )
996              ) ;
997   }
998 
999   /**
1000    * Returns <code>true</code> if <code>OES_single_precision</code>, fp32, fixed function point (FFP) compatibility entry points available,
1001    * otherwise <code>false</code>.
1002    * @see #CTX_IMPL_FP32_COMPAT_API
1003    */
hasFP32CompatAPI()1004   public final boolean hasFP32CompatAPI() {
1005       return 0 != ( ctxOptions & CTX_IMPL_FP32_COMPAT_API ) ;
1006   }
1007 
1008   /**
1009    * Returns the maximum number of FBO RENDERBUFFER samples
1010    * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false.
1011    */
getMaxRenderbufferSamples()1012   public final int getMaxRenderbufferSamples() {
1013       if( hasFullFBOSupport() ) {
1014           final GL gl = getGL();
1015           final int[] val = new int[] { 0 } ;
1016           try {
1017               gl.glGetIntegerv(GL.GL_MAX_SAMPLES, val, 0);
1018               final int glerr = gl.glGetError();
1019               if(GL.GL_NO_ERROR == glerr) {
1020                   return val[0];
1021               } else if(DEBUG) {
1022                   System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
1023               }
1024           } catch (final GLException gle) { gle.printStackTrace(); }
1025       }
1026       return 0;
1027   }
1028 
1029   /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns <code>true</code>. */
isNPOTTextureAvailable()1030   public boolean isNPOTTextureAvailable() {
1031       return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
1032   }
1033 
isTextureFormatBGRA8888Available()1034   public boolean isTextureFormatBGRA8888Available() {
1035       return isGL2GL3() ||
1036              isExtensionAvailable(GLExtensions.EXT_texture_format_BGRA8888) ||
1037              isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ;
1038   }
1039 
1040   /**
1041    * Indicates whether this GLContext is capable of GL4bc.  <p>Includes [ GL4bc ].</p>
1042    * @see GLProfile#isGL4bc()
1043    */
isGL4bc()1044   public final boolean isGL4bc() {
1045       return 0 != (ctxOptions & CTX_PROFILE_COMPAT) &&
1046              ctxVersion.getMajor() >= 4;
1047   }
1048 
1049   /**
1050    * Indicates whether this GLContext is capable of GL4.    <p>Includes [ GL4bc, GL4 ].</p>
1051    * @see GLProfile#isGL4()
1052    */
isGL4()1053   public final boolean isGL4() {
1054       return 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) &&
1055              ctxVersion.getMajor() >= 4;
1056   }
1057 
1058   /**
1059    * Indicates whether this GLContext uses a GL4 core profile. <p>Includes [ GL4 ].</p>
1060    */
isGL4core()1061   public final boolean isGL4core() {
1062       return 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
1063              ctxVersion.getMajor() >= 4;
1064   }
1065 
1066   /**
1067    * Indicates whether this GLContext is capable of GL3bc.  <p>Includes [ GL4bc, GL3bc ].</p>
1068    * @see GLProfile#isGL3bc()
1069    */
isGL3bc()1070   public final boolean isGL3bc() {
1071       return 0 != (ctxOptions & CTX_PROFILE_COMPAT) &&
1072              ctxVersion.compareTo(Version3_1) >= 0 ;
1073   }
1074 
1075   /**
1076    * Indicates whether this GLContext is capable of GL3.    <p>Includes [ GL4bc, GL4, GL3bc, GL3 ].</p>
1077    * @see GLProfile#isGL3()
1078    */
isGL3()1079   public final boolean isGL3() {
1080       return 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)) &&
1081              ctxVersion.compareTo(Version3_1) >= 0 ;
1082   }
1083 
1084   /**
1085    * Indicates whether this GLContext uses a GL3 core profile. <p>Includes [ GL4, GL3 ].</p>
1086    */
isGL3core()1087   public final boolean isGL3core() {
1088       return 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
1089              ctxVersion.compareTo(Version3_1) >= 0;
1090   }
1091 
1092   /**
1093    * Indicates whether this GLContext uses a GL core profile. <p>Includes [ GL4, GL3, GLES3, GLES2 ].</p>
1094    */
isGLcore()1095   public final boolean isGLcore() {
1096       return ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 2 ) ||
1097              ( 0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
1098                ctxVersion.compareTo(Version3_1) >= 0
1099              ) ;
1100   }
1101 
1102   /**
1103    * Indicates whether this GLContext allows CPU data sourcing (indices, vertices ..) as opposed to using a GPU buffer source (VBO),
1104    * e.g. {@link GL2#glDrawElements(int, int, int, java.nio.Buffer)}.
1105    * <p>Includes [GL2ES1, GLES2] == [ GL4bc, GL3bc, GL2, GLES1, GL2ES1, GLES2 ].</p>
1106    * <p>See Bug 852 - https://jogamp.org/bugzilla/show_bug.cgi?id=852 </p>
1107    */
isCPUDataSourcingAvail()1108   public final boolean isCPUDataSourcingAvail() {
1109       return isGL2ES1() || isGLES2();
1110   }
1111 
1112   /**
1113    * Indicates whether this GLContext's native profile does not implement a <i>default vertex array object</i> (VAO),
1114    * starting w/ OpenGL 3.1 core.
1115    * <p>Includes [ GL4, GL3 ].</p>
1116    * <pre>
1117      Due to GL 3.1 core spec: E.1. DEPRECATED AND REMOVED FEATURES (p 296),
1118             GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331)
1119      there is no more default VAO buffer 0 bound, hence generating and binding one
1120      to avoid INVALID_OPERATION at VertexAttribPointer.
1121      More clear is GL 4.3 core spec: 10.4 (p 307).
1122    * </pre>
1123    * <pre>
1124      ES 3.x is <i>not</i> included here.
1125      Due to it's ES 2.0 backward compatibility it still supports the following features:
1126             <i>client side vertex arrays</i>
1127             <i>default vertex array object</i>
1128 
1129      Binding a custom VAO with ES 3.0 would cause <i>client side vertex arrays</i> via {@link GL2ES1#glVertexPointer(int, int, int, java.nio.Buffer) glVertexPointer}
1130      to produce <code>GL_INVALID_OPERATION</code>.
1131 
1132      However, they are marked <i>deprecated</i>:
1133             GL ES 3.0 spec F.1. Legacy Features (p 322).
1134             GL ES 3.1 spec F.1. Legacy Features (p 454).
1135    * </pre>
1136    * <p>
1137    * If no default VAO is implemented in the native OpenGL profile,
1138    * an own default VAO is being used, see {@link #getDefaultVAO()}.
1139    * </p>
1140    * @see #getDefaultVAO()
1141    */
hasNoDefaultVAO()1142   public final boolean hasNoDefaultVAO() {
1143       return // ES 3.x not included, see above. ( 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() >= 3 ) ||
1144              ( 0 != ( ctxOptions & CTX_IS_ARB_CREATED ) &&
1145                0 != ( ctxOptions & CTX_PROFILE_CORE ) &&
1146                ctxVersion.compareTo(Version3_1) >= 0
1147              ) ;
1148   }
1149 
1150   /**
1151    * If this GLContext does not implement a default VAO, see {@link #hasNoDefaultVAO()},
1152    * an <i>own default VAO</i> will be created and bound at context creation.
1153    * <p>
1154    * If this GLContext does implement a default VAO, i.e. {@link #hasNoDefaultVAO()}
1155    * returns <code>false</code>, this method returns <code>0</code>.
1156    * </p>
1157    * <p>
1158    * Otherwise this method returns the VAO object name
1159    * representing this GLContext's <i>own default VAO</i>.
1160    * </p>
1161    * @see #hasNoDefaultVAO()
1162    */
getDefaultVAO()1163   public abstract int getDefaultVAO();
1164 
1165   /**
1166    * Indicates whether this GLContext is capable of GL2.    <p>Includes [ GL4bc, GL3bc, GL2  ].</p>
1167    * @see GLProfile#isGL2()
1168    */
isGL2()1169   public final boolean isGL2() {
1170       return 0 != ( ctxOptions & CTX_PROFILE_COMPAT ) && ctxVersion.getMajor()>=1 ;
1171   }
1172 
1173   /**
1174    * Indicates whether this GLContext is capable of GL2GL3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GL2, GL2GL3 ].</p>
1175    * @see GLProfile#isGL2GL3()
1176    */
isGL2GL3()1177   public final boolean isGL2GL3() {
1178       return isGL2() || isGL3();
1179   }
1180 
1181   /**
1182    * Indicates whether this GLContext is capable of GLES1.  <p>Includes [ GLES1 ].</p>
1183    * @see GLProfile#isGLES1()
1184    */
isGLES1()1185   public final boolean isGLES1() {
1186       return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 1 ;
1187   }
1188 
1189   /**
1190    * Indicates whether this GLContext is capable of GLES2.  <p>Includes [ GLES2, GLES3 ].</p>
1191    * @see GLProfile#isGLES2()
1192    */
isGLES2()1193   public final boolean isGLES2() {
1194       if( 0 != ( ctxOptions & CTX_PROFILE_ES ) ) {
1195           final int major = ctxVersion.getMajor();
1196           return 2 == major || 3 == major;
1197       } else {
1198           return false;
1199       }
1200   }
1201 
1202   /**
1203    * Indicates whether this GLContext is capable of GLES3.  <p>Includes [ GLES3 ].</p>
1204    * @see GLProfile#isGLES3()
1205    */
isGLES3()1206   public final boolean isGLES3() {
1207       return 0 != ( ctxOptions & CTX_PROFILE_ES ) && ctxVersion.getMajor() == 3 ;
1208   }
1209 
1210   /**
1211    * Indicates whether this GLContext is capable of GLES.  <p>Includes [ GLES3, GLES1, GLES2 ].</p>
1212    * @see GLProfile#isGLES()
1213    */
isGLES()1214   public final boolean isGLES() {
1215       return 0 != ( CTX_PROFILE_ES & ctxOptions ) ;
1216   }
1217 
1218   /**
1219    * Indicates whether this GLContext is capable of GL2ES1. <p>Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].</p>
1220    * @see GLProfile#isGL2ES1()
1221    */
isGL2ES1()1222   public final boolean isGL2ES1() {
1223       return isGLES1() || isGL2();
1224   }
1225 
1226   /**
1227    * Indicates whether this GLContext is capable of GL2ES2. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL2, GL2GL3, GL2ES2, GLES2 ].</p>
1228    * @see GLProfile#isGL2ES2()
1229    */
isGL2ES2()1230   public final boolean isGL2ES2() {
1231       return isGLES2() || isGL2GL3();
1232   }
1233 
1234   /**
1235    * Indicates whether this GLContext is capable of GL2ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3, GL3ES3, GL2, GL2GL3 ].</p>
1236    * @see GLProfile#isGL2ES3()
1237    * @see #isGL3ES3()
1238    * @see #isGL2GL3()
1239    */
isGL2ES3()1240   public final boolean isGL2ES3() {
1241       return isGL3ES3() || isGL2GL3();
1242   }
1243 
1244   /**
1245    * Indicates whether this GLContext is capable of GL3ES3. <p>Includes [ GL4bc, GL4, GL3bc, GL3, GLES3 ].</p>
1246    * @see GLProfile#isGL3ES3()
1247    */
isGL3ES3()1248   public final boolean isGL3ES3() {
1249       return isGL4ES3() || isGL3();
1250   }
1251 
1252   /**
1253    * Returns true if this profile is capable of GL4ES3, i.e. if {@link #isGLES3Compatible()} returns true.
1254    * <p>Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]</p>
1255    * @see GLProfile#isGL4ES3()
1256    */
isGL4ES3()1257   public final boolean isGL4ES3() {
1258       return isGLES3Compatible() ;
1259   }
1260 
1261   /**
1262    * Set the swap interval of the current context and attached <i>onscreen {@link GLDrawable}</i>.
1263    * <p>
1264    * <i>offscreen {@link GLDrawable}</i> are ignored and {@code false} is returned.
1265    * </p>
1266    * <p>
1267    * The {@code interval} semantics:
1268    * <ul>
1269    *   <li><i>0</i> disables the vertical synchronization</li>
1270    *   <li><i>&ge;1</i> is the number of vertical refreshes before a swap buffer occurs</li>
1271    *   <li><i>&lt;0</i> enables <i>late swaps to occur without synchronization to the video frame</i>, a.k.a <i>EXT_swap_control_tear</i>.
1272    *              If supported, the absolute value is the minimum number of
1273    *              video frames between buffer swaps. If not supported, the absolute value is being used, see above.
1274    *   </li>
1275    * </ul>
1276    * </p>
1277    * @param interval see above
1278    * @return true if the operation was successful, otherwise false
1279    * @throws GLException if the context is not current.
1280    * @see #getSwapInterval()
1281    */
setSwapInterval(final int interval)1282   public /* abstract */ boolean setSwapInterval(final int interval) throws GLException {
1283       // FIXME: Make abstract for next version - just here to *not* break SEMVER!
1284       throw new InternalError("Implemented in GLContextImpl");
1285   }
setSwapIntervalImpl(final int interval)1286   protected boolean setSwapIntervalImpl(final int interval) {
1287       // FIXME: Remove for next version - just here to *not* break SEMVER!
1288       throw new InternalError("Implemented in GLContextImpl");
1289   }
1290 
1291   /**
1292    * Return the current swap interval.
1293    * <p>
1294    * If the context has not been made current at all,
1295    * the default value {@code 0} is returned.
1296    * </p>
1297    * <p>
1298    * For a valid context w/ an <o>onscreen {@link GLDrawable}</i> the default value is {@code 1},
1299    * otherwise the default value is {@code 0}.
1300    * </p>
1301    * @see #setSwapInterval(int)
1302    */
getSwapInterval()1303   public /* abstract */ int getSwapInterval() {
1304       // FIXME: Make abstract for next version - just here to *not* break SEMVER!
1305       throw new InternalError("Implemented in GLContextImpl");
1306   }
1307 
setDefaultSwapInterval()1308   protected void setDefaultSwapInterval() {
1309       // FIXME: Remove for next version - just here to *not* break SEMVER!
1310       throw new InternalError("Implemented in GLContextImpl");
1311   }
1312 
queryMaxSwapGroups(final int[] maxGroups, final int maxGroups_offset, final int[] maxBarriers, final int maxBarriers_offset)1313   public final boolean queryMaxSwapGroups(final int[] maxGroups, final int maxGroups_offset,
1314                                           final int[] maxBarriers, final int maxBarriers_offset) {
1315     validateCurrent();
1316     return queryMaxSwapGroupsImpl(maxGroups, maxGroups_offset, maxBarriers, maxBarriers_offset);
1317   }
queryMaxSwapGroupsImpl(final int[] maxGroups, final int maxGroups_offset, final int[] maxBarriers, final int maxBarriers_offset)1318   protected boolean queryMaxSwapGroupsImpl(final int[] maxGroups, final int maxGroups_offset,
1319                                           final int[] maxBarriers, final int maxBarriers_offset) { return false; }
joinSwapGroup(final int group)1320   public final boolean joinSwapGroup(final int group) {
1321     validateCurrent();
1322     return joinSwapGroupImpl(group);
1323   }
joinSwapGroupImpl(final int group)1324   protected boolean joinSwapGroupImpl(final int group) { /** nop per default .. **/  return false; }
1325   protected int currentSwapGroup = -1; // default: not set yet ..
getSwapGroup()1326   public int getSwapGroup() {
1327       return currentSwapGroup;
1328   }
bindSwapBarrier(final int group, final int barrier)1329   public final boolean bindSwapBarrier(final int group, final int barrier) {
1330     validateCurrent();
1331     return bindSwapBarrierImpl(group, barrier);
1332   }
bindSwapBarrierImpl(final int group, final int barrier)1333   protected boolean bindSwapBarrierImpl(final int group, final int barrier) { /** nop per default .. **/  return false; }
1334 
1335   /**
1336    * Return the framebuffer name bound to this context,
1337    * see {@link GL#glBindFramebuffer(int, int)}.
1338    * <p>
1339    * Method is only thread-safe while context is {@link #makeCurrent() made current}.
1340    * </p>
1341    */
getBoundFramebuffer(int target)1342   public abstract int getBoundFramebuffer(int target);
1343 
1344   /**
1345    * Return the default draw framebuffer name.
1346    * <p>
1347    * May differ from it's default <code>zero</code>
1348    * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
1349    * is being used.
1350    * </p>
1351    * <p>
1352    * Method is only thread-safe while context is {@link #makeCurrent() made current}.
1353    * </p>
1354    */
getDefaultDrawFramebuffer()1355   public abstract int getDefaultDrawFramebuffer();
1356 
1357   /**
1358    * Return the default read framebuffer name.
1359    * <p>
1360    * May differ from it's default <code>zero</code>
1361    * in case an framebuffer object ({@link com.jogamp.opengl.FBObject}) based drawable
1362    * is being used.
1363    * </p>
1364    * <p>
1365    * Method is only thread-safe while context is {@link #makeCurrent() made current}.
1366    * </p>
1367    */
getDefaultReadFramebuffer()1368   public abstract int getDefaultReadFramebuffer();
1369 
1370   /**
1371    * Returns the default color buffer within the current bound
1372    * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​,
1373    * which will be used as the source for pixel reading commands,
1374    * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} etc.
1375    * <p>
1376    * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0},
1377    * otherwise this is {@link GL#GL_FRONT} for single buffer configurations
1378    * and {@link GL#GL_BACK} for double buffer configurations.
1379    * </p>
1380    * <p>
1381    * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
1382    * and {@link GL#GL_BACK} is the default.
1383    * </p>
1384    * <p>
1385    * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i
1386    * </p>
1387    * <p>
1388    * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead}
1389    * for read-pixels and swap-buffers implications.
1390    * </p>
1391    * <p>
1392    * Method is only thread-safe while context is {@link #makeCurrent() made current}.
1393    * </p>
1394    */
getDefaultReadBuffer()1395   public abstract int getDefaultReadBuffer();
1396 
1397   /**
1398    * Get the default pixel data type, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}.
1399    * <p>
1400    * Method is only thread-safe while context is {@link #makeCurrent() made current}.
1401    * </p>
1402    */
getDefaultPixelDataType()1403   public abstract int getDefaultPixelDataType();
1404 
1405   /**
1406    * Get the default pixel data format, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}.
1407    * <p>
1408    * Method is only thread-safe while context is {@link #makeCurrent() made current}.
1409    * </p>
1410    */
getDefaultPixelDataFormat()1411   public abstract int getDefaultPixelDataFormat();
1412 
1413   /**
1414    * @return The extension implementing the GLDebugOutput feature,
1415    *         either {@link GLExtensions#ARB_debug_output} or {@link GLExtensions#AMD_debug_output}.
1416    *         If unavailable or called before initialized via {@link #makeCurrent()}, <i>null</i> is returned.
1417    */
getGLDebugMessageExtension()1418   public abstract String getGLDebugMessageExtension();
1419 
1420   /**
1421    * @return the current synchronous debug behavior, set via {@link #setGLDebugSynchronous(boolean)}.
1422    */
isGLDebugSynchronous()1423   public abstract boolean isGLDebugSynchronous();
1424 
1425   /**
1426    * Enables or disables the synchronous debug behavior via
1427    * {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS glEnable/glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS)},
1428    * if extension is {@link GLExtensions#ARB_debug_output}.
1429    * There is no equivalent for {@link GLExtensions#AMD_debug_output}.
1430    * <p> The default is <code>true</code>, ie {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS}.</p>
1431    * @link {@link #isGLDebugSynchronous()}
1432    */
setGLDebugSynchronous(boolean synchronous)1433   public abstract void setGLDebugSynchronous(boolean synchronous);
1434 
1435   /**
1436    * @return true if the GLDebugOutput feature is enabled or not.
1437    */
isGLDebugMessageEnabled()1438   public abstract boolean isGLDebugMessageEnabled();
1439 
1440   /**
1441    * Enables or disables the GLDebugOutput feature of extension {@link GLExtensions#ARB_debug_output}
1442    * or {@link GLExtensions#AMD_debug_output}, if available.
1443    *
1444    * <p>To enable the GLDebugOutput feature {@link #enableGLDebugMessage(boolean) enableGLDebugMessage(true)}
1445    * or {@link #setContextCreationFlags(int) setContextCreationFlags}({@link GLContext#CTX_OPTION_DEBUG})
1446    * shall be called <b>before</b> context creation via {@link #makeCurrent()}!</p>
1447    *
1448    * <p>In case {@link GLAutoDrawable} are being used,
1449    * {@link GLAutoDrawable#setContextCreationFlags(int) glAutoDrawable.setContextCreationFlags}({@link GLContext#CTX_OPTION_DEBUG})
1450    * shall be issued before context creation via {@link #makeCurrent()}!</p>
1451    *
1452    * <p>After context creation, the GLDebugOutput feature may be enabled or disabled at any time using this method.</p>
1453    *
1454    * @param enable If true enables, otherwise disables the GLDebugOutput feature.
1455    *
1456    * @throws GLException if this context is not current or GLDebugOutput registration failed (enable)
1457    *
1458    * @see #setContextCreationFlags(int)
1459    * @see #addGLDebugListener(GLDebugListener)
1460    * @see GLAutoDrawable#setContextCreationFlags(int)
1461    */
enableGLDebugMessage(boolean enable)1462   public abstract void enableGLDebugMessage(boolean enable) throws GLException;
1463 
1464   /**
1465    * Add {@link GLDebugListener}.<br>
1466    *
1467    * @param listener {@link GLDebugListener} handling {@link GLDebugMessage}s
1468    * @see #enableGLDebugMessage(boolean)
1469    * @see #removeGLDebugListener(GLDebugListener)
1470    */
addGLDebugListener(GLDebugListener listener)1471   public abstract void addGLDebugListener(GLDebugListener listener);
1472 
1473   /**
1474    * Remove {@link GLDebugListener}.<br>
1475    *
1476    * @param listener {@link GLDebugListener} handling {@link GLDebugMessage}s
1477    * @see #enableGLDebugMessage(boolean)
1478    * @see #addGLDebugListener(GLDebugListener)
1479    */
removeGLDebugListener(GLDebugListener listener)1480   public abstract void removeGLDebugListener(GLDebugListener listener);
1481 
1482   /**
1483    * Generic entry for {@link GL2GL3#glDebugMessageControl(int, int, int, int, IntBuffer, boolean)}
1484    * and {@link GL2GL3#glDebugMessageEnableAMD(int, int, int, IntBuffer, boolean)} of the GLDebugOutput feature.
1485    * @see #enableGLDebugMessage(boolean)
1486    */
glDebugMessageControl(int source, int type, int severity, int count, IntBuffer ids, boolean enabled)1487   public abstract void glDebugMessageControl(int source, int type, int severity, int count, IntBuffer ids, boolean enabled);
1488 
1489   /**
1490    * Generic entry for {@link GL2GL3#glDebugMessageControl(int, int, int, int, int[], int, boolean)}
1491    * and {@link GL2GL3#glDebugMessageEnableAMD(int, int, int, int[], int, boolean)} of the GLDebugOutput feature.
1492    * @see #enableGLDebugMessage(boolean)
1493    */
glDebugMessageControl(int source, int type, int severity, int count, int[] ids, int ids_offset, boolean enabled)1494   public abstract void glDebugMessageControl(int source, int type, int severity, int count, int[] ids, int ids_offset, boolean enabled);
1495 
1496   /**
1497    * Generic entry for {@link GL2GL3#glDebugMessageInsert(int, int, int, int, int, String)}
1498    * and {@link GL2GL3#glDebugMessageInsertAMD(int, int, int, int, String)} of the GLDebugOutput feature.
1499    * @see #enableGLDebugMessage(boolean)
1500    */
glDebugMessageInsert(int source, int type, int id, int severity, String buf)1501   public abstract void glDebugMessageInsert(int source, int type, int id, int severity, String buf);
1502 
1503   public static final int GL_VERSIONS[][] = {
1504       /* 0.*/ { -1 },
1505       /* 1.*/ { 0, 1, 2, 3, 4, 5 },
1506       /* 2.*/ { 0, 1 },
1507       /* 3.*/ { 0, 1, 2, 3 },
1508       /* 4.*/ { 0, 1, 2, 3, 4, 5 } };
1509 
1510   public static final int ES_VERSIONS[][] = {
1511       /* 0.*/ { -1 },
1512       /* 1.*/ { 0, 1 },
1513       /* 2.*/ { 0 },
1514       /* 3.*/ { 0, 1, 2 } };
1515 
getMaxMajor(final int ctxProfile)1516   public static final int getMaxMajor(final int ctxProfile) {
1517       return ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ? ES_VERSIONS.length-1 : GL_VERSIONS.length-1;
1518   }
1519 
getMaxMinor(final int ctxProfile, final int major)1520   public static final int getMaxMinor(final int ctxProfile, final int major) {
1521       if( 1>major ) {
1522           return -1;
1523       }
1524       if( ( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) ) {
1525           if( major>=ES_VERSIONS.length ) return -1;
1526           return ES_VERSIONS[major].length-1;
1527       } else {
1528           if( major>=GL_VERSIONS.length ) return -1;
1529           return GL_VERSIONS[major].length-1;
1530       }
1531   }
1532 
1533   /**
1534    * Returns true, if the major.minor is not inferior to the lowest
1535    * valid version and does not exceed the highest known major number by more than one.
1536    * <p>
1537    * The minor version number is ignored by the upper limit validation
1538    * and the major version number may exceed by one.
1539    * </p>
1540    * <p>
1541    * The upper limit check is relaxed since we don't want to cut-off
1542    * unforseen new GL version since the release of JOGL.
1543    * </p>
1544    * <p>
1545    * Hence it is important to iterate through GL version from the upper limit
1546    * and {@link #decrementGLVersion(int, int[], int[])} until invalid.
1547    * </p>
1548    */
isValidGLVersion(final int ctxProfile, final int major, final int minor)1549   public static final boolean isValidGLVersion(final int ctxProfile, final int major, final int minor) {
1550       if( 1>major || 0>minor ) {
1551           return false;
1552       }
1553       if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
1554           if( major >= ES_VERSIONS.length + 1 ) return false;
1555       } else {
1556           if( major>=GL_VERSIONS.length + 1 ) return false;
1557       }
1558       return true;
1559   }
1560 
1561   /**
1562    * Clip the given GL version to the maximum known valid version if exceeding.
1563    * @return true if clipped, i.e. given value exceeds maximum, otherwise false.
1564    */
clipGLVersion(final int ctxProfile, final int major[], final int minor[])1565   public static final boolean clipGLVersion(final int ctxProfile, final int major[], final int minor[]) {
1566       final int m = major[0];
1567       final int n = minor[0];
1568 
1569       if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
1570           if( m >= ES_VERSIONS.length ) {
1571               major[0] = ES_VERSIONS.length - 1;
1572               minor[0] = ES_VERSIONS[major[0]].length - 1;
1573               return true;
1574           }
1575           if( n  >= ES_VERSIONS[m].length ) {
1576               minor[0] = ES_VERSIONS[m].length - 1;
1577               return true;
1578           }
1579       } else if( m >= GL_VERSIONS.length ) { // !isES
1580           major[0] = GL_VERSIONS.length - 1;
1581           minor[0] = GL_VERSIONS[major[0]].length - 1;
1582           return true;
1583       } else if( n  >= GL_VERSIONS[m].length ) { // !isES
1584           minor[0] = GL_VERSIONS[m].length - 1;
1585           return true;
1586       }
1587       return false;
1588   }
1589 
1590   /**
1591    * Decrement the given GL version by one
1592    * and return true if still valid, otherwise false.
1593    * <p>
1594    * If the given version exceeds the maximum known valid version,
1595    * it is {@link #clipGLVersion(int, int[], int[]) clipped} and
1596    * true is returned.
1597    * </p>
1598    *
1599    * @param ctxProfile
1600    * @param major
1601    * @param minor
1602    * @return
1603    */
decrementGLVersion(final int ctxProfile, final int major[], final int minor[])1604   public static final boolean decrementGLVersion(final int ctxProfile, final int major[], final int minor[]) {
1605       if( !clipGLVersion(ctxProfile, major, minor) ) {
1606           int m = major[0];
1607           int n = minor[0] - 1;
1608           if(n < 0) {
1609               if( 0 != ( CTX_PROFILE_ES & ctxProfile ) ) {
1610                   if( m >= 3 ) {
1611                       m -= 1;
1612                   } else {
1613                       m = 0; // major decr [1,2] -> 0
1614                   }
1615                   n = ES_VERSIONS[m].length-1;
1616               } else {
1617                   m -= 1;
1618                   n = GL_VERSIONS[m].length-1;
1619               }
1620           }
1621           if( !isValidGLVersion(ctxProfile, m, n) ) {
1622               return false;
1623           }
1624           major[0]=m;
1625           minor[0]=n;
1626       }
1627       return true;
1628   }
1629 
composeBits(final int a8, final int b8, final int c16)1630   protected static int composeBits(final int a8, final int b8, final int c16) {
1631     return  ( ( a8    & 0x000000FF ) << 24 ) |
1632             ( ( b8    & 0x000000FF ) << 16 ) |
1633             ( ( c16   & 0x0000FFFF )       ) ;
1634   }
decomposeBits(final int bits32, final int[] ctp)1635   protected static VersionNumber decomposeBits(final int bits32, final int[] ctp) {
1636       final int major = ( bits32 & 0xFF000000 ) >>> 24 ;
1637       final int minor = ( bits32 & 0x00FF0000 ) >>> 16 ;
1638       ctp[0]          = ( bits32 & 0x0000FFFF )        ;
1639       return new VersionNumber(major, minor, 0);
1640   }
1641 
validateProfileBits(final int bits, final String argName)1642   private static void validateProfileBits(final int bits, final String argName) {
1643     int num = 0;
1644     if( 0 != ( CTX_PROFILE_COMPAT & bits ) ) { num++; }
1645     if( 0 != ( CTX_PROFILE_CORE   & bits ) ) { num++; }
1646     if( 0 != ( CTX_PROFILE_ES     & bits ) ) { num++; }
1647     if(1!=num) {
1648         throw new GLException("Internal Error: "+argName+": 1 != num-profiles: "+num);
1649     }
1650   }
1651 
1652   //
1653   // version mapping
1654   //
1655 
1656   /**
1657    * @see #getDeviceVersionAvailableKey(com.jogamp.nativewindow.AbstractGraphicsDevice, int, int)
1658    */
1659   protected static final IdentityHashMap<String, Integer> deviceVersionAvailable = new IdentityHashMap<String, Integer>();
1660 
1661   /**
1662    * @see #getUniqueDeviceString(com.jogamp.nativewindow.AbstractGraphicsDevice)
1663    */
1664   private static final IdentityHashMap<String, String> deviceVersionsAvailableSet = new IdentityHashMap<String, String>();
1665 
1666   /** clears the device/context mappings as well as the GL/GLX proc address tables. */
shutdown()1667   protected static void shutdown() {
1668       deviceVersionAvailable.clear();
1669       deviceVersionsAvailableSet.clear();
1670       GLContextImpl.shutdownImpl(); // well ..
1671   }
1672 
getAvailableGLVersionsSet(final AbstractGraphicsDevice device)1673   protected static boolean getAvailableGLVersionsSet(final AbstractGraphicsDevice device) {
1674       synchronized ( deviceVersionsAvailableSet ) {
1675         return deviceVersionsAvailableSet.containsKey(device.getUniqueID());
1676       }
1677   }
1678 
setAvailableGLVersionsSet(final AbstractGraphicsDevice device, final boolean set)1679   protected static void setAvailableGLVersionsSet(final AbstractGraphicsDevice device, final boolean set) {
1680       synchronized ( deviceVersionsAvailableSet ) {
1681           final String devKey = device.getUniqueID();
1682           if( set ) {
1683               deviceVersionsAvailableSet.put(devKey, devKey);
1684           } else {
1685               deviceVersionsAvailableSet.remove(devKey);
1686           }
1687           if (DEBUG) {
1688             System.err.println(getThreadName() + ": createContextARB-MapGLVersions SET "+devKey);
1689             System.err.println(GLContext.dumpAvailableGLVersions(null).toString());
1690           }
1691       }
1692   }
1693 
1694   /**
1695    * Returns a unique String object using {@link String#intern()} for the given arguments,
1696    * which object reference itself can be used as a key.
1697    */
getDeviceVersionAvailableKey(final AbstractGraphicsDevice device, final int major, final int profile)1698   protected static String getDeviceVersionAvailableKey(final AbstractGraphicsDevice device, final int major, final int profile) {
1699       final String r = device.getUniqueID() + "-" + toHexString(composeBits(major, profile, 0));
1700       return r.intern();
1701   }
1702 
1703   /**
1704    * @deprecated Use {@link GLContextImpl#mapAvailableGLVersion(AbstractGraphicsDevice, int, int, VersionNumber, int)}
1705    */
mapAvailableGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int profile, final int resMajor, final int resMinor, int resCtp)1706   protected static Integer mapAvailableGLVersion(final AbstractGraphicsDevice device,
1707                                                  final int reqMajor, final int profile, final int resMajor, final int resMinor, int resCtp)
1708   {
1709     validateProfileBits(profile, "profile");
1710     validateProfileBits(resCtp, "resCtp");
1711 
1712     if(FORCE_NO_FBO_SUPPORT) {
1713         resCtp &= ~CTX_IMPL_FBO ;
1714     }
1715     if(DEBUG) {
1716         System.err.println(getThreadName() + ": createContextARB-MapGLVersions MAP "+device+": "+reqMajor+" ("+GLContext.getGLProfile(new StringBuilder(), profile).toString()+ ") -> "+getGLVersion(resMajor, resMinor, resCtp, null));
1717     }
1718     final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, profile);
1719     final Integer val = Integer.valueOf(composeBits(resMajor, resMinor, resCtp));
1720     synchronized(deviceVersionAvailable) {
1721         return deviceVersionAvailable.put( objectKey, val );
1722     }
1723   }
1724 
dumpAvailableGLVersions(StringBuilder sb)1725   protected static StringBuilder dumpAvailableGLVersions(StringBuilder sb) {
1726     if(null == sb) {
1727         sb = new StringBuilder();
1728     }
1729     synchronized(deviceVersionAvailable) {
1730         final Set<String> keys = deviceVersionAvailable.keySet();
1731         boolean needsSeparator = false;
1732         for(final Iterator<String> keyI = keys.iterator(); keyI.hasNext(); ) {
1733             if(needsSeparator) {
1734                 sb.append(Platform.getNewline());
1735             }
1736             final String key = keyI.next();
1737             sb.append("MapGLVersions ").append(key).append(": ");
1738             final Integer valI = deviceVersionAvailable.get(key);
1739             if(null != valI) {
1740                 final int[] ctp = { 0 };
1741                 final VersionNumber version = decomposeBits(valI.intValue(), ctp);
1742                 GLContext.getGLVersion(sb, version, ctp[0], null);
1743             } else {
1744                 sb.append("n/a");
1745             }
1746             needsSeparator = true;
1747         }
1748     }
1749     return sb;
1750   }
1751 
1752   /**
1753    * @param device the device to request whether the profile is available for
1754    * @param reqMajor Key Value either 1, 2, 3 or 4
1755    * @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
1756    * @return the available GL version as encoded with {@link #composeBits(int, int, int), otherwise <code>null</code>
1757    */
getAvailableGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)1758   protected static Integer getAvailableGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)  {
1759     final String objectKey = getDeviceVersionAvailableKey(device, reqMajor, reqProfile);
1760     Integer val;
1761     synchronized(deviceVersionAvailable) {
1762         val = deviceVersionAvailable.get( objectKey );
1763     }
1764     return val;
1765   }
1766 
1767   /**
1768    * @param reqMajor Key Value either 1, 2, 3 or 4
1769    * @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
1770    * @param major if not null, returns the used major version
1771    * @param minor if not null, returns the used minor version
1772    * @param ctp if not null, returns the used context profile
1773    */
getAvailableGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile, final int[] major, final int minor[], final int ctp[])1774   protected static boolean getAvailableGLVersion(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile,
1775                                                  final int[] major, final int minor[], final int ctp[]) {
1776 
1777     final Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
1778     if(null==valI) {
1779         return false;
1780     }
1781 
1782     final int bits32 = valI.intValue();
1783 
1784     if(null!=major) {
1785         major[0] = ( bits32 & 0xFF000000 ) >>> 24 ;
1786     }
1787     if(null!=minor) {
1788         minor[0] = ( bits32 & 0x00FF0000 ) >>> 16 ;
1789     }
1790     if(null!=ctp) {
1791         ctp[0]   = ( bits32 & 0x0000FFFF )       ;
1792     }
1793     return true;
1794   }
1795 
1796   /**
1797    * returns the highest GLProfile string regarding the implementation version and context profile bits.
1798    * @throws GLException if version and context profile bits could not be mapped to a GLProfile
1799    */
getGLProfile(final int major, final int minor, final int ctp)1800   protected static String getGLProfile(final int major, final int minor, final int ctp)
1801           throws GLException {
1802     if(0 != ( CTX_PROFILE_COMPAT & ctp )) {
1803         if(major >= 4)                            { return GLProfile.GL4bc; }
1804         else if(major == 3 && minor >= 1)         { return GLProfile.GL3bc; }
1805         else                                      { return GLProfile.GL2; }
1806     } else if(0 != ( CTX_PROFILE_CORE & ctp )) {
1807         if(major >= 4)                            { return GLProfile.GL4; }
1808         else if(major == 3 && minor >= 1)         { return GLProfile.GL3; }
1809     } else if(0 != ( CTX_PROFILE_ES & ctp )) {
1810         if(major == 3)                            { return GLProfile.GLES3; }
1811         else if(major == 2)                       { return GLProfile.GLES2; }
1812         else if(major == 1)                       { return GLProfile.GLES1; }
1813     }
1814     throw new GLException("Unhandled OpenGL version/profile: "+GLContext.getGLVersion(major, minor, ctp, null));
1815   }
1816 
1817   /**
1818    * Returns the GLProfile's major version number at reqMajorCTP[0] and it's context property (CTP) at reqMajorCTP[1] for availability mapping request.
1819    */
getRequestMajorAndCompat(final GLProfile glp, final int[ ] reqMajorCTP)1820   protected static final void getRequestMajorAndCompat(final GLProfile glp, final int[/*2*/] reqMajorCTP) {
1821     final GLProfile glpImpl = glp.getImpl();
1822     if( glpImpl.isGL4() ) {
1823         reqMajorCTP[0]=4;
1824     } else if ( glpImpl.isGL3() || glpImpl.isGLES3() ) {
1825         reqMajorCTP[0]=3;
1826     } else if (glpImpl.isGLES1()) {
1827         reqMajorCTP[0]=1;
1828     } else /* if (glpImpl.isGL2() || glpImpl.isGLES2()) */ {
1829         reqMajorCTP[0]=2;
1830     }
1831     if( glpImpl.isGLES() ) {
1832         reqMajorCTP[1]=CTX_PROFILE_ES;
1833     } else if( glpImpl.isGL2() ) { // incl GL3bc and GL4bc
1834         reqMajorCTP[1]=CTX_PROFILE_COMPAT;
1835     } else {
1836         reqMajorCTP[1]=CTX_PROFILE_CORE;
1837     }
1838   }
1839 
1840   /**
1841    * @param device the device the context profile is being requested for
1842    * @param GLProfile the GLProfile the context profile is being requested for
1843    * @return the GLProfile's context property (CTP) if available, otherwise <code>0</code>
1844    */
getAvailableContextProperties(final AbstractGraphicsDevice device, final GLProfile glp)1845   protected static final int getAvailableContextProperties(final AbstractGraphicsDevice device, final GLProfile glp) {
1846     final int[] reqMajorCTP = new int[] { 0, 0 };
1847     getRequestMajorAndCompat(glp, reqMajorCTP);
1848 
1849     final int _major[] = { 0 };
1850     final int _minor[] = { 0 };
1851     final int _ctp[] = { 0 };
1852     if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1], _major, _minor, _ctp)) {
1853       return _ctp[0];
1854     }
1855     return 0; // n/a
1856   }
1857 
1858   /**
1859    * @param device the device the profile is being requested
1860    * @param major Key Value either 1, 2, 3 or 4
1861    * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
1862    * @return the highest GLProfile for the device regarding availability, version and profile bits.
1863    */
getAvailableGLProfile(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)1864   protected static GLProfile getAvailableGLProfile(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)
1865           throws GLException {
1866     final String glpName = getAvailableGLProfileName(device, reqMajor, reqProfile);
1867     return null != glpName ? GLProfile.get(device, glpName) : null;
1868   }
1869 
1870   /**
1871    * @param device the device the profile is being requested
1872    * @param major Key Value either 1, 2, 3 or 4
1873    * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
1874    * @return the highest GLProfile name for the device regarding availability, version and profile bits.
1875    */
getAvailableGLProfileName(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)1876   /* package */ static String getAvailableGLProfileName(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile)
1877           throws GLException {
1878     final int major[] = { 0 };
1879     final int minor[] = { 0 };
1880     final int ctp[] = { 0 };
1881     if(GLContext.getAvailableGLVersion(device, reqMajor, reqProfile, major, minor, ctp)) {
1882         return GLContext.getGLProfile(major[0], minor[0], ctp[0]);
1883     }
1884     return null;
1885   }
1886 
1887   /**
1888    * @param device the device the profile is being requested
1889    * @param major Key Value either 1, 2, 3 or 4
1890    * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
1891    */
getAvailableGLVersionAsString(final AbstractGraphicsDevice device, final int major, final int profile)1892   protected static String getAvailableGLVersionAsString(final AbstractGraphicsDevice device, final int major, final int profile) {
1893     final int _major[] = { 0 };
1894     final int _minor[] = { 0 };
1895     final int _ctp[] = { 0 };
1896     if(getAvailableGLVersion(device, major, profile, _major, _minor, _ctp)) {
1897         return getGLVersion(_major[0], _minor[0], _ctp[0], null);
1898     }
1899     return null;
1900   }
1901 
1902   /**
1903    * Returns true if it is possible to create an <i>framebuffer object</i> (FBO).
1904    * <p>
1905    * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
1906    * </p>
1907    * <p>
1908    * FBO support is queried as described in {@link #hasBasicFBOSupport()}.
1909    * </p>
1910    *
1911    * @param device the device to request whether FBO is available for
1912    * @param glp {@link GLProfile} to check for FBO capabilities
1913    * @see GLContext#hasBasicFBOSupport()
1914    */
isFBOAvailable(final AbstractGraphicsDevice device, final GLProfile glp)1915   public static final boolean isFBOAvailable(final AbstractGraphicsDevice device, final GLProfile glp) {
1916       return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) );
1917   }
1918 
1919   /**
1920    * @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.
1921    * @see GLContext#isHardwareRasterizer()
1922    * @see GLProfile#isHardwareRasterizer()
1923    */
isHardwareRasterizer(final AbstractGraphicsDevice device, final GLProfile glp)1924   public static final int isHardwareRasterizer(final AbstractGraphicsDevice device, final GLProfile glp) {
1925       final int r;
1926       final int ctp = getAvailableContextProperties(device, glp);
1927       if(0 == ctp) {
1928           r = -1;
1929       } else if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
1930           r = 1;
1931       } else {
1932           r = 0;
1933       }
1934       return r;
1935   }
1936 
1937   /**
1938    * @param device the device to request whether the profile is available for
1939    * @param reqMajor Key Value either 1, 2, 3 or 4
1940    * @param reqProfile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
1941    * @param isHardware return value of one boolean, whether the profile is a hardware rasterizer or not
1942    * @return true if the requested GL version is available regardless of a software or hardware rasterizer, otherwise false.
1943    */
isGLVersionAvailable(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile, final boolean isHardware[])1944   protected static boolean isGLVersionAvailable(final AbstractGraphicsDevice device, final int reqMajor, final int reqProfile, final boolean isHardware[]) {
1945       final Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
1946       if(null==valI) {
1947           return false;
1948       }
1949       isHardware[0] = 0 == ( valI.intValue() & GLContext.CTX_IMPL_ACCEL_SOFT ) ;
1950       return true;
1951   }
1952 
isGLES1Available(final AbstractGraphicsDevice device, final boolean isHardware[])1953   public static boolean isGLES1Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
1954       return isGLVersionAvailable(device, 1, GLContext.CTX_PROFILE_ES, isHardware);
1955   }
1956 
isGLES2Available(final AbstractGraphicsDevice device, final boolean isHardware[])1957   public static boolean isGLES2Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
1958       return isGLVersionAvailable(device, 2, GLContext.CTX_PROFILE_ES, isHardware);
1959   }
1960 
isGLES3Available(final AbstractGraphicsDevice device, final boolean isHardware[])1961   public static boolean isGLES3Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
1962       return isGLVersionAvailable(device, 3, GLContext.CTX_PROFILE_ES, isHardware);
1963   }
1964 
getGL3ctp(final AbstractGraphicsDevice device)1965   private static final int getGL3ctp(final AbstractGraphicsDevice device) {
1966       final int major[] = { 0 };
1967       final int minor[] = { 0 };
1968       final int ctp[] = { 0 };
1969       boolean ok;
1970 
1971       ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_ES, major, minor, ctp);
1972       if( !ok ) {
1973           ok = GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_CORE, major, minor, ctp);
1974       }
1975       if( !ok ) {
1976           GLContext.getAvailableGLVersion(device, 3, GLContext.CTX_PROFILE_COMPAT, major, minor, ctp);
1977       }
1978       return ctp[0];
1979   }
1980 
1981   /**
1982    * Returns true if a ES3 compatible profile is available,
1983    * i.e. either a &ge; 4.3 context or a &ge; 3.1 context supporting <code>GL_ARB_ES3_compatibility</code>,
1984    * otherwise false.
1985    * <p>
1986    * Includes [ GL &ge; 4.3, GL &ge; 3.1 w/ GL_ARB_ES3_compatibility and GLES3 ]
1987    * </p>
1988    */
isGLES3CompatibleAvailable(final AbstractGraphicsDevice device)1989   public static final boolean isGLES3CompatibleAvailable(final AbstractGraphicsDevice device) {
1990       return 0 != ( getGL3ctp(device) & CTX_IMPL_ES3_COMPAT );
1991   }
1992   /**
1993    * Returns true if a ES3 &ge; 3.1 compatible profile is available,
1994    * i.e. either a &ge; 4.5 context or a &ge; 3.1 context supporting <code>GL_ARB_ES3_1_compatibility</code>,
1995    * otherwise false.
1996    * <p>
1997    * Includes [ GL &ge; 4.5, GL &ge; 3.1 w/ GL_ARB_ES3_1_compatibility and GLES3 &ge; 3.1 ]
1998    * </p>
1999    */
isGLES31CompatibleAvailable(final AbstractGraphicsDevice device)2000   public static final boolean isGLES31CompatibleAvailable(final AbstractGraphicsDevice device) {
2001       return 0 != ( getGL3ctp(device) & CTX_IMPL_ES31_COMPAT );
2002   }
2003   /**
2004    * Returns true if a ES3 &ge; 3.2 compatible profile is available,
2005    * i.e. either a &ge; 4.5 context or a &ge; 3.1 context supporting <code>GL_ARB_ES3_2_compatibility</code>,
2006    * otherwise false.
2007    * <p>
2008    * Includes [ GL &ge; 4.5, GL &ge; 3.1 w/ GL_ARB_ES3_2_compatibility and GLES3 &ge; 3.2 ]
2009    * </p>
2010    */
isGLES32CompatibleAvailable(final AbstractGraphicsDevice device)2011   public static final boolean isGLES32CompatibleAvailable(final AbstractGraphicsDevice device) {
2012       return 0 != ( getGL3ctp(device) & CTX_IMPL_ES32_COMPAT );
2013   }
2014 
isGL4bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[])2015   public static boolean isGL4bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[]) {
2016       return isGLVersionAvailable(device, 4, CTX_PROFILE_COMPAT, isHardware);
2017   }
2018 
isGL4Available(final AbstractGraphicsDevice device, final boolean isHardware[])2019   public static boolean isGL4Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
2020       return isGLVersionAvailable(device, 4, CTX_PROFILE_CORE, isHardware);
2021   }
2022 
isGL3bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[])2023   public static boolean isGL3bcAvailable(final AbstractGraphicsDevice device, final boolean isHardware[]) {
2024       return isGLVersionAvailable(device, 3, CTX_PROFILE_COMPAT, isHardware);
2025   }
2026 
isGL3Available(final AbstractGraphicsDevice device, final boolean isHardware[])2027   public static boolean isGL3Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
2028       return isGLVersionAvailable(device, 3, CTX_PROFILE_CORE, isHardware);
2029   }
2030 
isGL2Available(final AbstractGraphicsDevice device, final boolean isHardware[])2031   public static boolean isGL2Available(final AbstractGraphicsDevice device, final boolean isHardware[]) {
2032     return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT, isHardware);
2033   }
2034 
getGLProfile(final StringBuilder sb, final int ctp)2035   protected static StringBuilder getGLProfile(final StringBuilder sb, final int ctp) {
2036     boolean needColon = false;
2037     needColon = appendString(sb, "ES profile",            needColon, 0 != ( CTX_PROFILE_ES & ctp ));
2038     needColon = appendString(sb, "Compat profile",        needColon, 0 != ( CTX_PROFILE_COMPAT & ctp ));
2039     needColon = appendString(sb, "Core profile",          needColon, 0 != ( CTX_PROFILE_CORE & ctp ));
2040     needColon = appendString(sb, "forward",               needColon, 0 != ( CTX_OPTION_FORWARD & ctp ));
2041     needColon = appendString(sb, "arb",                   needColon, 0 != ( CTX_IS_ARB_CREATED & ctp ));
2042     needColon = appendString(sb, "debug",                 needColon, 0 != ( CTX_OPTION_DEBUG & ctp ));
2043     needColon = appendString(sb, "compat[",               needColon, true);
2044     {
2045         needColon = false;
2046         needColon = appendString(sb, "ES2",               needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp ));
2047         needColon = appendString(sb, "ES3",               needColon, 0 != ( CTX_IMPL_ES3_COMPAT & ctp ));
2048         needColon = appendString(sb, "ES31",              needColon, 0 != ( CTX_IMPL_ES31_COMPAT & ctp ));
2049         needColon = appendString(sb, "ES32",              needColon, 0 != ( CTX_IMPL_ES32_COMPAT & ctp ));
2050         needColon = appendString(sb, "FP32",              needColon, 0 != ( CTX_IMPL_FP32_COMPAT_API & ctp ));
2051         needColon = false;
2052     }
2053     needColon = appendString(sb, "]",                     needColon, true);
2054     needColon = appendString(sb, "FBO",                   needColon, 0 != ( CTX_IMPL_FBO & ctp ));
2055     if( 0 != ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
2056         needColon = appendString(sb, "software",          needColon, true);
2057     } else {
2058         needColon = appendString(sb, "hardware",          needColon, true);
2059     }
2060     return sb;
2061   }
getGLVersion(final StringBuilder sb, final VersionNumber version, final int ctp, final String gl_version)2062   protected static StringBuilder getGLVersion(final StringBuilder sb, final VersionNumber version, final int ctp, final String gl_version) {
2063       return getGLVersion(sb, version.getMajor(), version.getMinor(), ctp, gl_version);
2064   }
getGLVersion(final StringBuilder sb, final int major, final int minor, final int ctp, final String gl_version)2065   protected static StringBuilder getGLVersion(final StringBuilder sb, final int major, final int minor, final int ctp, final String gl_version) {
2066     sb.append(major);
2067     sb.append(".");
2068     sb.append(minor);
2069     sb.append(" (");
2070     getGLProfile(sb, ctp);
2071     sb.append(")");
2072     if(null!=gl_version) {
2073         sb.append(" - ");
2074         sb.append(gl_version);
2075     }
2076     return sb;
2077   }
getGLVersion(final int major, final int minor, final int ctp, final String gl_version)2078   protected static String getGLVersion(final int major, final int minor, final int ctp, final String gl_version) {
2079       return getGLVersion(new StringBuilder(), major, minor, ctp, gl_version).toString();
2080   }
2081 
2082   //
2083   // internal string utils
2084   //
2085 
toHexString(final int hex)2086   protected static String toHexString(final int hex) {
2087     return "0x" + Integer.toHexString(hex);
2088   }
2089 
toHexString(final long hex)2090   protected static String toHexString(final long hex) {
2091     return "0x" + Long.toHexString(hex);
2092   }
2093 
appendString(final StringBuilder sb, final String string, boolean needColon, final boolean condition)2094   private static boolean appendString(final StringBuilder sb, final String string, boolean needColon, final boolean condition) {
2095     if(condition) {
2096         if(needColon) {
2097             sb.append(", ");
2098         }
2099         sb.append(string);
2100         needColon=true;
2101     }
2102     return needColon;
2103   }
2104 
getThreadName()2105   protected static String getThreadName() { return Thread.currentThread().getName(); }
2106 
2107 }
2108 
2109