/// <summary>
		/// Query the OpenGL implementation limits.
		/// </summary>
		/// <param name="glExtensions">
		/// A <see cref="Gl.Extensions"/> that specify the supported OpenGL extension by the current
		/// implementation.
		/// </param>
		/// <returns>
		/// It returns a <see cref="GraphicsLimits"/> that specify the current OpenGL implementation limits.
		/// </returns>
		/// <remarks>
		/// It is assumed to have a valid OpenGL context current on the calling thread.
		/// </remarks>
		public static GraphicsLimits Query(Gl.Extensions glExtensions)
		{
			if (glExtensions == null)
				throw new ArgumentNullException("glExtensions");

			KhronosApi.LogComment("Query OpenGL implementation imits.");

			GraphicsLimits graphicsLimits = new GraphicsLimits();
			FieldInfo[] graphicsLimitsFields = typeof(GraphicsLimits).GetFields(BindingFlags.Public | BindingFlags.Instance);

			foreach (FieldInfo field in graphicsLimitsFields) {
				GraphicsLimitAttribute graphicsLimitAttribute = (GraphicsLimitAttribute)Attribute.GetCustomAttribute(field, typeof(GraphicsLimitAttribute));
				Attribute[] graphicsExtensionAttributes = Attribute.GetCustomAttributes(field, typeof(KhronosApi.ExtensionAttribute));
				MethodInfo getMethod;

				if (graphicsLimitAttribute == null)
					continue;

				// Check extension support
				if ((graphicsExtensionAttributes != null) && (graphicsExtensionAttributes.Length > 0)) {
					bool supported = Array.Exists(graphicsExtensionAttributes, delegate(Attribute item) {
						return glExtensions.HasExtensions(((KhronosApi.ExtensionAttribute)item).ExtensionName);
					});

					if (supported == false)
						continue;
				}

				// Determine which method is used to get the OpenGL limit
				if (field.FieldType != typeof(String)) {
					if (field.FieldType.IsArray == true)
						getMethod = typeof(Gl).GetMethod("Get", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Int32), field.FieldType }, null);
					else
						getMethod = typeof(Gl).GetMethod("Get", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Int32), field.FieldType.MakeByRefType() }, null);
				} else
					getMethod = typeof(Gl).GetMethod("GetString", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Int32) }, null);

				if (getMethod != null) {
					if (field.FieldType != typeof(String)) {
						object obj;

						if (field.FieldType.IsArray == false)
							obj = Activator.CreateInstance(field.FieldType);
						else
							obj = Array.CreateInstance(field.FieldType.GetElementType(), graphicsLimitAttribute.ArrayLenght);
						object[] @params = new object[] { graphicsLimitAttribute.EnumValue, obj };

						try {
							getMethod.Invoke(null, @params);

							field.SetValue(graphicsLimits, @params[1]);
						} catch (Exception) {

						}
						
					} else {
						try {
							string s = (string)getMethod.Invoke(null, new object[] { graphicsLimitAttribute.EnumValue });

							field.SetValue(graphicsLimits, s);
						} catch (Exception) {
							
						}
					}
				} else
					throw new InvalidOperationException("GraphicsLimits field " + field.Name + " doesn't have a OpenGL compatible type");

				string fieldValueString;
				object fieldValue = field.GetValue(graphicsLimits);

				if (fieldValue is Array) {
					StringBuilder sb = new StringBuilder();

					sb.Append("{ ");
					if (((Array)fieldValue).Length > 0) {
						foreach (object arrayItem in (Array)fieldValue)
							sb.AppendFormat("{0}, ", arrayItem);
						sb.Remove(sb.Length - 2, 2);
					}
					sb.Append(" }");

					fieldValueString = sb.ToString();
				} else
					fieldValueString = fieldValue.ToString();
			}

			return (graphicsLimits);
		}