Skip to content

Commit

Permalink
Merge branch 'nvidiafix' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
thefiddler committed May 12, 2014
2 parents 50b611e + 4e8786f commit c2bd862
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 60 deletions.
111 changes: 69 additions & 42 deletions Source/OpenTK/Platform/X11/Bindings/Glx.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ enum GLXAttribute : int
LEVEL = 3, LEVEL = 3,
CONFIG_CAVEAT = 0x20, CONFIG_CAVEAT = 0x20,
RENDER_TYPE_SGIX = 0x8011, RENDER_TYPE_SGIX = 0x8011,
SWAP_INTERVAL_EXT = 0x20F1,
MAX_SWAP_INTERVAL_EXT = 0x20F2,
} }


enum GLXHyperpipeAttrib : int enum GLXHyperpipeAttrib : int
Expand Down Expand Up @@ -259,32 +261,69 @@ enum ErrorCode : int
/// <summary> /// <summary>
/// Provides access to GLX functions. /// Provides access to GLX functions.
/// </summary> /// </summary>
class Glx class Glx : Graphics.GraphicsBindingsBase
{ {
const string Library = "libGL.so.1"; const string Library = "libGL.so.1";
static readonly object sync_root = new object();


static string[] EntryPointNames = new string[] static readonly byte[] EntryPointNames = new byte[]
{ {
"glXCreateContextAttribs", // glXCreateContextAttribsARB
"glXSwapIntervalEXT", 0x67, 0x6c, 0x58, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x73, 0x41, 0x52, 0x42, 0,
"glXGetSwapIntervalEXT", // glXSwapIntervalEXT
"glXSwapIntervalMESA", 0x67, 0x6c, 0x58, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x45, 0x58, 0x54, 0,
"glXGetSwapIntervalMESA", // glXSwapIntervalMESA
"glXSwapIntervalOML", 0x67, 0x6c, 0x58, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x45, 0x53, 0x41, 0,
"glXGetSwapIntervalOML", // glXGetSwapIntervalMESA
"glXSwapIntervalSGI", 0x67, 0x6c, 0x58, 0x47, 0x65, 0x74, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x45, 0x53, 0x41, 0,
"glXGetSwapIntervalSGI", // glXSwapIntervalSGI
0x67, 0x6c, 0x58, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x47, 0x49, 0,
}; };
static IntPtr[] EntryPoints = new IntPtr[EntryPointNames.Length]; static readonly int[] EntryPointOffsets = new int[5];
static IntPtr[] EntryPoints = new IntPtr[5];


static Glx() internal Glx()
{ {
// GLX entry points are not bound to a context. // GLX entry points are not bound to a context.
// This means we can load them without creating // This means we can load them without creating
// a context first! (unlike WGL) // a context first! (unlike WGL)
for (int i = 0; i < EntryPointNames.Length; i++) _EntryPointsInstance = EntryPoints;
_EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointOffsets;

// Writing the entry point name offsets
// by hand is error prone. Do it in code
// instead:
int offset = 0;
for (int i = 0, j = 0; i < EntryPointNames.Length; i++)
{ {
EntryPoints[i] = Arb.GetProcAddress(EntryPointNames[i]); if (EntryPointNames[i] == 0)
{
EntryPointOffsets[j++] = offset;
offset = i + 1;
}
}
}

protected override object SyncRoot { get { return sync_root; } }

protected override IntPtr GetAddress(string funcname)
{
return Arb.GetProcAddress(funcname);
}

internal override void LoadEntryPoints()
{
unsafe
{
fixed (byte* name = _EntryPointNamesInstance)
{
for (int i = 0; i < _EntryPointsInstance.Length; i++)
{
_EntryPointsInstance[i] = Arb.GetProcAddress(
new IntPtr(name + _EntryPointNameOffsetsInstance[i]));
}
}
} }
} }


Expand All @@ -302,6 +341,9 @@ internal static bool SupportsFunction(string name)


[DllImport(Library, EntryPoint = "glXIsDirect")] [DllImport(Library, EntryPoint = "glXIsDirect")]
public static extern bool IsDirect(IntPtr dpy, IntPtr context); public static extern bool IsDirect(IntPtr dpy, IntPtr context);

[DllImport(Library, EntryPoint = "glXQueryDrawable")]
public static extern ErrorCode QueryDrawable(IntPtr dpy, IntPtr drawable, GLXAttribute attribute, out int value);


[DllImport(Library, EntryPoint = "glXQueryExtension")] [DllImport(Library, EntryPoint = "glXQueryExtension")]
public static extern bool QueryExtension(IntPtr dpy, ref int errorBase, ref int eventBase); public static extern bool QueryExtension(IntPtr dpy, ref int errorBase, ref int eventBase);
Expand Down Expand Up @@ -409,19 +451,16 @@ public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPt
[DllImport(Library, EntryPoint = "glXGetProcAddressARB")] [DllImport(Library, EntryPoint = "glXGetProcAddressARB")]
public static extern IntPtr GetProcAddress([MarshalAs(UnmanagedType.LPTStr)] string procName); public static extern IntPtr GetProcAddress([MarshalAs(UnmanagedType.LPTStr)] string procName);


[DllImport(Library, EntryPoint = "glXGetProcAddressARB")]
public static extern IntPtr GetProcAddress(IntPtr procName);

#endregion #endregion
} }


public partial class Ext public partial class Ext
{ {
[AutoGenerated(EntryPoint = "glXSwapIntervalEXT")] [AutoGenerated(EntryPoint = "glXSwapIntervalEXT")]
public static ErrorCode SwapInterval(int interval) public static ErrorCode SwapInterval(IntPtr display, IntPtr drawable, int interval)
{
throw new NotImplementedException();
}

[AutoGenerated(EntryPoint = "glXGetSwapIntervalEXT")]
public static int GetSwapInterval()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
Expand Down Expand Up @@ -449,35 +488,23 @@ public static ErrorCode SwapInterval(int interval)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

[AutoGenerated(EntryPoint = "glXGetSwapIntervalSGI")]
public static int GetSwapInterval()
{
throw new NotImplementedException();
}
} }


[Slot(0)] [Slot(0)]
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
internal unsafe static extern IntPtr glXCreateContextAttribsARB(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs); internal unsafe static extern IntPtr glXCreateContextAttribsARB(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs);
[Slot(1)] [Slot(1)]
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
internal static extern ErrorCode glXSwapIntervalEXT(int interval); internal static extern ErrorCode glXSwapIntervalEXT(IntPtr display, IntPtr drawable, int interval);
[Slot(2)] [Slot(2)]
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
internal static extern int glXGetSwapIntervalEXT();
[Slot(3)]
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
internal static extern ErrorCode glXSwapIntervalMESA(int interval); internal static extern ErrorCode glXSwapIntervalMESA(int interval);
[Slot(4)] [Slot(3)]
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
internal static extern int glXGetSwapIntervalMESA(); internal static extern int glXGetSwapIntervalMESA();
[Slot(5)] [Slot(4)]
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
internal static extern ErrorCode glXSwapIntervalSGI(int interval); internal static extern ErrorCode glXSwapIntervalSGI(int interval);
[Slot(6)]
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
internal static extern int glXGetSwapIntervalSGI();


#endregion #endregion
} }
Expand Down
67 changes: 49 additions & 18 deletions Source/OpenTK/Platform/X11/X11GLContext.cs
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ internal sealed class X11GLContext : DesktopGraphicsContext


#region --- Constructors --- #region --- Constructors ---


static X11GLContext()
{
new Glx().LoadEntryPoints();
}

public X11GLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shared, bool direct, public X11GLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shared, bool direct,
int major, int minor, GraphicsContextFlags flags) int major, int minor, GraphicsContextFlags flags)
{ {
Expand Down Expand Up @@ -258,8 +263,7 @@ bool SupportsCreateContextAttribs(IntPtr display, X11WindowInfo window)
{ {
return return
SupportsExtension(display, window, "GLX_ARB_create_context") && SupportsExtension(display, window, "GLX_ARB_create_context") &&
SupportsExtension(display, window, "GLX_ARB_create_context_profile") && SupportsExtension(display, window, "GLX_ARB_create_context_profile");
Glx.SupportsFunction("glXCreateContextAttribsARB");
} }


#endregion #endregion
Expand Down Expand Up @@ -359,20 +363,40 @@ public override int SwapInterval
{ {
get get
{ {
if (currentWindow == null)
{
Debug.Print("Context must be current");
throw new InvalidOperationException();
}

using (new XLock(display)) using (new XLock(display))
{ {
if (vsync_ext_supported) if (vsync_ext_supported)
return Glx.Ext.GetSwapInterval(); {
int value;
Glx.QueryDrawable(Display, currentWindow.Handle, GLXAttribute.SWAP_INTERVAL_EXT, out value);
return value;
}
else if (vsync_mesa_supported) else if (vsync_mesa_supported)
{
return Glx.Mesa.GetSwapInterval(); return Glx.Mesa.GetSwapInterval();
}
else if (vsync_sgi_supported) else if (vsync_sgi_supported)
{
return sgi_swap_interval; return sgi_swap_interval;
else }
return 0;
return 0;
} }
} }
set set
{ {
if (currentWindow == null)
{
Debug.Print("Context must be current");
throw new InvalidOperationException();
}

if (value < 0 && !vsync_tear_supported) if (value < 0 && !vsync_tear_supported)
{ {
value = 1; value = 1;
Expand All @@ -382,11 +406,17 @@ public override int SwapInterval
using (new XLock(Display)) using (new XLock(Display))
{ {
if (vsync_ext_supported) if (vsync_ext_supported)
error_code = Glx.Ext.SwapInterval(value); {
Glx.Ext.SwapInterval(Display, currentWindow.Handle, value);
}
else if (vsync_mesa_supported) else if (vsync_mesa_supported)
{
error_code = Glx.Mesa.SwapInterval(value); error_code = Glx.Mesa.SwapInterval(value);
}
else if (vsync_sgi_supported) else if (vsync_sgi_supported)
{
error_code = Glx.Sgi.SwapInterval(value); error_code = Glx.Sgi.SwapInterval(value);
}
} }


if (error_code == X11.ErrorCode.NO_ERROR) if (error_code == X11.ErrorCode.NO_ERROR)
Expand All @@ -402,23 +432,24 @@ public override int SwapInterval


public override void LoadAll() public override void LoadAll()
{ {
// Note: GLX entry points are always available, even
// for extensions that are not currently supported by
// the underlying driver. This means we can only check
// the extension strings for support, not the entry
// points themselves.
vsync_ext_supported = vsync_ext_supported =
SupportsExtension(display, currentWindow, "GLX_EXT_swap_control") && SupportsExtension(display, currentWindow, "GLX_EXT_swap_control");
Glx.SupportsFunction("glXSwapIntervalEXT") &&
Glx.SupportsFunction("glXGetSwapIntervalEXT");
vsync_mesa_supported = vsync_mesa_supported =
SupportsExtension(display, currentWindow, "GLX_MESA_swap_control") && SupportsExtension(display, currentWindow, "GLX_MESA_swap_control");
Glx.SupportsFunction("glXSwapIntervalMESA") &&
Glx.SupportsFunction("glXGetSwapIntervalMESA");
vsync_sgi_supported = vsync_sgi_supported =
SupportsExtension(display, currentWindow, "GLX_SGI_swap_control") && SupportsExtension(display, currentWindow, "GLX_SGI_swap_control");
Glx.SupportsFunction("glXSwapIntervalSGI");
Debug.Print("Context supports vsync: {0}.",
vsync_ext_supported || vsync_mesa_supported || vsync_ext_supported);

vsync_tear_supported = vsync_tear_supported =
SupportsExtension(display, currentWindow, "GLX_EXT_swap_control_tear"); SupportsExtension(display, currentWindow, "GLX_EXT_swap_control_tear");
Debug.Print("Context supports vsync tear: {0}.", vsync_tear_supported);
Debug.Print("Context supports vsync: {0}.",
vsync_ext_supported || vsync_mesa_supported || vsync_sgi_supported);
Debug.Print("Context supports adaptive vsync: {0}.",
vsync_tear_supported);


base.LoadAll(); base.LoadAll();
} }
Expand Down

0 comments on commit c2bd862

Please sign in to comment.