Ejemplo n.º 1
0
            /// <summary>
            /// Query the OpenGL implementation limits.
            /// </summary>
            /// <param name="version">
            /// The <see cref="KhronosVersion"/> that specifies the GL version.
            /// </param>
            /// <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="Gl.Limits"/> 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 Limits Query(KhronosVersion version, Extensions glExtensions)
            {
                if (glExtensions == null)
                {
                    throw new ArgumentNullException("glExtensions");
                }

                LogComment("Query OpenGL implementation limits.");

                Limits graphicsLimits = new Limits();

#if NETSTANDARD1_1 || NETSTANDARD1_4
                IEnumerable <FieldInfo> graphicsLimitsFields = typeof(Limits).GetTypeInfo().DeclaredFields;
#else
                IEnumerable <FieldInfo> graphicsLimitsFields = typeof(Limits).GetFields(BindingFlags.Public | BindingFlags.Instance);
#endif

                foreach (FieldInfo field in graphicsLimitsFields)
                {
#if NETSTANDARD1_1 || NETSTANDARD1_4 || NETCORE
                    LimitAttribute graphicsLimitAttribute      = (LimitAttribute)field.GetCustomAttribute(typeof(LimitAttribute));
                    Attribute[]    graphicsExtensionAttributes = new List <Attribute>(field.GetCustomAttributes(typeof(RequiredByFeatureAttribute))).ToArray();
#else
                    LimitAttribute graphicsLimitAttribute      = (LimitAttribute)Attribute.GetCustomAttribute(field, typeof(LimitAttribute));
                    Attribute[]    graphicsExtensionAttributes = Attribute.GetCustomAttributes(field, typeof(RequiredByFeatureAttribute));
#endif
                    MethodInfo getMethod;

                    if (graphicsLimitAttribute == null)
                    {
                        continue;
                    }

                    // Check extension support
                    if ((graphicsExtensionAttributes != null) && (graphicsExtensionAttributes.Length > 0))
                    {
                        bool supported = Array.Exists(graphicsExtensionAttributes, delegate(Attribute item) {
                            RequiredByFeatureAttribute featureAttribute = (RequiredByFeatureAttribute)item;
                            return(featureAttribute.IsSupported(version, glExtensions));
                        });

                        if (supported == false)
                        {
                            continue;
                        }
                    }

                    // Determine which method is used to get the OpenGL limit
#if   NETSTANDARD1_1 || NETSTANDARD1_4
                    if (field.FieldType != typeof(String))
                    {
                        if (field.FieldType.IsArray == true)
                        {
                            getMethod = typeof(Gl).GetTypeInfo().GetDeclaredMethod("Get");
                        }
                        else
                        {
                            getMethod = typeof(Gl).GetTypeInfo().GetDeclaredMethod("Get");
                        }
                    }
                    else
                    {
                        getMethod = typeof(Gl).GetTypeInfo().GetDeclaredMethod("GetString");
                    }
#elif NETCORE
                    if (field.FieldType != typeof(String))
                    {
                        if (field.FieldType.IsArray == true)
                        {
                            getMethod = typeof(Gl).GetMethod("Get", new Type[] { typeof(Int32), field.FieldType });
                        }
                        else
                        {
                            getMethod = typeof(Gl).GetMethod("Get", new Type[] { typeof(Int32), field.FieldType.MakeByRefType() });
                        }
                    }
                    else
                    {
                        getMethod = typeof(Gl).GetMethod("GetString", new Type[] { typeof(Int32) });
                    }
#else
                    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);
                    }
#endif

                    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(), (int)graphicsLimitAttribute.ArrayLength);
                            }

                            try {
                                object[] @params = new object[] { graphicsLimitAttribute.EnumValue, obj };
                                getMethod.Invoke(null, @params);
                                field.SetValue(graphicsLimits, @params[1]);
                            } catch (GlException) {
                            } catch (Exception) {
                            }
                        }
                        else
                        {
                            try {
                                string s = (string)getMethod.Invoke(null, new object[] { graphicsLimitAttribute.EnumValue });
                                field.SetValue(graphicsLimits, s);
                            } catch (GlException) {
                            } catch (Exception) {
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("GraphicsLimits field " + field.Name + " doesn't have a OpenGL compatible type");
                    }
                }

                return(graphicsLimits);
            }
Ejemplo n.º 2
0
        /// <summary>
        /// Check whether commands implemented by the current driver have a corresponding extension declaring the
        /// support of them.
        /// </summary>
        /// <typeparam name="T">
        /// The type of the KhronosApi to inspect for commands.
        /// </typeparam>
        /// <param name="version">
        /// The <see cref="KhronosVersion"/> currently implemented by the current context on this thread.
        /// </param>
        /// <param name="extensions">
        /// The <see cref="ExtensionsCollection"/> that specifies the extensions supported by the driver.
        /// </param>
        protected static void CheckExtensionCommands <T>(KhronosVersion version, ExtensionsCollection extensions, bool enableExtensions) where T : KhronosApi
        {
            if (version == null)
            {
                throw new ArgumentNullException("version");
            }
            if (extensions == null)
            {
                throw new ArgumentNullException("extensions");
            }

#if !NETCORE
            Type            apiType         = typeof(T);
            FunctionContext functionContext = GetFunctionContext(apiType);

            Debug.Assert(functionContext != null);
            if (functionContext == null)
            {
                throw new InvalidOperationException("unrecognized API type");
            }

            LogComment("Checking commands for {0}", version);

            Dictionary <string, List <Type> > hiddenVersions   = new Dictionary <string, List <Type> >();
            Dictionary <string, bool>         hiddenExtensions = new Dictionary <string, bool>();

            foreach (FieldInfo fi in functionContext.Delegates)
            {
                Delegate fiDelegateType     = (Delegate)fi.GetValue(null);
                string   commandName        = fi.Name.Substring(3);
                bool     commandDefined     = fiDelegateType != null;
                bool     supportedByFeature = false;

                Type delegateType = fi.DeclaringType.GetNestedType(fi.Name.Substring(1), BindingFlags.Public | BindingFlags.NonPublic);
                IEnumerable <object> requiredByFeatureAttributes = delegateType.GetCustomAttributes(typeof(RequiredByFeatureAttribute), false);

                foreach (RequiredByFeatureAttribute requiredByFeatureAttribute in requiredByFeatureAttributes)
                {
                    supportedByFeature |= requiredByFeatureAttribute.IsSupported(version, extensions);
                }

                // Find the underlying extension
                RequiredByFeatureAttribute hiddenVersionAttrib   = null;
                RequiredByFeatureAttribute hiddenExtensionAttrib = null;

                foreach (RequiredByFeatureAttribute requiredByFeatureAttribute in requiredByFeatureAttributes)
                {
                    if (requiredByFeatureAttribute.IsSupportedApi(version.Api) == false)
                    {
                        // Version attribute
                        if (hiddenVersionAttrib == null)
                        {
                            hiddenVersionAttrib = requiredByFeatureAttribute;
                        }
                    }
                    else
                    {
                        // Extension attribute
                        if (hiddenExtensionAttrib == null)
                        {
                            hiddenExtensionAttrib = requiredByFeatureAttribute;
                        }
                    }
                }

                if (commandDefined != supportedByFeature)
                {
#if DEBUG_VERBOSE
                    string supportString = "any feature";

                    if (hiddenVersionAttrib != null)
                    {
                        supportString = hiddenVersionAttrib.FeatureName;
                        if (hiddenExtensionAttrib != null)
                        {
                            supportString += " or ";
                        }
                    }

                    if (hiddenExtensionAttrib != null)
                    {
                        if (hiddenVersionAttrib == null)
                        {
                            supportString = String.Empty;
                        }
                        supportString += hiddenExtensionAttrib.FeatureName;
                    }
#endif

                    if (commandDefined)
                    {
#if DEBUG_VERBOSE
                        LogComment("The command {0} is defined, but {1} support is not advertised.", commandName, supportString);
#endif
                        if (hiddenVersionAttrib != null && hiddenExtensionAttrib == null)
                        {
                            List <Type> versionDelegates = new List <Type>();

                            if (hiddenVersions.TryGetValue(hiddenVersionAttrib.FeatureName, out versionDelegates) == false)
                            {
                                hiddenVersions.Add(hiddenVersionAttrib.FeatureName, versionDelegates = new List <Type>());
                            }
                            versionDelegates.Add(delegateType);
                        }

                        if (hiddenExtensionAttrib != null)
                        {
                            // Eventually leave to false for incomplete extensions
                            if (hiddenExtensions.ContainsKey(hiddenExtensionAttrib.FeatureName) == false)
                            {
                                hiddenExtensions.Add(hiddenExtensionAttrib.FeatureName, true);
                            }
                        }
                    }
                    else
                    {
#if DEBUG_VERBOSE
                        LogComment("The command {0} is not defined, but required by some feature.", commandName);
#endif
                    }
                }

                // Partial extensions are not supported
                if (hiddenExtensionAttrib != null && commandDefined == false && hiddenExtensions.ContainsKey(hiddenExtensionAttrib.FeatureName))
                {
                    hiddenExtensions[hiddenExtensionAttrib.FeatureName] = false;
                }
            }

            if (hiddenExtensions.Count > 0)
            {
                LogComment("Found {0} experimental extensions:", hiddenExtensions.Count);
                foreach (KeyValuePair <string, bool> hiddenExtension in hiddenExtensions)
                {
                    LogComment("- {0}: {1}", hiddenExtension.Key, hiddenExtension.Value ? "experimental" : "experimental (partial, unsupported)");
                }
            }

            if (hiddenVersions.Count > 0)
            {
                LogComment("Found {0} experimental version commands:", hiddenVersions.Count);
                foreach (KeyValuePair <string, List <Type> > hiddenVersion in hiddenVersions)
                {
                    LogComment("- {0}", hiddenVersion.Key);
                    foreach (Type delegateType in hiddenVersion.Value)
                    {
                        LogComment("    > {0}", delegateType.Name);
                    }
                }
            }

            if (enableExtensions)
            {
                bool sync = false;

                foreach (KeyValuePair <string, bool> hiddenExtension in hiddenExtensions)
                {
                    if (hiddenExtension.Value == false)
                    {
                        continue;                               // Do not enable partial extension
                    }
                    extensions.EnableExtension(hiddenExtension.Key);
                    sync = true;
                }

                if (sync)
                {
                    extensions.SyncMembers(version);
                }
            }
#endif
        }