/// <summary>
		/// Process shader source lines to resolve #include directives.
		/// </summary>
		/// <param name="includeLibrary">
		/// A <see cref="ShaderIncludeLibrary"/> determining the shader include file system.
		/// </param>
		/// <param name="cctx">
		/// A <see cref="ShaderCompilerContext"/> that specify the compiler parameteres.
		/// </param>
		/// <param name="shaderSource">
		/// A <see cref="IEnumerable{String}"/> that specify the shader source lines. Null items in the enumeration
		/// will be ignored.
		/// </param>
		/// <returns>
		/// It returns the processed source lines <paramref name="shaderSource"/>, but without any #include directive. Each #include
		/// directive will be replaced by the corresponding text depending on <paramref name="cctx"/>.
		/// </returns>
		/// <remarks>
		/// <para>
		/// </para>
		/// </remarks>
		/// <exception cref="ArgumentNullException">
		/// Exception throw if <paramref name="includeLibrary"/>, <paramref name="cctx"/> or <paramref name="shaderSource"/> is null.
		/// </exception>
		public static List<string> Process(ShaderIncludeLibrary includeLibrary, ShaderCompilerContext cctx, List<string> shaderSource)
		{
			if (includeLibrary == null)
				throw new ArgumentNullException("includeLibrary");
			if (cctx == null)
				throw new ArgumentNullException("cctx");
			if (shaderSource == null)
				throw new ArgumentNullException("sSource");

			IncludeProcessorContext ictx = new IncludeProcessorContext();

			return (Process(includeLibrary, cctx, ictx, shaderSource));
		}
        /// <summary>
        /// Process shader source lines to resolve #include directives.
        /// </summary>
        /// <param name="includeLibrary">
        /// A <see cref="ShaderIncludeLibrary"/> determining the shader include file system.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specify the compiler parameteres.
        /// </param>
        /// <param name="shaderSource">
        /// A <see cref="IEnumerable{String}"/> that specify the shader source lines. Null items in the enumeration
        /// will be ignored.
        /// </param>
        /// <returns>
        /// It returns the processed source lines <paramref name="shaderSource"/>, but without any #include directive. Each #include
        /// directive will be replaced by the corresponding text depending on <paramref name="cctx"/>.
        /// </returns>
        /// <remarks>
        /// <para>
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// Exception throw if <paramref name="includeLibrary"/>, <paramref name="cctx"/> or <paramref name="shaderSource"/> is null.
        /// </exception>
        public static List <string> Process(ShaderIncludeLibrary includeLibrary, ShaderCompilerContext cctx, List <string> shaderSource)
        {
            if (includeLibrary == null)
            {
                throw new ArgumentNullException("includeLibrary");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }
            if (shaderSource == null)
            {
                throw new ArgumentNullException("sSource");
            }

            IncludeProcessorContext ictx = new IncludeProcessorContext();

            return(Process(includeLibrary, cctx, ictx, shaderSource));
        }
		/// <summary>
		/// Construct a GraphicsContext specifying the implemented OpenGL version.
		/// </summary>
		/// <param name="deviceContext">
		/// A <see cref="IDeviceContext"/> that specify the device context which has to be linked this
		/// this Render context.
		/// </param>
		/// <param name="sharedContext">
		/// A <see cref="GraphicsContext"/> that specify the render context which has to be linked this
		/// this Render context (to share resource with it).
		/// </param>
		/// <param name="version">
		/// A <see cref="KhronosVersion"/> that specify the minimum OpenGL version required to implement.
		/// </param>
		/// <param name="flags">
		/// A <see cref="GraphicsContextFlags"/> that specify special features to enable in the case they are supported.
		/// </param>
		/// <exception cref="ArgumentException">
		/// Exception thrown in the case <paramref name="version"/> is different from the currently implemented by the derive,
		/// and the OpenGL extension WGL_ARB_create_context_profile or WGL_ARB_create_context are not implemented.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// This exception is thrown in the case <paramref name="version"/> specify a forward compatible version (greater than or equal to
		/// <see cref="GLVersion.Version_3_2"/>), and the OpenGL extension WGL_ARB_create_context_profile or WGL_ARB_create_context
		/// are not implemented.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// This exception is thrown in the case <paramref name="devctx"/> is <see cref="IntPtr.Zero"/>.
		/// </exception>
		/// <exception cref="InvalidOperationException">
		/// This exception is thrown in the case it's not possible to create a valid OpenGL context.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// This exception is thrown if <paramref name="sharedContext"/> is not null and it was created by a thread different from the calling one.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// This exception is thrown if <paramref name="sharedContext"/> is not null and it is disposed.
		/// </exception>
		public GraphicsContext(IDeviceContext deviceContext, GraphicsContext sharedContext, KhronosVersion version, GraphicsContextFlags flags)
		{
			try {
				IntPtr sharedContextHandle = (sharedContext != null) ? sharedContext._RenderContext : IntPtr.Zero;

#if DEBUG
				_ConstructorStackTrace = Environment.StackTrace;
#endif

				// Store thread ID of the render context
				_RenderContextThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
				// Store thread ID of the device context
				_DeviceContextThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;

				if (deviceContext == null)
					throw new ArgumentNullException("deviceContext");
				if ((sharedContext != null) && (sharedContext._DeviceContext == null))
					throw new ArgumentException("shared context disposed", "hSharedContext");
				if ((sharedContext != null) && (sharedContext._RenderContextThreadId != _RenderContextThreadId))
					throw new ArgumentException("shared context created from another thread", "hSharedContext");
				if ((version != null) && (version != _CurrentVersion) && ((CurrentCaps.PlatformExtensions.CreateContext_ARB == false) && (CurrentCaps.PlatformExtensions.CreateContextProfile_ARB == false)))
					throw new ArgumentException("unable to specify OpenGL version when GL_ARB_create_context[_profile] is not supported");

				// Store device context handle
				_DeviceContext = deviceContext;
				_DeviceContext.IncRef();

				// Allow version to be null (fallback to current version)
				version = version ?? _CurrentVersion;
				// Set flags
				_ContextFlags = flags;

				if ((CurrentCaps.PlatformExtensions.CreateContext_ARB || CurrentCaps.PlatformExtensions.CreateContextProfile_ARB) && (version.Major >= 3)) {
					List<int> cAttributes = new List<int>();

					#region Context Version

					// Requires a specific version
					Debug.Assert(Wgl.CONTEXT_MAJOR_VERSION_ARB == Glx.CONTEXT_MAJOR_VERSION_ARB);
					Debug.Assert(Wgl.CONTEXT_MINOR_VERSION_ARB == Glx.CONTEXT_MINOR_VERSION_ARB);
					cAttributes.AddRange(new int[] {
						Wgl.CONTEXT_MAJOR_VERSION_ARB, version.Major,
						Wgl.CONTEXT_MINOR_VERSION_ARB, version.Minor
					});

					#endregion

					#region Context Profile

					uint contextProfile = 0;

					// Check binary compatibility between WGL and GLX
					Debug.Assert(Wgl.CONTEXT_PROFILE_MASK_ARB == Glx.CONTEXT_PROFILE_MASK_ARB);
					Debug.Assert(Wgl.CONTEXT_CORE_PROFILE_BIT_ARB == Glx.CONTEXT_CORE_PROFILE_BIT_ARB);
					Debug.Assert(Wgl.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB == Glx.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
					Debug.Assert(Wgl.CONTEXT_ES_PROFILE_BIT_EXT == Glx.CONTEXT_ES_PROFILE_BIT_EXT);

					// By default, Core profile

					// Core profile?
					if ((flags & GraphicsContextFlags.CoreProfile) != 0)
						contextProfile |= Wgl.CONTEXT_CORE_PROFILE_BIT_ARB;
					// Compatibility profile?
					if ((flags & GraphicsContextFlags.CompatibilityProfile) != 0)
						contextProfile |= Wgl.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
					// OpenGL ES profile?
					if ((flags & GraphicsContextFlags.EmbeddedProfile) != 0)
						contextProfile |= Wgl.CONTEXT_ES_PROFILE_BIT_EXT;

					if (contextProfile != 0) {
						cAttributes.AddRange(new int[] {
							Wgl.CONTEXT_PROFILE_MASK_ARB, unchecked((int)contextProfile)
						});
					}

					#endregion

					#region Context Flags

					uint contextFlags = 0;

					// Check binary compatibility between WGL and GLX
					Debug.Assert(Wgl.CONTEXT_FLAGS_ARB == Glx.CONTEXT_FLAGS_ARB);
					Debug.Assert(Wgl.CONTEXT_FORWARD_COMPATIBLE_BIT_ARB == Glx.CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
					Debug.Assert(Wgl.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB == Glx.CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
					Debug.Assert(Wgl.CONTEXT_DEBUG_BIT_ARB == Glx.CONTEXT_DEBUG_BIT_ARB);
					Debug.Assert(Wgl.CONTEXT_ROBUST_ACCESS_BIT_ARB == Glx.CONTEXT_ROBUST_ACCESS_BIT_ARB);
					Debug.Assert(Wgl.CONTEXT_RESET_ISOLATION_BIT_ARB == Glx.CONTEXT_RESET_ISOLATION_BIT_ARB);

					if (((flags & GraphicsContextFlags.CompatibilityProfile) != 0) && (_CurrentCaps.GlExtensions.Compatibility_ARB == false))
						throw new NotSupportedException("compatibility profile not supported");
					if (((flags & GraphicsContextFlags.Robust) != 0) && (_CurrentCaps.GlExtensions.Robustness_ARB == false && _CurrentCaps.GlExtensions.Robustness_EXT == false))
						throw new NotSupportedException("robust profile not supported");

					// Context flags: debug context
					if ((flags & GraphicsContextFlags.Debug) != 0)
						contextFlags |= Wgl.CONTEXT_DEBUG_BIT_ARB;
					// Context flags: forward compatible context
					if ((flags & GraphicsContextFlags.ForwardCompatible) != 0)
						contextFlags |= Wgl.CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
					// Context flags: robust behavior
					if ((flags & GraphicsContextFlags.Robust) != 0)
						contextFlags |= Wgl.CONTEXT_ROBUST_ACCESS_BIT_ARB;
					// Context flags: reset isolation
					if ((flags & GraphicsContextFlags.ResetIsolation) != 0)
						contextFlags |= Wgl.CONTEXT_RESET_ISOLATION_BIT_ARB;

					if (contextFlags != 0) {
						cAttributes.AddRange(new int[] {
							Wgl.CONTEXT_FLAGS_ARB, unchecked((int)contextFlags)
						});
					}

					#endregion

					// End of attributes
					cAttributes.Add(0);

					// Create rendering context
					int[] contextAttributes = cAttributes.ToArray();

					_RenderContext = _DeviceContext.CreateContextAttrib(sharedContextHandle, contextAttributes);
					Debug.Assert(_RenderContext != IntPtr.Zero);
				} else {
					// Create rendering context
					_RenderContext = _DeviceContext.CreateContext(sharedContextHandle);
					Debug.Assert(_RenderContext != IntPtr.Zero);
				}

				if (_RenderContext == IntPtr.Zero)
					throw new InvalidOperationException(String.Format("unable to create context {0}", version));

				// Allow the creation of a GraphicsContext while another GraphicsContext is currently current to the
				// calling thread: restore currency after the job get done
				GraphicsContext prevContext = GetCurrentContext();
				IDeviceContext prevContextDevice = (prevContext != null) ? prevContext._CurrentDeviceContext : null;

				// This will cause OpenGL operation flushed... not too bad
				MakeCurrent(deviceContext, true);

				// Get the current OpenGL implementation supported by this GraphicsContext
				_Version = KhronosVersion.Parse(Gl.GetString(StringName.Version));
				// Get the current OpenGL Shading Language implementation supported by this GraphicsContext
				_ShadingVersion = KhronosVersion.Parse(Gl.GetString(StringName.ShadingLanguageVersion));
				// Query context capabilities
				_CapsStack.Push(GraphicsCapabilities.Query(this, deviceContext));

				// Determine this GraphicsContext object namespace
				if (sharedContext != null) {
					// Sharing same object name space
					_ObjectNameSpace = sharedContext._ObjectNameSpace;
				} else {
					// Reserved object name space
					_ObjectNameSpace = Guid.NewGuid();
				}

				// Create shader include library (GLSL #include support)
				_ShaderIncludeLibrary = new ShaderIncludeLibrary();
				_ShaderIncludeLibrary.Create(this);

				// Restore previous current context, if any. Otherwise, make uncurrent
				if (prevContext != null)
					prevContext.MakeCurrent(prevContextDevice, true);
				else
					MakeCurrent(deviceContext, false);
			} catch {
				// Rethrow the exception
				throw;
			}
		}
		/// <summary>
		/// Performs application-defined tasks associated with freeing, releasing, or resetting managed/unmanaged resources.
		/// </summary>
		/// <param name="disposing">
		/// </param>
		/// <remarks>
		/// This method shall be called by the same thread which has created this GraphicsContext, but only in the case the following
		/// constructors were called:
		/// - @ref GraphicsContext::GraphicsContext()
		/// </remarks>
		/// <exception cref="InvalidOperationException">
		/// Exception throw if this GraphicsContext has not been disposed before finalization.
		/// </exception>
		/// <exception cref="InvalidOperationException">
		/// Exception throw if it's not possible to release correctly the OpenGL context related to this GraphicsContext.
		/// </exception>
		/// <exception cref="InvalidOperationException">
		/// Exception throw if the current thread is not the one which has constructed this GraphicsContext.
		/// </exception>
		/// <exception cref="InvalidOperationException">
		/// Exception throw if it's not possible to release correctly the GDI device context related to this GraphicsContext.
		/// </exception>
		private void Dispose(bool disposing)
		{
			if (disposing == true) {

				// Dispose resources
				if (_DrawArrayBuffer != null)
					_DrawArrayBuffer.Dispose(this);
				if (_VertexArray != null)
					_VertexArray.Dispose(this);

				if (_ShaderIncludeLibrary != null) {
					_ShaderIncludeLibrary.Dispose(this);
					_ShaderIncludeLibrary = null;
				}

				// Dispose unmanaged resources
				if (_RenderContext != IntPtr.Zero) {
					if (_DeviceContext.DeleteContext(_RenderContext) == false)
						throw new InvalidOperationException("unable to release OpenGL context");
					_RenderContext = IntPtr.Zero;
				}

				if (_DeviceContextThreadId != System.Threading.Thread.CurrentThread.ManagedThreadId)
					throw new InvalidOperationException("disposing on a different thread context");
				_DeviceContext.DecRef();
				_DeviceContext = null;

				// Remove context from the current ones
				int threadId = 0;
				bool threadCurrentFound = false;

				lock (_RenderThreadsLock) {
					foreach (KeyValuePair<int, GraphicsContext> pair in _RenderThreads) {
						if (ReferenceEquals(pair.Value, this) == true) {
							threadId = pair.Key;
							threadCurrentFound = true;
							break;
						}
					}
				}

				if (threadCurrentFound == true)
					_RenderThreads[threadId] = null;
			}
		}
		private static List<string> Process(ShaderIncludeLibrary includeLibrary, ShaderCompilerContext cctx, IncludeProcessorContext ictx, IEnumerable<string> shaderSource)
		{
			if (includeLibrary == null)
				throw new ArgumentNullException("includeLibrary");
			if (cctx == null)
				throw new ArgumentNullException("cctx");
			if (shaderSource == null)
				throw new ArgumentNullException("sSource");
			
			List<string> processedSource = new List<string>();

			// Shader includes not supported. Process them manually before submitting shader source text lines.

			foreach (string line in shaderSource) {
				// Ignore null items
				if (line == null) continue;

				if ((_RegexInclude.Match(line)).Success) {
					ShaderInclude shaderInclude = null;
					string includePath = ExtractIncludePath(line);
					string canonicalPath = String.Empty;

					if (includePath.StartsWith("/") == false) {

						// If <path> does not start with a forward slash, it is a path relative
						// to one of the ordered list of initial search points.

						if ((ictx.CurrentPath != String.Empty) && (_RegexIncludeAngular.Match(line).Success == false)) {

							// If it is quoted with double quotes in a previously included string, then the first
							// search point will be the tree location where the previously included
							// string had been found. If not found there, the search continues at
							// the beginning of the list of search points, as just described (see comment later).

							canonicalPath = NormalizeIncludePath(Path.Combine(ictx.CurrentPath, includePath));
							if (includeLibrary.IsPathDefined(canonicalPath))
								shaderInclude = includeLibrary.GetInclude(canonicalPath);
						}

						// If this path is quoted with angled brackets, the tree is searched relative to the
						// first search point in the ordered list, and then relative to each
						// subsequent search point, in order, until a matching path is found in
						// the tree. This is also the behavior if it is quoted with double
						// quotes in an initial (non-included) shader string.

						if (shaderInclude == null) {
							foreach (string includeSearchPath in cctx.Includes) {
								canonicalPath = NormalizeIncludePath(Path.Combine(includeSearchPath, includePath));
								if (includeLibrary.IsPathDefined(canonicalPath)) {
									shaderInclude = includeLibrary.GetInclude(canonicalPath);
									break;
								}
							}
						}
					} else {

						// If <path> starts with a forward slash, whether it is quoted with
						// double quotes or with angled brackets, the list of search points is
						// ignored and <path> is looked up in the tree as described in Appendix
						// A.

						canonicalPath = includePath;
						if (includeLibrary.IsPathDefined(canonicalPath) == false)
							throw new InvalidOperationException(String.Format("absolute include path \"{0}\" not existing", canonicalPath));
						shaderInclude = includeLibrary.GetInclude(canonicalPath);
					}

					if (shaderInclude == null)
						throw new InvalidOperationException(String.Format("include path '{0}' not found", includePath));

					// Recurse on included source (it may contain other includes)
					IncludeProcessorContext ictxRecurse = new IncludeProcessorContext();

					System.Diagnostics.Debug.Assert(String.IsNullOrEmpty(canonicalPath) == false);
					ictxRecurse.CurrentPath = canonicalPath;

					processedSource.AddRange(Process(includeLibrary, cctx, ictxRecurse, shaderInclude.Source));
				} else
					processedSource.Add(line);
			}

			return (processedSource);
		}
        private static List <string> Process(ShaderIncludeLibrary includeLibrary, ShaderCompilerContext cctx, IncludeProcessorContext ictx, IEnumerable <string> shaderSource)
        {
            if (includeLibrary == null)
            {
                throw new ArgumentNullException("includeLibrary");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }
            if (shaderSource == null)
            {
                throw new ArgumentNullException("sSource");
            }

            List <string> processedSource = new List <string>();

            // Shader includes not supported. Process them manually before submitting shader source text lines.

            foreach (string line in shaderSource)
            {
                // Ignore null items
                if (line == null)
                {
                    continue;
                }

                if ((_RegexInclude.Match(line)).Success)
                {
                    ShaderInclude shaderInclude = null;
                    string        includePath   = ExtractIncludePath(line);
                    string        canonicalPath = String.Empty;

                    if (includePath.StartsWith("/") == false)
                    {
                        // If <path> does not start with a forward slash, it is a path relative
                        // to one of the ordered list of initial search points.

                        if ((ictx.CurrentPath != String.Empty) && (_RegexIncludeAngular.Match(line).Success == false))
                        {
                            // If it is quoted with double quotes in a previously included string, then the first
                            // search point will be the tree location where the previously included
                            // string had been found. If not found there, the search continues at
                            // the beginning of the list of search points, as just described (see comment later).

                            canonicalPath = NormalizeIncludePath(Path.Combine(ictx.CurrentPath, includePath));
                            if (includeLibrary.IsPathDefined(canonicalPath))
                            {
                                shaderInclude = includeLibrary.GetInclude(canonicalPath);
                            }
                        }

                        // If this path is quoted with angled brackets, the tree is searched relative to the
                        // first search point in the ordered list, and then relative to each
                        // subsequent search point, in order, until a matching path is found in
                        // the tree. This is also the behavior if it is quoted with double
                        // quotes in an initial (non-included) shader string.

                        if (shaderInclude == null)
                        {
                            foreach (string includeSearchPath in cctx.Includes)
                            {
                                canonicalPath = NormalizeIncludePath(Path.Combine(includeSearchPath, includePath));
                                if (includeLibrary.IsPathDefined(canonicalPath))
                                {
                                    shaderInclude = includeLibrary.GetInclude(canonicalPath);
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        // If <path> starts with a forward slash, whether it is quoted with
                        // double quotes or with angled brackets, the list of search points is
                        // ignored and <path> is looked up in the tree as described in Appendix
                        // A.

                        canonicalPath = includePath;
                        if (includeLibrary.IsPathDefined(canonicalPath) == false)
                        {
                            throw new InvalidOperationException(String.Format("absolute include path \"{0}\" not existing", canonicalPath));
                        }
                        shaderInclude = includeLibrary.GetInclude(canonicalPath);
                    }

                    if (shaderInclude == null)
                    {
                        throw new InvalidOperationException(String.Format("include path '{0}' not found", includePath));
                    }

                    // Recurse on included source (it may contain other includes)
                    IncludeProcessorContext ictxRecurse = new IncludeProcessorContext();

                    System.Diagnostics.Debug.Assert(String.IsNullOrEmpty(canonicalPath) == false);
                    ictxRecurse.CurrentPath = canonicalPath;

                    processedSource.AddRange(Process(includeLibrary, cctx, ictxRecurse, shaderInclude.Source));
                }
                else
                {
                    processedSource.Add(line);
                }
            }

            return(processedSource);
        }