[Win] More robust WGL extension detection

Affects issue #42 and issue #45
This commit is contained in:
Stefanos A. 2014-01-10 09:24:59 +01:00
parent a4d2a31386
commit ef5aedba6f
2 changed files with 55 additions and 44 deletions

View file

@ -8,6 +8,7 @@
#endregion #endregion
using System; using System;
using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Reflection; using System.Reflection;
@ -34,6 +35,9 @@ namespace OpenTK.Platform.Windows
internal const string Library = "OPENGL32.DLL"; internal const string Library = "OPENGL32.DLL";
readonly static Dictionary<string, bool> extensions =
new Dictionary<string, bool>();
private static Assembly assembly; private static Assembly assembly;
private static Type wglClass; private static Type wglClass;
private static Type delegatesClass; private static Type delegatesClass;
@ -121,43 +125,61 @@ namespace OpenTK.Platform.Windows
#endregion #endregion
#region public static partial class Arb public static bool SupportsExtension(string name)
/// <summary>Contains ARB extensions for WGL.</summary>
public static partial class Arb
{ {
/// <summary> return SupportsExtension(Wgl.GetCurrentDC(), name);
/// Checks if a Wgl extension is supported by the given context. }
/// </summary>
/// <param name="context">The device context.</param> /// <summary>
/// <param name="ext">The extension to check.</param> /// Checks if a Wgl extension is supported by the given context.
/// <returns>True if the extension is supported by the given context, false otherwise</returns> /// </summary>
public static bool SupportsExtension(WinGLContext context, string ext) /// <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)
{
if (extensions.Count == 0)
{ {
// We cache this locally, as another thread might create a context which doesn't support this method. // 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 // 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 // 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 // have to create one accelerated and one non-accelerated context in the same application, with the
// non-accelerated context coming second. // non-accelerated context coming second.
Wgl.Delegates.GetExtensionsStringARB get = Wgl.Delegates.wglGetExtensionsStringARB; 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 (get != null) if (str_ptr != IntPtr.Zero)
{ {
string[] extensions = null; string str;
unsafe unsafe
{ {
extensions = new string((sbyte*)get(context.DeviceContext)) str = new string((sbyte*)str_ptr);
.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
} }
if (extensions == null || extensions.Length == 0)
return false;
foreach (string s in extensions) foreach (string ext in str.Split(' '))
if (s == ext) {
return true; 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 #endregion
@ -167,27 +189,6 @@ namespace OpenTK.Platform.Windows
/// <summary>Contains EXT extensions for WGL.</summary> /// <summary>Contains EXT extensions for WGL.</summary>
public static partial class Ext 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 #endregion

View file

@ -31,6 +31,7 @@ namespace OpenTK.Platform.Windows
IntPtr device_context; IntPtr device_context;
bool vsync_supported; bool vsync_supported;
bool vsync_tear_supported;
readonly WinGraphicsMode ModeSelector; readonly WinGraphicsMode ModeSelector;
@ -325,7 +326,13 @@ namespace OpenTK.Platform.Windows
lock (LoadLock) lock (LoadLock)
{ {
if (vsync_supported) if (vsync_supported)
{
if (value < 0 && !vsync_tear_supported)
{
value = 1;
}
Wgl.Ext.SwapInterval(value); Wgl.Ext.SwapInterval(value);
}
} }
} }
} }
@ -339,8 +346,11 @@ namespace OpenTK.Platform.Windows
lock (LoadLock) lock (LoadLock)
{ {
Wgl.LoadAll(); 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"); Wgl.Load("wglGetSwapIntervalEXT") && Wgl.Load("wglSwapIntervalEXT");
vsync_tear_supported =
Wgl.SupportsExtension(DeviceContext, "WGL_EXT_swap_tear");
} }
base.LoadAll(); base.LoadAll();