1 /*
2  * Copyright (c) 2002-2014 LWJGL Project
3  * 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  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions 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 'LWJGL' nor the names of
17  *   its contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package org.lwjgl.opengl;
33 
34 import org.lwjgl.BufferUtils;
35 import org.lwjgl.LWJGLUtil;
36 
37 import java.nio.IntBuffer;
38 import java.util.LinkedHashMap;
39 import java.util.Map.Entry;
40 
41 /**
42  * This class represents the context attributes passed to CreateContextAttribs of the ARB_create_context extension.
43  * <p/>
44  * The attributes supported are described in the following extensions:<br>
45  * <ul>
46  * <li><a href="http://www.opengl.org/registry/specs/ARB/wgl_create_context.txt">WGL_ARB_create_context(_profile)</a> and <a href="http://www.opengl.org/registry/specs/ARB/glx_create_context.txt">GLX_ARB_create_context(_profile)</a></li>
47  * <li><a href="http://www.opengl.org/registry/specs/ARB/wgl_create_context_robustness.txt">WGL_ARB_create_context_robustness</a> and <a href="http://www.opengl.org/registry/specs/ARB/glx_create_context_robustness.txt">GLX_ARB_create_context_robustness</a></li>
48  * <li><a href="http://www.opengl.org/registry/specs/ARB/wgl_robustness_isolation.txt">WGL_ARB_robustness_isolation</a> and <a href="http://www.opengl.org/registry/specs/ARB/glx_robustness_isolation.txt">GLX_ARB_robustness_isolation</a></li>
49  * <li><a href="http://www.opengl.org/registry/specs/ARB/wgl_create_context_es2_profile.txt">WGL_EXT_create_context_es2_profile</a> and <a href="http://www.opengl.org/registry/specs/ARB/glx_create_context_es2_profile.txt">GLX_EXT_create_context_es2_profile</a></li>
50  * <li><a href="http://www.opengl.org/registry/specs/ARB/context_flush_control.txt">KHR_context_flush_control</a></li>
51  * </ul>
52  * <p/>
53  * Use of this class is optional. If an OpenGL context is created without passing an instance of this class
54  * (or ARB_create_context is not supported), the old context creation code will be used. Support for debug and forward
55  * compatible mobes is not guaranteed by the OpenGL implementation. Developers may encounter debug contexts being the same
56  * as non-debug contexts or forward compatible contexts having support for deprecated functionality.
57  * <p/>
58  * If the {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB} flag is used, LWJGL will not load the deprecated functionality (as defined in the OpenGL 3.0
59  * specification), even if the driver exposes the corresponding entry points.
60  * <p/>
61  * This extension is not supported on MacOS X. However, in order to enable the GL 3.2 context on MacOS X 10.7 or newer, an instance of this class must be passed
62  * to LWJGL. The only valid configuration is <code>ContextAttribs(3, 2, CONTEXT_CORE_PROFILE_BIT_ARB)</code>, anything else will be ignored.
63  *
64  * @author spasi <spasi@users.sourceforge.net>
65  */
66 public final class ContextAttribs {
67 
68 	// ATTRIBUTES
69 
70 	public static final int CONTEXT_MAJOR_VERSION_ARB = 0x2091;
71 	public static final int CONTEXT_MINOR_VERSION_ARB = 0x2092;
72 
73 	public static final int CONTEXT_PROFILE_MASK_ARB = 0x9126,
74 		CONTEXT_CORE_PROFILE_BIT_ARB                 = 0x00000001,
75 		CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB        = 0x00000002,
76 		CONTEXT_ES2_PROFILE_BIT_EXT                  = 0x00000004;
77 
78 	public static final int CONTEXT_FLAGS_ARB = 0x2094,
79 		CONTEXT_DEBUG_BIT_ARB                 = 0x0001,
80 		CONTEXT_FORWARD_COMPATIBLE_BIT_ARB    = 0x0002,
81 		CONTEXT_ROBUST_ACCESS_BIT_ARB         = 0x00000004,
82 		CONTEXT_RESET_ISOLATION_BIT_ARB       = 0x00000008;
83 
84 	public static final int CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB = 0x8256,
85 		NO_RESET_NOTIFICATION_ARB                                   = 0x8261,
86 		LOSE_CONTEXT_ON_RESET_ARB                                   = 0x8252;
87 
88 	public static final int CONTEXT_RELEASE_BEHABIOR_ARB = 0x2097,
89 		CONTEXT_RELEASE_BEHAVIOR_NONE_ARB                = 0x0000,
90 		CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB               = 0x2098;
91 
92 	public static final int CONTEXT_LAYER_PLANE_ARB = 0x2093; // WGL-only
93 
94 	// STATE
95 
96 	private int majorVersion;
97 	private int minorVersion;
98 
99 	private int profileMask;
100 	private int contextFlags;
101 
102 	private int contextResetNotificationStrategy = NO_RESET_NOTIFICATION_ARB;
103 	private int contextReleaseBehavior           = CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB;
104 
105 	private int layerPlane;
106 
107 	// CONSTRUCTORS
108 
109 	/** Creates the default ContextAttribs instance. No special attributes will be used when creating the OpenGL context. */
ContextAttribs()110 	public ContextAttribs() {
111 		this(1, 0);
112 	}
113 
114 	/** Creates a ContextAttribs instance for the given OpenGL version. */
ContextAttribs(int majorVersion, int minorVersion)115 	public ContextAttribs(int majorVersion, int minorVersion) {
116 		this(majorVersion, minorVersion, 0, 0);
117 	}
118 
119 	/**
120 	 * Creates a new ContextAttribs instance with the given attributes.
121 	 *
122 	 * @param majorVersion the major OpenGL version
123 	 * @param minorVersion the minor OpenGL version
124 	 * @param profileMask  the context profile mask. One of:<br>{@link #CONTEXT_CORE_PROFILE_BIT_ARB}, {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB}, {@link #CONTEXT_ES2_PROFILE_BIT_EXT}
125 	 */
ContextAttribs(int majorVersion, int minorVersion, int profileMask)126 	public ContextAttribs(int majorVersion, int minorVersion, int profileMask) {
127 		this(majorVersion, minorVersion, 0, profileMask);
128 	}
129 
130 	/**
131 	 * Creates a new ContextAttribs instance with the given attributes.
132 	 *
133 	 * @param majorVersion the major OpenGL version
134 	 * @param minorVersion the minor OpenGL version
135 	 * @param profileMask  the context profile mask. One of:<br>{@link #CONTEXT_CORE_PROFILE_BIT_ARB}, {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB}, {@link #CONTEXT_ES2_PROFILE_BIT_EXT}
136 	 * @param contextFlags the context flags, a bitfield value. One or more of:<br>{@link #CONTEXT_DEBUG_BIT_ARB}, {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB}, {@link #CONTEXT_ROBUST_ACCESS_BIT_ARB}, {@link #CONTEXT_RESET_ISOLATION_BIT_ARB}
137 	 */
ContextAttribs(int majorVersion, int minorVersion, int profileMask, int contextFlags)138 	public ContextAttribs(int majorVersion, int minorVersion, int profileMask, int contextFlags) {
139 		if ( majorVersion < 0 || 4 < majorVersion ||
140 		     minorVersion < 0 ||
141 		     (majorVersion == 4 && 5 < minorVersion) ||
142 		     (majorVersion == 3 && 3 < minorVersion) ||
143 		     (majorVersion == 2 && 1 < minorVersion) ||
144 		     (majorVersion == 1 && 5 < minorVersion) )
145 			throw new IllegalArgumentException("Invalid OpenGL version specified: " + majorVersion + '.' + minorVersion);
146 
147 		if ( LWJGLUtil.CHECKS ) {
148 			if ( 1 < Integer.bitCount(profileMask) || CONTEXT_ES2_PROFILE_BIT_EXT < profileMask )
149 				throw new IllegalArgumentException("Invalid profile mask specified: " + Integer.toBinaryString(profileMask));
150 
151 			if ( 0xF < contextFlags )
152 				throw new IllegalArgumentException("Invalid context flags specified: " + Integer.toBinaryString(profileMask));
153 		}
154 
155 		this.majorVersion = majorVersion;
156 		this.minorVersion = minorVersion;
157 
158 		this.profileMask = profileMask;
159 		this.contextFlags = contextFlags;
160 	}
161 
162 	// Copy constructor
ContextAttribs(ContextAttribs other)163 	private ContextAttribs(ContextAttribs other) {
164 		this.majorVersion = other.majorVersion;
165 		this.minorVersion = other.minorVersion;
166 
167 		this.profileMask = other.profileMask;
168 		this.contextFlags = other.contextFlags;
169 
170 		this.contextResetNotificationStrategy = other.contextResetNotificationStrategy;
171 		this.contextReleaseBehavior = other.contextReleaseBehavior;
172 
173 		this.layerPlane = other.layerPlane;
174 	}
175 
176 	// GETTERS
177 
178 	/** Returns the {@link #CONTEXT_MAJOR_VERSION_ARB} value. */
getMajorVersion()179 	public int getMajorVersion() {
180 		return majorVersion;
181 	}
182 
183 	/** Returns the {@link #CONTEXT_MINOR_VERSION_ARB} value. */
getMinorVersion()184 	public int getMinorVersion() {
185 		return minorVersion;
186 	}
187 
188 	/** Returns the {@link #CONTEXT_PROFILE_MASK_ARB} value. */
getProfileMask()189 	public int getProfileMask() {
190 		return profileMask;
191 	}
192 
hasMask(int mask)193 	private boolean hasMask(int mask) {
194 		return profileMask == mask;
195 	}
196 
197 	/** Returns true if the {@link #CONTEXT_CORE_PROFILE_BIT_ARB} has been set. */
isProfileCore()198 	public boolean isProfileCore() {
199 		return hasMask(CONTEXT_CORE_PROFILE_BIT_ARB);
200 	}
201 
202 	/** Returns true if the {@link #CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB} has been set. */
isProfileCompatibility()203 	public boolean isProfileCompatibility() {
204 		return hasMask(CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
205 	}
206 
207 	/** Returns true if the {@link #CONTEXT_ES2_PROFILE_BIT_EXT} has been set. */
isProfileES()208 	public boolean isProfileES() {
209 		return hasMask(CONTEXT_ES2_PROFILE_BIT_EXT);
210 	}
211 
212 	/** Returns the {@link #CONTEXT_FLAGS_ARB} value. */
getContextFlags()213 	public int getContextFlags() {
214 		return contextFlags;
215 	}
216 
hasFlag(int flag)217 	private boolean hasFlag(int flag) {
218 		return (contextFlags & flag) != 0;
219 	}
220 
221 	/** Returns true if the {@link #CONTEXT_DEBUG_BIT_ARB} has been set. */
isDebug()222 	public boolean isDebug() {
223 		return hasFlag(CONTEXT_DEBUG_BIT_ARB);
224 	}
225 
226 	/** Returns true if the {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB} has been set. */
isForwardCompatible()227 	public boolean isForwardCompatible() {
228 		return hasFlag(CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
229 	}
230 
231 	/** Returns true if the {@link #CONTEXT_ROBUST_ACCESS_BIT_ARB} has been set. */
isRobustAccess()232 	public boolean isRobustAccess() { return hasFlag(CONTEXT_ROBUST_ACCESS_BIT_ARB); }
233 
234 	/** Returns true if the {@link #CONTEXT_RESET_ISOLATION_BIT_ARB} has been set. */
isContextResetIsolation()235 	public boolean isContextResetIsolation() {
236 		return hasFlag(CONTEXT_RESET_ISOLATION_BIT_ARB);
237 	}
238 
239 	/** Returns the {@link #CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB} value. */
getContextResetNotificationStrategy()240 	public int getContextResetNotificationStrategy() {
241 		return contextResetNotificationStrategy;
242 	}
243 
244 	/**
245 	 * Returns true if the {@link #CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB} has been set to {@link #LOSE_CONTEXT_ON_RESET_ARB}.
246 	 *
247 	 * @deprecated use {@link #getContextResetNotificationStrategy} instead
248 	 */
isLoseContextOnReset()249 	public boolean isLoseContextOnReset() { return contextResetNotificationStrategy == LOSE_CONTEXT_ON_RESET_ARB; }
250 
251 	/** Returns the {@link #CONTEXT_RELEASE_BEHABIOR_ARB} value. */
getContextReleaseBehavior()252 	public int getContextReleaseBehavior() {
253 		return contextReleaseBehavior;
254 	}
255 
256 	/** Returns the {@link #CONTEXT_LAYER_PLANE_ARB} value. */
getLayerPlane()257 	public int getLayerPlane() {
258 		return layerPlane;
259 	}
260 
261 	// CHAIN CONFIGURATION PATTERN
262 
toggleMask(int mask, boolean value)263 	private ContextAttribs toggleMask(int mask, boolean value) {
264 		if ( value == hasMask(mask) )
265 			return this;
266 
267 		ContextAttribs attribs = new ContextAttribs(this);
268 		attribs.profileMask = value ? mask : 0;
269 		return attribs;
270 	}
271 
272 	/**
273 	 * Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_CORE_PROFILE_BIT_ARB} bit in {@link #CONTEXT_PROFILE_MASK_ARB} set to the given value.
274 	 * If {@code profileCore} is true, all other bits in the mask are cleared.
275 	 */
withProfileCore(boolean profileCore)276 	public ContextAttribs withProfileCore(boolean profileCore) {
277 		if ( majorVersion < 3 || (majorVersion == 3 && minorVersion < 2) )
278 			throw new IllegalArgumentException("Profiles are only supported on OpenGL version 3.2 or higher.");
279 
280 		return toggleMask(CONTEXT_CORE_PROFILE_BIT_ARB, profileCore);
281 	}
282 
283 	/**
284 	 * Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB} bit in {@link #CONTEXT_PROFILE_MASK_ARB} set to the given value.
285 	 * If {@code profileCompatibility} is true, all other bits in the mask are cleared.
286 	 */
withProfileCompatibility(boolean profileCompatibility)287 	public ContextAttribs withProfileCompatibility(boolean profileCompatibility) {
288 		if ( majorVersion < 3 || (majorVersion == 3 && minorVersion < 2) )
289 			throw new IllegalArgumentException("Profiles are only supported on OpenGL version 3.2 or higher.");
290 
291 		return toggleMask(CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, profileCompatibility);
292 	}
293 
294 	/**
295 	 * Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_ES2_PROFILE_BIT_EXT} bit in {@link #CONTEXT_PROFILE_MASK_ARB} set to the given value.
296 	 * If {@code profileES} is true, all other bits in the mask are cleared.
297 	 */
withProfileES(boolean profileES)298 	public ContextAttribs withProfileES(boolean profileES) {
299 		if ( !(majorVersion == 2 && minorVersion == 0) )
300 			throw new IllegalArgumentException("The OpenGL ES profile is only supported on OpenGL version 2.0.");
301 
302 		return toggleMask(CONTEXT_ES2_PROFILE_BIT_EXT, profileES);
303 	}
304 
toggleFlag(int flag, boolean value)305 	private ContextAttribs toggleFlag(int flag, boolean value) {
306 		if ( value == hasFlag(flag) )
307 			return this;
308 
309 		ContextAttribs attribs = new ContextAttribs(this);
310 		attribs.contextFlags ^= flag; // toggle bit
311 		return attribs;
312 	}
313 
314 	/** Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_DEBUG_BIT_ARB} bit in {@link #CONTEXT_FLAGS_ARB} set to the given value. */
withDebug(boolean debug)315 	public ContextAttribs withDebug(boolean debug) { return toggleFlag(CONTEXT_DEBUG_BIT_ARB, debug); }
316 
317 	/** Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_FORWARD_COMPATIBLE_BIT_ARB} bit in {@link #CONTEXT_FLAGS_ARB} set to the given value. */
withForwardCompatible(boolean forwardCompatible)318 	public ContextAttribs withForwardCompatible(boolean forwardCompatible) { return toggleFlag(CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, forwardCompatible); }
319 
320 	/** Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_ROBUST_ACCESS_BIT_ARB} bit in {@link #CONTEXT_FLAGS_ARB} set to the given value. */
withRobustAccess(boolean robustAccess)321 	public ContextAttribs withRobustAccess(boolean robustAccess) { return toggleFlag(CONTEXT_ROBUST_ACCESS_BIT_ARB, robustAccess); }
322 
323 	/** Returns a new {@code ContextAttribs} instance with the {@link #CONTEXT_RESET_ISOLATION_BIT_ARB} bit in {@link #CONTEXT_FLAGS_ARB} set to the given value. */
withContextResetIsolation(boolean contextResetIsolation)324 	public ContextAttribs withContextResetIsolation(boolean contextResetIsolation) { return toggleFlag(CONTEXT_RESET_ISOLATION_BIT_ARB, contextResetIsolation); }
325 
326 	/**
327 	 * Returns a ContextAttribs instance with {@link #CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB} set to the given strategy. The default context reset notification
328 	 * strategy is {@link #NO_RESET_NOTIFICATION_ARB}.
329 	 *
330 	 * @param strategy the context reset notification strategy. One of:<br>{@link #NO_RESET_NOTIFICATION_ARB}, {@link #LOSE_CONTEXT_ON_RESET_ARB}
331 	 *
332 	 * @return the new ContextAttribs
333 	 */
withResetNotificationStrategy(int strategy)334 	public ContextAttribs withResetNotificationStrategy(int strategy) {
335 		if ( strategy == contextResetNotificationStrategy )
336 			return this;
337 
338 		if ( LWJGLUtil.CHECKS && !(strategy == NO_RESET_NOTIFICATION_ARB || strategy == LOSE_CONTEXT_ON_RESET_ARB) )
339 			throw new IllegalArgumentException("Invalid context reset notification strategy specified: 0x" + LWJGLUtil.toHexString(strategy));
340 
341 		ContextAttribs attribs = new ContextAttribs(this);
342 		attribs.contextResetNotificationStrategy = strategy;
343 		return attribs;
344 	}
345 
346 	/**
347 	 * Returns a ContextAttribs instance with {@link #CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB} set to {@link #LOSE_CONTEXT_ON_RESET_ARB} if the parameter is
348 	 * true or to {@link #NO_RESET_NOTIFICATION_ARB} if the parameter is false.
349 	 *
350 	 * @param loseContextOnReset the context reset notification strategy
351 	 *
352 	 * @return the new ContextAttribs
353 	 *
354 	 * @deprecated use {@link #withResetNotificationStrategy} instead
355 	 */
withLoseContextOnReset(boolean loseContextOnReset)356 	public ContextAttribs withLoseContextOnReset(boolean loseContextOnReset) {
357 		return withResetNotificationStrategy(loseContextOnReset ? LOSE_CONTEXT_ON_RESET_ARB : NO_RESET_NOTIFICATION_ARB);
358 	}
359 
360 	/**
361 	 * Returns a ContextAttribs instance with {@link #CONTEXT_RELEASE_BEHABIOR_ARB} set to the given behavior. The default context release behavior is
362 	 * {@link #CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB}.
363 	 *
364 	 * @param behavior the context release behavior. One of:<br>{@link #CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB}, {@link #CONTEXT_RELEASE_BEHAVIOR_NONE_ARB}
365 	 *
366 	 * @return the new ContextAttribs
367 	 */
withContextReleaseBehavior(int behavior)368 	public ContextAttribs withContextReleaseBehavior(int behavior) {
369 		if ( behavior == contextReleaseBehavior )
370 			return this;
371 
372 		if ( LWJGLUtil.CHECKS && !(behavior == CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB || behavior == CONTEXT_RELEASE_BEHAVIOR_NONE_ARB) )
373 			throw new IllegalArgumentException("Invalid context release behavior specified: 0x" + LWJGLUtil.toHexString(behavior));
374 
375 		ContextAttribs attribs = new ContextAttribs(this);
376 		attribs.contextReleaseBehavior = behavior;
377 		return attribs;
378 	}
379 
380 	/** Returns a new {@code ContextAttribs} instance with {@link #CONTEXT_LAYER_PLANE_ARB} set to the given value. */
withLayer(int layerPlane)381 	public ContextAttribs withLayer(int layerPlane) {
382 		if ( LWJGLUtil.getPlatform() != LWJGLUtil.PLATFORM_WINDOWS )
383 			throw new IllegalArgumentException("The CONTEXT_LAYER_PLANE_ARB attribute is supported only on the Windows platform.");
384 
385 		if ( layerPlane == this.layerPlane )
386 			return this;
387 
388 		if ( layerPlane < 0 )
389 			throw new IllegalArgumentException("Invalid layer plane specified: " + layerPlane);
390 
391 		ContextAttribs attribs = new ContextAttribs(this);
392 		attribs.layerPlane = layerPlane;
393 		return attribs;
394 	}
395 
getAttribList()396 	IntBuffer getAttribList() {
397 		if ( LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_MACOSX )
398 			return null;
399 
400 		LinkedHashMap<Integer, Integer> map = new LinkedHashMap<Integer, Integer>(8);
401 
402 		if ( !(majorVersion == 1 && minorVersion == 0) ) {
403 			map.put(CONTEXT_MAJOR_VERSION_ARB, majorVersion);
404 			map.put(CONTEXT_MINOR_VERSION_ARB, minorVersion);
405 		}
406 
407 		if ( contextFlags != 0 )
408 			map.put(CONTEXT_FLAGS_ARB, contextFlags);
409 
410 		if ( profileMask != 0 )
411 			map.put(CONTEXT_PROFILE_MASK_ARB, profileMask);
412 
413 		if ( contextResetNotificationStrategy != NO_RESET_NOTIFICATION_ARB )
414 			map.put(CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, contextResetNotificationStrategy);
415 
416 		if ( contextReleaseBehavior != CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB )
417 			map.put(CONTEXT_RELEASE_BEHABIOR_ARB, contextReleaseBehavior);
418 
419 		if ( layerPlane != 0 )
420 			map.put(CONTEXT_LAYER_PLANE_ARB, layerPlane);
421 
422 		if ( map.isEmpty() )
423 			return null;
424 
425 		IntBuffer attribs = BufferUtils.createIntBuffer((map.size() * 2) + 1);
426 		for ( Entry<Integer, Integer> attrib : map.entrySet() ) {
427 			attribs
428 				.put(attrib.getKey())
429 				.put(attrib.getValue());
430 		}
431 		attribs.put(0);
432 		attribs.rewind();
433 		return attribs;
434 	}
435 
toString()436 	public String toString() {
437 		StringBuilder sb = new StringBuilder(32);
438 
439 		sb.append("ContextAttribs:");
440 		sb.append(" Version=").append(majorVersion).append('.').append(minorVersion);
441 
442 		if ( profileMask != 0 ) {
443 			sb.append(", Profile=");
444 			if ( hasMask(CONTEXT_CORE_PROFILE_BIT_ARB) )
445 				sb.append("CORE");
446 			else if ( hasMask(CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) )
447 				sb.append("COMPATIBLITY");
448 			else if ( hasMask(CONTEXT_ES2_PROFILE_BIT_EXT) )
449 				sb.append("ES2");
450 			else
451 				sb.append("*unknown*");
452 		}
453 
454 		if ( contextFlags != 0 ) {
455 			if ( hasFlag(CONTEXT_DEBUG_BIT_ARB) )
456 				sb.append(", DEBUG");
457 			if ( hasFlag(CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) )
458 				sb.append(", FORWARD_COMPATIBLE");
459 			if ( hasFlag(CONTEXT_ROBUST_ACCESS_BIT_ARB) )
460 				sb.append(", ROBUST_ACCESS");
461 			if ( hasFlag(CONTEXT_RESET_ISOLATION_BIT_ARB) )
462 				sb.append(", RESET_ISOLATION");
463 		}
464 
465 		if ( contextResetNotificationStrategy != NO_RESET_NOTIFICATION_ARB )
466 			sb.append(", LOSE_CONTEXT_ON_RESET");
467 		if ( contextReleaseBehavior != CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB )
468 			sb.append(", RELEASE_BEHAVIOR_NONE");
469 
470 		if ( layerPlane != 0 )
471 			sb.append(", Layer=").append(layerPlane);
472 
473 		return sb.toString();
474 	}
475 
476 }