[Win] More robust WGL extension detection
authorStefanos A. <stapostol@gmail.com>
Fri, 10 Jan 2014 08:24:59 +0000 (09:24 +0100)
committerStefanos A. <stapostol@gmail.com>
Fri, 10 Jan 2014 08:24:59 +0000 (09:24 +0100)
Affects issue #42 and issue #45

Source/OpenTK/Platform/Windows/WglHelper.cs
Source/OpenTK/Platform/Windows/WinGLContext.cs

index fd1c3de..0e86321 100644 (file)
@@ -8,6 +8,7 @@
 #endregion
 
 using System;
+using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Reflection;
 
@@ -34,6 +35,9 @@ namespace OpenTK.Platform.Windows
 
         internal const string Library = "OPENGL32.DLL";
 
+        readonly static Dictionary<string, bool> extensions =
+            new Dictionary<string, bool>();
+
         private static Assembly assembly;
         private static Type wglClass;
         private static Type delegatesClass;
@@ -121,43 +125,61 @@ namespace OpenTK.Platform.Windows
 
         #endregion
 
-        #region public static partial class Arb
+        public static bool SupportsExtension(string name)
+        {
+            return SupportsExtension(Wgl.GetCurrentDC(), name);
+        }
 
-        /// <summary>Contains ARB extensions for WGL.</summary>
-        public static partial class Arb
+        /// <summary>
+        /// Checks if a Wgl extension is supported by the given context.
+        /// </summary>
+        /// <param name="context">The device context.</param>
+        /// <param name="ext">The extension to check.</param>
+        /// <returns>True if the extension is supported by the given context, false otherwise</returns>
+        public static bool SupportsExtension(IntPtr dc, string name)
         {
-            /// <summary>
-            /// Checks if a Wgl extension is supported by the given context.
-            /// </summary>
-            /// <param name="context">The device context.</param>
-            /// <param name="ext">The extension to check.</param>
-            /// <returns>True if the extension is supported by the given context, false otherwise</returns>
-            public static bool SupportsExtension(WinGLContext context, string ext)
+            if (extensions.Count == 0)
             {
                 // We cache this locally, as another thread might create a context which doesn't support  this method.
                 // The design is far from ideal, but there's no good solution to this issue as long as we are using
                 // static WGL/GL classes. Fortunately, this issue is extremely unlikely to arise in practice, as you'd
                 // have to create one accelerated and one non-accelerated context in the same application, with the
                 // non-accelerated context coming second.
-                Wgl.Delegates.GetExtensionsStringARB get = Wgl.Delegates.wglGetExtensionsStringARB;
-
-                if (get != null)
+                Wgl.Delegates.GetExtensionsStringARB get_arb = Wgl.Delegates.wglGetExtensionsStringARB;
+                Wgl.Delegates.GetExtensionsStringEXT get_ext = Wgl.Delegates.wglGetExtensionsStringEXT;
+                IntPtr str_ptr =
+                    get_arb != null ? get_arb(dc) :
+                    get_ext != null ? get_ext() :
+                    IntPtr.Zero;
+
+                if (str_ptr != IntPtr.Zero)
                 {
-                    string[] extensions = null;
+                    string str;
+
                     unsafe
                     {
-                        extensions = new string((sbyte*)get(context.DeviceContext))
-                            .Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
+                        str = new string((sbyte*)str_ptr);
                     }
-                    if (extensions == null || extensions.Length == 0)
-                        return false;
 
-                    foreach (string s in extensions)
-                        if (s == ext)
-                            return true;
+                    foreach (string ext in str.Split(' '))
+                    {
+                        extensions.Add(ext, true);
+                    }
                 }
-                return false;
             }
+
+            if (extensions.Count > 0)
+            {
+                return extensions.ContainsKey(name);
+            }
+            return false;
+        }
+
+        #region public static partial class Arb
+
+        /// <summary>Contains ARB extensions for WGL.</summary>
+        public static partial class Arb
+        {
         }
 
         #endregion 
@@ -167,27 +189,6 @@ namespace OpenTK.Platform.Windows
         /// <summary>Contains EXT extensions for WGL.</summary>
         public static partial class Ext
         {
-            private static string[] extensions;
-            /// <summary>
-            /// Checks if a Wgl extension is supported by the given context.
-            /// </summary>
-            /// <param name="ext">The extension to check.</param>
-            /// <returns>True if the extension is supported by the given context, false otherwise</returns>
-            public static bool SupportsExtension(string ext)
-            {
-                if (Wgl.Delegates.wglGetExtensionsStringEXT != null)
-                {
-                    if (extensions == null || rebuildExtensionList)
-                    {
-                        extensions = Wgl.Ext.GetExtensionsString().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
-                        Array.Sort(extensions);
-                        rebuildExtensionList = false;
-                    }
-
-                    return Array.BinarySearch(extensions, ext) != -1;
-                }
-                return false;
-            }
         }
 
         #endregion
index 837c3e7..af55d3e 100644 (file)
@@ -31,6 +31,7 @@ namespace OpenTK.Platform.Windows
 
         IntPtr device_context;
         bool vsync_supported;
+        bool vsync_tear_supported;
 
         readonly WinGraphicsMode ModeSelector;
 
@@ -325,7 +326,13 @@ namespace OpenTK.Platform.Windows
                 lock (LoadLock)
                 {
                     if (vsync_supported)
+                    {
+                        if (value < 0 && !vsync_tear_supported)
+                        {
+                            value = 1;
+                        }
                         Wgl.Ext.SwapInterval(value);
+                    }
                 }
             }
         }
@@ -339,8 +346,11 @@ namespace OpenTK.Platform.Windows
             lock (LoadLock)
             {
                 Wgl.LoadAll();
-                vsync_supported = Wgl.Arb.SupportsExtension(this, "WGL_EXT_swap_control") &&
+                vsync_supported =
+                    Wgl.SupportsExtension(DeviceContext, "WGL_EXT_swap_control") &&
                     Wgl.Load("wglGetSwapIntervalEXT") && Wgl.Load("wglSwapIntervalEXT");
+                vsync_tear_supported =
+                    Wgl.SupportsExtension(DeviceContext, "WGL_EXT_swap_tear");
             }
 
             base.LoadAll();