示例#1
0
        /// <summary>
        /// Bind the OpenGL delegates to a specific API.
        /// </summary>
        /// <param name="version">
        /// A <see cref="KhronosVersion"/> that specifies the API to bind.
        /// </param>
        /// <param name="extensions">
        /// A <see cref="KhronosApi.ExtensionsCollection"/> that specifies the extensions supported. It can be null.
        /// </param>
        public static void BindAPI(KhronosVersion version, ExtensionsCollection extensions)
        {
            if (version == null)
            {
                throw new ArgumentNullException("version");
            }

            BindAPI <Gl>(GetPlatformLibrary(version), GetProcAddressGLOS, version, extensions);
        }
示例#2
0
        /// <summary>
        /// Bind the OpenGL delegates to a specific API.
        /// </summary>
        /// <param name="version">
        /// A <see cref="KhronosVersion"/> that specifies the API to bind.
        /// </param>
        /// <param name="extensions">
        /// A <see cref="Khronos.KhronosApi.ExtensionsCollection"/> that specifies the extensions supported. It can be null.
        /// </param>
        public static void BindAPI(KhronosVersion version, ExtensionsCollection extensions)
        {
            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }

            BindAPI <Gl>(version, extensions);
        }
示例#3
0
文件: Gl.cs 项目: ipud2/OpenGL.Net-1
        /// <summary>
        /// Bind the OpenGL delegates to a specific API.
        /// </summary>
        /// <param name="version">
        /// A <see cref="KhronosVersion"/> that specifies the API to bind.
        /// </param>
        /// <param name="extensions">
        /// A <see cref="Khronos.KhronosApi.ExtensionsCollection"/> that specifies the extensions supported. It can be null.
        /// </param>
        public static void BindAPI(KhronosVersion version, ExtensionsCollection extensions)
        {
            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }

            BindAPI <Gl>(GetPlatformLibrary(version), _GetAddressDelegate, version, extensions);
        }
示例#4
0
        /// <summary>
        /// Link delegates fields using import declarations.
        /// </summary>
        /// <param name="version"></param>
        /// <param name="extensions"></param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="path"/> or <paramref name="getAddress"/> is null.
        /// </exception>
        internal static void BindAPI <T>(KhronosVersion version, ExtensionsCollection extensions)
        {
            FunctionContext functionContext = GetFunctionContext(typeof(T));

            Debug.Assert(functionContext != null);

            foreach (FieldInfo fi in functionContext.Delegates)
            {
                BindAPIFunction(fi, version, extensions);
            }
        }
示例#5
0
        /// <summary>
        /// Bind the OpenGL delegates to a specific API.
        /// </summary>
        /// <param name="version">
        /// A <see cref="KhronosVersion"/> that specifies the API to bind.
        /// </param>
        /// <param name="getProcAddress">
        /// The <see cref="IGetProcAddress"/> used for loading function pointers.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="version"/> or <paramref name="getProcAddress"/> is null.
        /// </exception>
        private static void BindAPI(KhronosVersion version, ExtensionsCollection extensions, IGetProcAddress getProcAddress)
        {
            if (version == null)
            {
                throw new ArgumentNullException("version");
            }
            if (getProcAddress == null)
            {
                throw new ArgumentNullException("getProcAddress");
            }

            BindAPI <Gl>(GetPlatformLibrary(version), getProcAddress, version, extensions);
        }
示例#6
0
        /// <summary>
        /// Link delegates fields using import declarations.
        /// </summary>
        /// <param name="path">
        /// A <see cref="String"/> that specifies the assembly file path containing the import functions.
        /// </param>
        /// <param name="getAddress">
        /// A <see cref="GetAddressDelegate"/> used for getting function pointers. This parameter is dependent on the currently running platform.
        /// </param>
        /// <param name="functionContext">
        /// A <see cref="FunctionContext"/> mapping a <see cref="MethodInfo"/> with the relative function name.
        /// </param>
        /// <param name="function">
        /// A <see cref="FieldInfo"/> that specifies the underlying function field to be updated.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="path"/>, <paramref name="function"/> or <paramref name="getAddress"/> is null.
        /// </exception>
        private static void BindAPIFunction(string path, GetAddressDelegate getAddress, FunctionContext functionContext, FieldInfo function, KhronosVersion version, ExtensionsCollection extensions)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            if (functionContext == null)
            {
                throw new ArgumentNullException("functionContext");
            }
            if (function == null)
            {
                throw new ArgumentNullException("function");
            }
            if (getAddress == null)
            {
                throw new ArgumentNullException("getAddress");
            }

            if (version != null || extensions != null)
            {
                if (IsCompatibleField(function, version, extensions) == false)
                {
                    function.SetValue(null, null);                                              // Function not supported: reset
                    return;
                }
            }

            string importName    = function.Name.Substring(1);                    // Delegate name always prefixes with 'p'
            IntPtr importAddress = IntPtr.Zero;

            // Load command address
            importAddress = getAddress(path, importName);

            // Manages aliases (load external symbol)
            if (importAddress == IntPtr.Zero)
            {
#if !NETCORE
                Attribute[] aliasOfAttributes = Attribute.GetCustomAttributes(function, typeof(AliasOfAttribute));
#else
                Attribute[] aliasOfAttributes = new List <Attribute>(function.GetCustomAttributes(typeof(AliasOfAttribute))).ToArray();
#endif

                for (int i = 1 /* Skip base name */; i < aliasOfAttributes.Length; i++)
                {
                    AliasOfAttribute aliasOfAttribute = (AliasOfAttribute)aliasOfAttributes[i];
                    if ((importAddress = getAddress(path, aliasOfAttribute.SymbolName)) != IntPtr.Zero)
                    {
                        break;
                    }
                }
            }

            if (importAddress != IntPtr.Zero)
            {
                Delegate delegatePtr;

                // Try to load external symbol
                if ((delegatePtr = Marshal.GetDelegateForFunctionPointer(importAddress, function.FieldType)) == null)
                {
                    MethodInfo methodInfo;

                    if (functionContext.Imports.TryGetValue(importName, out methodInfo) == true)
                    {
#if !NETCORE
                        delegatePtr = Delegate.CreateDelegate(function.FieldType, methodInfo);
#else
                        delegatePtr = methodInfo.CreateDelegate(function.FieldType);
#endif
                    }
                }

                if (delegatePtr != null)
                {
                    function.SetValue(null, delegatePtr);
                }
            }
            else
            {
                function.SetValue(null, null);                                          // Function not implemented: reset
            }
        }
示例#7
0
        /// <summary>
        /// Determine whether an API command is compatible with the specific API version and extensions registry.
        /// </summary>
        /// <param name="function">
        /// A <see cref="FieldInfo"/> that specifies the command delegate to set. This argument make avail attributes useful
        /// to determine the actual support for this command.
        /// </param>
        /// <param name="version">
        /// The <see cref="KhronosVersion"/> that specifies the API version.
        /// </param>
        /// <param name="extensions">
        /// The <see cref="ExtensionsCollection"/> that specifies the API extensions registry.
        /// </param>
        /// <returns>
        /// It returns a <see cref="Boolean"/> that specifies whether <paramref name="function"/> is supported by the
        /// API having the version <paramref name="version"/> and the extensions registry <paramref name="extensions"/>.
        /// </returns>
        internal static bool IsCompatibleField(FieldInfo function, KhronosVersion version, ExtensionsCollection extensions)
        {
            if (function == null)
            {
                throw new ArgumentNullException("function");
            }
            if (version == null)
            {
                throw new ArgumentNullException("version");
            }

#if !NETCORE
            Attribute[] attrRequired = Attribute.GetCustomAttributes(function, typeof(RequiredByFeatureAttribute));
#else
            Attribute[] attrRequired = new List <Attribute>(function.GetCustomAttributes(typeof(RequiredByFeatureAttribute))).ToArray();
#endif

            KhronosVersion maxRequiredVersion = null;
            bool           isRequired = false, isRemoved = false;

            foreach (RequiredByFeatureAttribute attr in attrRequired)
            {
                // Check for API support
                if (attr.IsSupported(version, extensions) == false)
                {
                    continue;
                }
                // Supported!
                isRequired |= true;
                // Keep track of the maximum API version supporting this command
                // Note: useful for resurrected commands after deprecation
                if (maxRequiredVersion == null || maxRequiredVersion < attr.FeatureVersion)
                {
                    maxRequiredVersion = attr.FeatureVersion;
                }
            }

            if (isRequired)
            {
                // Note: indeed the feature could be supported; check whether it is removed

#if !NETCORE
                Attribute[] attrRemoved = Attribute.GetCustomAttributes(function, typeof(RemovedByFeatureAttribute));
#else
                Attribute[] attrRemoved = new List <Attribute>(function.GetCustomAttributes(typeof(RemovedByFeatureAttribute))).ToArray();
#endif
                KhronosVersion maxRemovedVersion = null;

                foreach (RemovedByFeatureAttribute attr in attrRemoved)
                {
                    if (attr.IsRemoved(version, extensions) == false)
                    {
                        continue;
                    }

                    // Removed!
                    isRemoved |= true;
                    // Keep track of the maximum API version removing this command
                    if (maxRemovedVersion == null || maxRemovedVersion < attr.FeatureVersion)
                    {
                        maxRemovedVersion = attr.FeatureVersion;
                    }
                }

                // Check for resurrection
                if (isRemoved)
                {
                    Debug.Assert(maxRequiredVersion != null);
                    Debug.Assert(maxRemovedVersion != null);

                    if (maxRequiredVersion > maxRemovedVersion)
                    {
                        isRemoved = false;
                    }
                }

                return(isRemoved == false);
            }
            else
            {
                return(false);
            }
        }
示例#8
0
        /// <summary>
        /// Link delegates field using import declaration, using platform specific method for determining procedures address.
        /// </summary>
        internal static void BindAPIFunction <T>(string path, string functionName, IGetProcAddress getProcAddress, KhronosVersion version, ExtensionsCollection extensions)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            if (functionName == null)
            {
                throw new ArgumentNullException("function");
            }
            if (getProcAddress == null)
            {
                throw new ArgumentNullException("getAddress");
            }

            FunctionContext functionContext = GetFunctionContext(typeof(T));

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

            Type delegatesClass = typeof(T).GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic);

            Debug.Assert(delegatesClass != null);
            if (delegatesClass == null)
            {
                throw new NotImplementedException("missing Delegates class");
            }

            FieldInfo functionField = delegatesClass.GetField("p" + functionName, BindingFlags.Static | BindingFlags.NonPublic);

            Debug.Assert(functionField != null);
            if (functionField == null)
            {
                throw new NotImplementedException(String.Format("unable to find function named {0}", functionName));
            }

            BindAPIFunction(path, delegate(string libpath, string function) {
                // Note: IGetProcAddress implementation may have GetOpenGLProcAddress equivalent to GetProcAddress
                IntPtr procAddress = getProcAddress.GetOpenGLProcAddress(function);

                if (procAddress == IntPtr.Zero)
                {
                    return(GetProcAddress.GetProcAddressOS.GetProcAddress(libpath, function));
                }

                return(procAddress);
            }, functionContext, functionField, version, extensions);
        }
示例#9
0
        /// <summary>
        /// Link delegates fields using import declarations.
        /// </summary>
        /// <param name="path">
        /// A <see cref="String"/> that specifies the assembly file path containing the import functions.
        /// </param>
        /// <param name="getAddress">
        /// A <see cref="GetAddressDelegate"/> used for getting function pointers. This parameter is dependent on the currently running platform.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="path"/> or <paramref name="getAddress"/> is null.
        /// </exception>
        private static void BindAPI <T>(string path, GetAddressDelegate getAddress, KhronosVersion version, ExtensionsCollection extensions)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            if (getAddress == null)
            {
                throw new ArgumentNullException("getAddress");
            }

            FunctionContext functionContext = GetFunctionContext(typeof(T));

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

            foreach (FieldInfo fi in functionContext.Delegates)
            {
                BindAPIFunction(path, getAddress, functionContext, fi, version, extensions);
            }
        }
示例#10
0
        /// <summary>
        /// Link delegates fields using import declarations.
        /// </summary>
        /// <param name="path">
        /// A <see cref="String"/> that specifies the assembly file path containing the import functions.
        /// </param>
        /// <param name="getAddress">
        /// A <see cref="GetAddressDelegate"/> used for getting function pointers.
        /// </param>
        /// <param name="functionContext">
        /// A <see cref="FunctionContext"/> mapping a <see cref="MethodInfo"/> with the relative function name.
        /// </param>
        /// <param name="function">
        /// A <see cref="FieldInfo"/> that specifies the underlying function field to be updated.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="path"/>, <paramref name="function"/> or <paramref name="getAddress"/> is null.
        /// </exception>
        private static void BindAPIFunction(string path, GetAddressDelegate getAddress, FunctionContext functionContext, FieldInfo function, KhronosVersion version, ExtensionsCollection extensions)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            if (functionContext == null)
            {
                throw new ArgumentNullException("functionContext");
            }
            if (function == null)
            {
                throw new ArgumentNullException("function");
            }
            if (getAddress == null)
            {
                throw new ArgumentNullException("getAddress");
            }

            RequiredByFeatureAttribute        requiredByFeature    = null;
            List <RequiredByFeatureAttribute> requiredByExtensions = new List <RequiredByFeatureAttribute>();
            string defaultName = function.Name.Substring(1);                       // Delegate name always prefixes with 'p'

            if (version != null || extensions != null)
            {
                bool isRemoved = false;

                #region Check Requirement

#if NETSTANDARD1_1 || NETSTANDARD1_4 || NETCORE
                Attribute[] attrRequired = new List <Attribute>(function.GetCustomAttributes(typeof(RequiredByFeatureAttribute))).ToArray();
#else
                Attribute[] attrRequired = Attribute.GetCustomAttributes(function, typeof(RequiredByFeatureAttribute));
#endif
                foreach (RequiredByFeatureAttribute attr in attrRequired)
                {
                    // Check for API support
                    if (attr.IsSupported(version, extensions) == false)
                    {
                        continue;
                    }
                    // Keep track of the features requiring this command
                    if (attr.FeatureVersion != null)
                    {
                        // Version feature: keep track only of the maximum version
                        if (requiredByFeature == null || requiredByFeature.FeatureVersion < attr.FeatureVersion)
                        {
                            requiredByFeature = attr;
                        }
                    }
                    else
                    {
                        // Extension feature: collect every supporting extension
                        requiredByExtensions.Add(attr);
                    }
                }

                #endregion

                #region Check Deprecation/Removal

                if (requiredByFeature != null)
                {
                    // Note: indeed the feature could be supported; check whether it is removed; this is checked only if
                    // a non-extension feature is detected: extensions cannot remove commands
#if NETSTANDARD1_1 || NETSTANDARD1_4 || NETCORE
                    Attribute[] attrRemoved = new List <Attribute>(function.GetCustomAttributes(typeof(RemovedByFeatureAttribute))).ToArray();
#else
                    Attribute[] attrRemoved = Attribute.GetCustomAttributes(function, typeof(RemovedByFeatureAttribute));
#endif
                    KhronosVersion maxRemovedVersion = null;

                    foreach (RemovedByFeatureAttribute attr in attrRemoved)
                    {
                        // Check for API support
                        if (attr.IsRemoved(version, extensions) == false)
                        {
                            continue;
                        }
                        // Removed!
                        isRemoved |= true;
                        // Keep track of the maximum API version removing this command
                        if (maxRemovedVersion == null || maxRemovedVersion < attr.FeatureVersion)
                        {
                            maxRemovedVersion = attr.FeatureVersion;
                        }
                    }

                    // Check for resurrection
                    if (isRemoved)
                    {
                        Debug.Assert(requiredByFeature != null);
                        Debug.Assert(maxRemovedVersion != null);

                        if (requiredByFeature.FeatureVersion > maxRemovedVersion)
                        {
                            isRemoved = false;
                        }
                    }
                }

                #endregion

                // Do not check feature requirements in case of removal. Note: extensions are checked all the same
                if (isRemoved)
                {
                    requiredByFeature = null;
                }
            }

            // Load function pointer
            IntPtr importAddress;

            if (requiredByFeature != null || version == null)
            {
                // Load command address (version feature)
                string functionName = defaultName;

                if (requiredByFeature != null && requiredByFeature.EntryPoint != null)
                {
                    functionName = requiredByFeature.EntryPoint;
                }

                if ((importAddress = getAddress(path, functionName)) != IntPtr.Zero)
                {
                    BindAPIFunction(function, importAddress);
                    return;
                }
            }

            // Load command address (extension features)
            foreach (RequiredByFeatureAttribute extensionFeature in requiredByExtensions)
            {
                string functionName = extensionFeature.EntryPoint ?? defaultName;

                if ((importAddress = getAddress(path, functionName)) != IntPtr.Zero)
                {
                    BindAPIFunction(function, importAddress);
                    return;
                }
            }

            // Function not implemented: reset
            function.SetValue(null, null);
        }
示例#11
0
 /// <summary>
 /// Link delegates field using import declaration, using platform specific method for determining procedures address.
 /// </summary>
 internal static void BindAPIFunction <T>(string path, string functionName, KhronosVersion version, ExtensionsCollection extensions)
 {
     BindAPIFunction <T>(path, functionName, GetProcAddress.GetProcAddressOS, version, extensions);
 }
        /// <summary>
        /// Link delegates field using import declaration, using platform specific method for determining procedures address.
        /// </summary>
        internal static void BindAPIFunction <T>(string functionName, KhronosVersion version, ExtensionsCollection extensions)
        {
            FunctionContext functionContext = GetFunctionContext(typeof(T));

            Debug.Assert(functionContext != null);

            BindAPIFunction(functionContext.GetFunction(functionName), version, extensions);
        }
示例#13
0
 /// <summary>
 /// Bind the OpenGL delegates for the API corresponding to the specified OpenGL API.
 /// </summary>
 /// <param name="version">
 /// A <see cref="KhronosVersion"/> that specifies the API to bind.
 /// </param>
 /// <param name="extensions">
 /// A <see cref="ExtensionsCollection"/> that specifies the extensions supported. It can be null.
 /// </param>
 public static void BindAPI(KhronosVersion version, ExtensionsCollection extensions)
 {
     BindAPI(version, extensions, GetProcAddress.GetProcAddressGL);
 }
示例#14
0
        /// <summary>
        /// Determine whether an API command is compatible with the specific API version and extensions registry.
        /// </summary>
        /// <param name="function">
        /// A <see cref="FieldInfo" /> that specifies the command delegate to set. This argument make avail attributes useful
        /// to determine the actual support for this command.
        /// </param>
        /// <param name="version">
        /// The <see cref="KhronosVersion" /> that specifies the API version.
        /// </param>
        /// <param name="extensions">
        /// The <see cref="ExtensionsCollection" /> that specifies the API extensions registry.
        /// </param>
        /// <returns>
        /// It returns a <see cref="bool" /> that specifies whether <paramref name="function" /> is supported by the
        /// API having the version <paramref name="version" /> and the extensions registry <paramref name="extensions" />.
        /// </returns>
        internal static bool IsCompatibleField(FieldInfo function, KhronosVersion version, ExtensionsCollection extensions)
        {
            Debug.Assert(function != null);
            Debug.Assert(version != null);

            IEnumerable <Attribute> attrRequired = Attribute.GetCustomAttributes(function, typeof(RequiredByFeatureAttribute));

            KhronosVersion maxRequiredVersion = null;
            bool           required = false, removed = false;

            // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop
            foreach (RequiredByFeatureAttribute attr in attrRequired)
            {
                // Check for API support
                if (attr.IsSupported(version, extensions) == false)
                {
                    continue;
                }
                // Supported!
                required = true;
                // Keep track of the maximum API version supporting this command
                // Note: useful for resurrected commands after deprecation
                if (maxRequiredVersion == null || maxRequiredVersion < attr.FeatureVersion)
                {
                    maxRequiredVersion = attr.FeatureVersion;
                }
            }

            if (required)
            {
                // Note: indeed the feature could be supported; check whether it is removed
                IEnumerable <Attribute> attrRemoved       = Attribute.GetCustomAttributes(function, typeof(RemovedByFeatureAttribute));
                KhronosVersion          maxRemovedVersion = null;

                // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop
                foreach (RemovedByFeatureAttribute attr in attrRemoved)
                {
                    if (attr.IsRemoved(version, extensions) == false)
                    {
                        continue;
                    }

                    // Removed!
                    removed = true;
                    // Keep track of the maximum API version removing this command
                    if (maxRemovedVersion == null || maxRemovedVersion < attr.FeatureVersion)
                    {
                        maxRemovedVersion = attr.FeatureVersion;
                    }
                }

                // Check for resurrection
                if (removed)
                {
                    Debug.Assert(maxRequiredVersion != null);
                    Debug.Assert(maxRemovedVersion != null);

                    if (maxRequiredVersion > maxRemovedVersion)
                    {
                        removed = false;
                    }
                }

                return(removed == false);
            }

            return(false);
        }
示例#15
0
 public static void BindAPIFunction(string functionName, KhronosVersion version, ExtensionsCollection extensions, GraphicsContext context)
 {
     BindAPIFunction(_functionContext.GetFunction(functionName), version, extensions, context);
 }
示例#16
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(nameof(version));
            }
            if (extensions == null)
            {
                throw new ArgumentNullException(nameof(extensions));
            }

#if NETSTANDARD1_1 || NETSTANDARD1_4 || NETCORE
            throw new NotImplementedException();
#else
            FunctionContext functionContext = GetFunctionContext(typeof(T));
            Debug.Assert(functionContext != null);

            LogComment($"Checking commands for {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);
                bool     commandDefined     = fiDelegateType != null;
                bool     supportedByFeature = false;

#if DEBUG_VERBOSE
                string commandName = fi.Name.Substring(3);
#endif
                // Get the delegate type
                Type delegateType = fi.DeclaringType?.GetNestedType(fi.Name.Substring(1), BindingFlags.Public | BindingFlags.NonPublic);
                if (delegateType == null)
                {
                    continue;                                   // Support fields names not in sync with delegate types
                }
                // TODO Why not use 'fi' directly for getting attributes? They should be in sync
                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))
                    {
                        // 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;

                            if (!hiddenVersions.TryGetValue(hiddenVersionAttrib.FeatureName, out versionDelegates))
                            {
                                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))
                            {
                                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 && hiddenExtensions.ContainsKey(hiddenExtensionAttrib.FeatureName))
                {
                    hiddenExtensions[hiddenExtensionAttrib.FeatureName] = false;
                }
            }

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

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

            if (enableExtensions)
            {
                bool sync = false;

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

                if (sync)
                {
                    extensions.SyncMembers(version);
                }
            }
#endif
        }
示例#17
0
        /// <summary>
        /// Link delegates fields using import declarations.
        /// </summary>
        /// <param name="path">
        /// A <see cref="string"/> that specifies the assembly file path containing the import functions.
        /// </param>
        /// <param name="getAddress">
        /// A <see cref="GetAddressDelegate"/> used for getting function pointers.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="path"/> or <paramref name="getAddress"/> is null.
        /// </exception>
        internal static void BindAPI <T>(string path, GetAddressDelegate getAddress, KhronosVersion version, ExtensionsCollection extensions)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            if (getAddress == null)
            {
                throw new ArgumentNullException(nameof(getAddress));
            }

            FunctionContext functionContext = GetFunctionContext(typeof(T));

            Debug.Assert(functionContext != null);

            foreach (FieldInfo fi in functionContext.Delegates)
            {
                BindAPIFunction(path, getAddress, fi, version, extensions);
            }
        }
示例#18
0
        /// <summary>
        /// Link delegates field using import declaration, using platform specific method for determining procedures address.
        /// </summary>
        internal static void BindAPIFunction <T>(string path, string functionName, GetAddressDelegate getProcAddress, KhronosVersion version, ExtensionsCollection extensions)
        {
            FunctionContext functionContext = GetFunctionContext(typeof(T));

            Debug.Assert(functionContext != null);

            BindAPIFunction(path, getProcAddress, functionContext.GetFunction(functionName), version, extensions);
        }
示例#19
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
        }
示例#20
0
 /// <summary>
 /// Bind a single OpenGL delegates to a specific API.
 /// </summary>
 /// <param name="version">
 /// A <see cref="KhronosVersion"/> that specifies the API to bind.
 /// </param>
 /// <param name="extensions">
 /// A <see cref="Khronos.KhronosApi.ExtensionsCollection"/> that specifies the extensions supported. It can be null.
 /// </param>
 /// <param name="functionName">
 /// A <see cref="String"/> that specifies the name of the function to bind.
 /// </param>
 internal static void BindAPIFunction(KhronosVersion version, ExtensionsCollection extensions, string functionName)
 {
     BindAPIFunction <Gl>(null, functionName, version, extensions);
 }
示例#21
0
 public static void CheckExtensionCommands(KhronosVersion version, ExtensionsCollection extensions, bool enableExtensions)
 {
     CheckExtensionCommands <TestApi>(version, extensions, enableExtensions);
 }
示例#22
0
        /// <summary>
        /// Link delegates fields using import declarations, using platform specific method for determining procedures addresses.
        /// </summary>
        /// <param name="imports">
        /// A <see cref="ImportMap"/> mapping a <see cref="MethodInfo"/> with the relative function name.
        /// </param>
        /// <param name="delegates">
        /// A <see cref="DelegateList"/> listing <see cref="FieldInfo"/> related to function delegates.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="imports"/> or <paramref name="delegates"/> is null.
        /// </exception>
        internal static void BindAPI <T>(string path, IGetProcAddress getProcAddress, KhronosVersion version, ExtensionsCollection extensions)
        {
            BindAPI <T>(path, delegate(string libpath, string function) {
                // Note: IGetProcAddress implementation may have GetOpenGLProcAddress equivalent to GetProcAddress
                IntPtr procAddress = getProcAddress.GetOpenGLProcAddress(function);

                if (procAddress == IntPtr.Zero)
                {
                    return(GetProcAddress.GetProcAddressOS.GetProcAddress(libpath, function));
                }

                if (procAddress == IntPtr.Zero)
                {
                    LogComment("Warning: no address for command {0}.", function);
                }

                return(procAddress);
            }, version, extensions);
        }
示例#23
0
        public static void BindAPIFunction(FieldInfo function, KhronosVersion version, ExtensionsCollection extensions, GraphicsContext context)
        {
            Debug.Assert(function != null);

            RequiredByFeatureAttribute requiredByFeature = null;
            var    requiredByExtensions = new List <RequiredByFeatureAttribute>();
            string defaultName          = function.Name.Substring(1); // Delegate name always prefixes with 'p'

            if (version != null || extensions != null)
            {
                var removed = false;

                #region Check Requirement

                IEnumerable <Attribute> attrRequired = new List <Attribute>(function.GetCustomAttributes(typeof(RequiredByFeatureAttribute)));
                // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop
                foreach (RequiredByFeatureAttribute attr in attrRequired)
                {
                    // Check for API support
                    if (attr.IsSupported(version, extensions) == false)
                    {
                        continue;
                    }
                    // Keep track of the features requiring this command
                    if (attr.FeatureVersion != null)
                    {
                        // Version feature: keep track only of the maximum version
                        if (requiredByFeature == null || requiredByFeature.FeatureVersion < attr.FeatureVersion)
                        {
                            requiredByFeature = attr;
                        }
                    }
                    else
                    {
                        // Extension feature: collect every supporting extension
                        requiredByExtensions.Add(attr);
                    }
                }

                #endregion

                #region Check Deprecation/Removal

                if (requiredByFeature != null)
                {
                    // Note: indeed the feature could be supported; check whether it is removed; this is checked only if
                    // a non-extension feature is detected: extensions cannot remove commands
                    Attribute[]    attrRemoved       = Attribute.GetCustomAttributes(function, typeof(RemovedByFeatureAttribute));
                    KhronosVersion maxRemovedVersion = null;

                    // ReSharper disable once PossibleInvalidCastExceptionInForeachLoop
                    foreach (RemovedByFeatureAttribute attr in attrRemoved)
                    {
                        // Check for API support
                        if (attr.IsRemoved(version, extensions) == false)
                        {
                            continue;
                        }
                        // Removed!
                        removed = true;
                        // Keep track of the maximum API version removing this command
                        if (maxRemovedVersion == null || maxRemovedVersion < attr.FeatureVersion)
                        {
                            maxRemovedVersion = attr.FeatureVersion;
                        }
                    }

                    // Check for resurrection
                    if (removed)
                    {
                        Debug.Assert(requiredByFeature != null);
                        Debug.Assert(maxRemovedVersion != null);

                        if (requiredByFeature.FeatureVersion > maxRemovedVersion)
                        {
                            removed = false;
                        }
                    }
                }

                #endregion

                // Do not check feature requirements in case of removal. Note: extensions are checked all the same
                if (removed)
                {
                    requiredByFeature = null;
                }
            }

            // Load function pointer
            IntPtr   importAddress;
            Delegate importDelegate;

            if (requiredByFeature != null || version == null)
            {
                // Load command address (version feature)
                string functionName = defaultName;

                if (requiredByFeature?.EntryPoint != null)
                {
                    functionName = requiredByFeature.EntryPoint;
                }

                if (context.Native)
                {
                    if ((importAddress = context.GetProcAddress(functionName)) != IntPtr.Zero)
                    {
                        BindNativeAPIFunction(function, importAddress);
                        return;
                    }
                }
                else
                {
                    if ((importDelegate = context.GetProcAddressNonNative(functionName)) != null)
                    {
                        function.SetValue(null, importDelegate);
                        return;
                    }
                }
            }

            // Load command address (extension features)
            foreach (RequiredByFeatureAttribute extensionFeature in requiredByExtensions)
            {
                string functionName = extensionFeature.EntryPoint ?? defaultName;

                if (context.Native)
                {
                    if ((importAddress = context.GetProcAddress(functionName)) != IntPtr.Zero)
                    {
                        BindNativeAPIFunction(function, importAddress);
                        return;
                    }
                }
                else
                {
                    if ((importDelegate = context.GetProcAddressNonNative(functionName)) != null)
                    {
                        function.SetValue(null, importDelegate);
                        return;
                    }
                }
            }

            // Function not implemented: reset
            function.SetValue(null, null);
        }
示例#24
0
        /// <summary>
        /// Link delegates field using import declaration, using platform specific method for determining procedures address.
        /// </summary>
        internal static void BindAPIFunction <T>(string path, string functionName, GetAddressDelegate getProcAddress, KhronosVersion version, ExtensionsCollection extensions)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            if (functionName == null)
            {
                throw new ArgumentNullException("function");
            }
            if (getProcAddress == null)
            {
                throw new ArgumentNullException("getAddress");
            }

            FunctionContext functionContext = GetFunctionContext(typeof(T));

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

#if NETSTANDARD1_1 || NETSTANDARD1_4
            TypeInfo delegatesClass = typeof(T).GetTypeInfo().GetDeclaredNestedType("Delegates");
            Debug.Assert(delegatesClass != null);
            if (delegatesClass == null)
            {
                throw new NotImplementedException("missing Delegates class");
            }

            FieldInfo functionField = delegatesClass.GetDeclaredField("p" + functionName);
            Debug.Assert(functionField != null);
            if (functionField == null)
            {
                throw new NotImplementedException(String.Format("unable to find function named {0}", functionName));
            }
#else
            Type delegatesClass = typeof(T).GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic);
            Debug.Assert(delegatesClass != null);
            if (delegatesClass == null)
            {
                throw new NotImplementedException("missing Delegates class");
            }

            FieldInfo functionField = delegatesClass.GetField("p" + functionName, BindingFlags.Static | BindingFlags.NonPublic);
            Debug.Assert(functionField != null);
            if (functionField == null)
            {
                throw new NotImplementedException(String.Format("unable to find function named {0}", functionName));
            }
#endif

            BindAPIFunction(path, getProcAddress, functionContext, functionField, version, extensions);
        }
示例#25
0
 /// <summary>
 /// Bind a single OpenGL delegates to a specific API.
 /// </summary>
 /// <param name="version">
 /// A <see cref="KhronosVersion"/> that specifies the API to bind.
 /// </param>
 /// <param name="extensions">
 /// A <see cref="KhronosApi.ExtensionsCollection"/> that specifies the extensions supported. It can be null.
 /// </param>
 /// <param name="functionName">
 /// A <see cref="String"/> that specifies the name of the function to bind.
 /// </param>
 internal static void BindAPIFunction(KhronosVersion version, ExtensionsCollection extensions, string functionName)
 {
     BindAPIFunction <Gl>(GetPlatformLibrary(version), functionName, GetProcAddressGLOS, version, extensions);
 }
示例#26
0
        /// <summary>
        /// Check whether commands implemented by the current driver have a corresponding extension declaring the
        /// support of them.
        /// </summary>
        /// <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>
        /// <param name="enableExtensions"></param>
        protected static void CheckExtensionCommands(KhronosVersion version, ExtensionsCollection extensions, bool enableExtensions)
        {
            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }
            if (extensions == null)
            {
                throw new ArgumentNullException(nameof(extensions));
            }

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

            foreach (FieldInfo fi in _functionContext.Delegates)
            {
                var  fiDelegateType     = (Delegate)fi.GetValue(null);
                bool commandDefined     = fiDelegateType != null;
                var  supportedByFeature = false;

                // Get the delegate type
                Type delegateType = fi.DeclaringType?.GetNestedType(fi.Name.Substring(1), BindingFlags.Public | BindingFlags.NonPublic);
                if (delegateType == null)
                {
                    continue; // Support fields names not in sync with delegate types
                }
                // TODO Why not use 'fi' directly for getting attributes? They should be in sync
                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 (commandDefined)
                    {
                        if (hiddenVersionAttrib != null && hiddenExtensionAttrib == null)
                        {
                            if (hiddenVersions.TryGetValue(hiddenVersionAttrib.FeatureName, out List <Type> 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);
                            }
                        }
                    }
                }

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

            if (!enableExtensions)
            {
                return;
            }

            var sync = false;

            foreach (KeyValuePair <string, bool> hiddenExtension in hiddenExtensions.Where(hiddenExtension => hiddenExtension.Value))
            {
                extensions.EnableExtension(hiddenExtension.Key);
                sync = true;
            }

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