Removed unimplement SetPixelFormatARB - no such function exists.
Added aggressive locking during context creation and delegate loading in order to avoid potential race conditions. Now uses Wgl.Imports directly wherever possible in order to improve performance and avoid race conditions. Slightly improved debugging messages.
This commit is contained in:
parent
9150a99252
commit
045d3d73f6
1 changed files with 116 additions and 98 deletions
|
@ -27,7 +27,8 @@ namespace OpenTK.Platform.Windows
|
|||
/// </summary>
|
||||
internal sealed class WinGLContext : DesktopGraphicsContext
|
||||
{
|
||||
static object SyncRoot = new object();
|
||||
static readonly object LoadLock = new object();
|
||||
static readonly object SyncRoot = new object();
|
||||
|
||||
static IntPtr opengl32Handle;
|
||||
static bool wgl_loaded;
|
||||
|
@ -39,18 +40,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
static WinGLContext()
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
// Dynamically load the OpenGL32.dll in order to use the extension loading capabilities of Wgl.
|
||||
if (opengl32Handle == IntPtr.Zero)
|
||||
{
|
||||
opengl32Handle = Functions.LoadLibrary(opengl32Name);
|
||||
if (opengl32Handle == IntPtr.Zero)
|
||||
throw new ApplicationException(String.Format("LoadLibrary(\"{0}\") call failed with code {1}",
|
||||
opengl32Name, Marshal.GetLastWin32Error()));
|
||||
Debug.WriteLine(String.Format("Loaded opengl32.dll: {0}", opengl32Handle));
|
||||
}
|
||||
}
|
||||
Init();
|
||||
}
|
||||
|
||||
public WinGLContext(GraphicsMode format, WinWindowInfo window, IGraphicsContext sharedContext,
|
||||
|
@ -68,58 +58,60 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
Mode = format;
|
||||
|
||||
Debug.Print("OpenGL will be bound to handle: {0}", window.WindowHandle);
|
||||
Debug.Write("Setting pixel format... ");
|
||||
Debug.Print("OpenGL will be bound to window:{0} on thread:{1}", window.WindowHandle,
|
||||
System.Threading.Thread.CurrentThread.ManagedThreadId);
|
||||
this.SetGraphicsModePFD(format, (WinWindowInfo)window);
|
||||
|
||||
if (!wgl_loaded)
|
||||
lock (LoadLock)
|
||||
{
|
||||
// We need to create a temp context in order to load wgl extensions (e.g. for multisampling or GL3).
|
||||
// We cannot rely on OpenTK.Platform.Wgl until we create the context and call Wgl.LoadAll().
|
||||
Debug.Print("Creating temporary context for wgl extensions.");
|
||||
|
||||
ContextHandle temp_context = new ContextHandle(Wgl.Imports.CreateContext(window.DeviceContext));
|
||||
Wgl.Imports.MakeCurrent(window.DeviceContext, temp_context.Handle);
|
||||
Wgl.LoadAll();
|
||||
Wgl.MakeCurrent(IntPtr.Zero, IntPtr.Zero);
|
||||
Wgl.DeleteContext(temp_context.Handle);
|
||||
wgl_loaded = true;
|
||||
}
|
||||
|
||||
if (Wgl.Delegates.wglCreateContextAttribsARB != null)
|
||||
{
|
||||
try
|
||||
if (!wgl_loaded)
|
||||
{
|
||||
Debug.Write("Using WGL_ARB_create_context... ");
|
||||
|
||||
List<int> attributes = new List<int>();
|
||||
attributes.Add((int)ArbCreateContext.MajorVersion);
|
||||
attributes.Add(major);
|
||||
attributes.Add((int)ArbCreateContext.MinorVersion);
|
||||
attributes.Add(minor);
|
||||
if (flags != 0)
|
||||
{
|
||||
attributes.Add((int)ArbCreateContext.Flags);
|
||||
#warning "This is not entirely correct: Embedded is not a valid flag! We need to add a GetARBContextFlags(GraphicsContextFlags) method."
|
||||
attributes.Add((int)flags);
|
||||
}
|
||||
// According to the docs, " <attribList> specifies a list of attributes for the context.
|
||||
// The list consists of a sequence of <name,value> pairs terminated by the
|
||||
// value 0. [...]"
|
||||
// Is this a single 0, or a <0, 0> pair? (Defensive coding: add two zeroes just in case).
|
||||
attributes.Add(0);
|
||||
attributes.Add(0);
|
||||
|
||||
Handle = new ContextHandle(
|
||||
Wgl.Arb.CreateContextAttribs(
|
||||
window.DeviceContext,
|
||||
sharedContext != null ? (sharedContext as IGraphicsContextInternal).Context.Handle : IntPtr.Zero,
|
||||
attributes.ToArray()));
|
||||
if (Handle == ContextHandle.Zero)
|
||||
Debug.Print("failed. (Error: {0})", Marshal.GetLastWin32Error());
|
||||
// We need to create a temp context in order to load wgl extensions (e.g. for multisampling or GL3).
|
||||
// We cannot rely on OpenTK.Platform.Wgl until we create the context and call Wgl.LoadAll().
|
||||
Debug.Print("Creating temporary context for wgl extensions.");
|
||||
ContextHandle temp_context = new ContextHandle(Wgl.Imports.CreateContext(window.DeviceContext));
|
||||
Wgl.Imports.MakeCurrent(window.DeviceContext, temp_context.Handle);
|
||||
Wgl.LoadAll();
|
||||
Wgl.Imports.MakeCurrent(IntPtr.Zero, IntPtr.Zero);
|
||||
Wgl.Imports.DeleteContext(temp_context.Handle);
|
||||
wgl_loaded = true;
|
||||
}
|
||||
|
||||
if (Wgl.Delegates.wglCreateContextAttribsARB != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Debug.Write("Using WGL_ARB_create_context... ");
|
||||
|
||||
List<int> attributes = new List<int>();
|
||||
attributes.Add((int)ArbCreateContext.MajorVersion);
|
||||
attributes.Add(major);
|
||||
attributes.Add((int)ArbCreateContext.MinorVersion);
|
||||
attributes.Add(minor);
|
||||
if (flags != 0)
|
||||
{
|
||||
attributes.Add((int)ArbCreateContext.Flags);
|
||||
#warning "This is not entirely correct: Embedded is not a valid flag! We need to add a GetARBContextFlags(GraphicsContextFlags) method."
|
||||
attributes.Add((int)flags);
|
||||
}
|
||||
// According to the docs, " <attribList> specifies a list of attributes for the context.
|
||||
// The list consists of a sequence of <name,value> pairs terminated by the
|
||||
// value 0. [...]"
|
||||
// Is this a single 0, or a <0, 0> pair? (Defensive coding: add two zeroes just in case).
|
||||
attributes.Add(0);
|
||||
attributes.Add(0);
|
||||
|
||||
Handle = new ContextHandle(
|
||||
Wgl.Arb.CreateContextAttribs(
|
||||
window.DeviceContext,
|
||||
sharedContext != null ? (sharedContext as IGraphicsContextInternal).Context.Handle : IntPtr.Zero,
|
||||
attributes.ToArray()));
|
||||
if (Handle == ContextHandle.Zero)
|
||||
Debug.Print("failed. (Error: {0})", Marshal.GetLastWin32Error());
|
||||
}
|
||||
catch (EntryPointNotFoundException e) { Debug.Print(e.ToString()); }
|
||||
catch (NullReferenceException e) { Debug.Print(e.ToString()); }
|
||||
}
|
||||
catch (EntryPointNotFoundException e) { Debug.Print(e.ToString()); }
|
||||
catch (NullReferenceException e) { Debug.Print(e.ToString()); }
|
||||
}
|
||||
|
||||
if (Handle == ContextHandle.Zero)
|
||||
|
@ -140,7 +132,7 @@ namespace OpenTK.Platform.Windows
|
|||
if (sharedContext != null)
|
||||
{
|
||||
Marshal.GetLastWin32Error();
|
||||
Debug.Write("Sharing state with context {0}: ", sharedContext.ToString());
|
||||
Debug.Write(String.Format("Sharing state with context {0}: ", sharedContext));
|
||||
bool result = Wgl.Imports.ShareLists((sharedContext as IGraphicsContextInternal).Context.Handle, Handle.Handle);
|
||||
Debug.WriteLine(result ? "success!" : "failed with win32 error " + Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
@ -160,13 +152,13 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
#region --- IGraphicsContext Members ---
|
||||
#region IGraphicsContext Members
|
||||
|
||||
#region SwapBuffers
|
||||
|
||||
public override void SwapBuffers()
|
||||
{
|
||||
if (!Functions.SwapBuffers(Wgl.GetCurrentDC()))
|
||||
if (!Functions.SwapBuffers(DeviceContext))
|
||||
throw new GraphicsContextException(String.Format(
|
||||
"Failed to swap buffers for context {0} current. Error: {1}", this, Marshal.GetLastWin32Error()));
|
||||
}
|
||||
|
@ -177,30 +169,36 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
public override void MakeCurrent(IWindowInfo window)
|
||||
{
|
||||
bool success;
|
||||
|
||||
if (window != null)
|
||||
lock (SyncRoot)
|
||||
lock (LoadLock)
|
||||
{
|
||||
if (((WinWindowInfo)window).WindowHandle == IntPtr.Zero)
|
||||
throw new ArgumentException("window", "Must point to a valid window.");
|
||||
bool success;
|
||||
|
||||
success = Wgl.Imports.MakeCurrent(((WinWindowInfo)window).DeviceContext, Handle.Handle);
|
||||
if (window != null)
|
||||
{
|
||||
if (((WinWindowInfo)window).WindowHandle == IntPtr.Zero)
|
||||
throw new ArgumentException("window", "Must point to a valid window.");
|
||||
|
||||
success = Wgl.Imports.MakeCurrent(((WinWindowInfo)window).DeviceContext, Handle.Handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = Wgl.Imports.MakeCurrent(IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
throw new GraphicsContextException(String.Format(
|
||||
"Failed to make context {0} current. Error: {1}", this, Marshal.GetLastWin32Error()));
|
||||
}
|
||||
else
|
||||
success = Wgl.Imports.MakeCurrent(IntPtr.Zero, IntPtr.Zero);
|
||||
|
||||
if (!success)
|
||||
throw new GraphicsContextException(String.Format(
|
||||
"Failed to make context {0} current. Error: {1}", this, Marshal.GetLastWin32Error()));
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsCurrent
|
||||
|
||||
public override bool IsCurrent
|
||||
{
|
||||
get { return Wgl.GetCurrentContext() == Handle.Handle; }
|
||||
get { return Wgl.Imports.GetCurrentContext() == Handle.Handle; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -214,12 +212,18 @@ namespace OpenTK.Platform.Windows
|
|||
{
|
||||
get
|
||||
{
|
||||
return vsync_supported && Wgl.Ext.GetSwapInterval() != 0;
|
||||
lock (LoadLock)
|
||||
{
|
||||
return vsync_supported && Wgl.Ext.GetSwapInterval() != 0;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (vsync_supported)
|
||||
Wgl.Ext.SwapInterval(value ? 1 : 0);
|
||||
lock (LoadLock)
|
||||
{
|
||||
if (vsync_supported)
|
||||
Wgl.Ext.SwapInterval(value ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,9 +233,12 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
public override void LoadAll()
|
||||
{
|
||||
Wgl.LoadAll();
|
||||
vsync_supported = Wgl.Arb.SupportsExtension(this, "WGL_EXT_swap_control") &&
|
||||
Wgl.Load("wglGetSwapIntervalEXT") && Wgl.Load("wglSwapIntervalEXT");
|
||||
lock (LoadLock)
|
||||
{
|
||||
Wgl.LoadAll();
|
||||
vsync_supported = Wgl.Arb.SupportsExtension(this, "WGL_EXT_swap_control") &&
|
||||
Wgl.Load("wglGetSwapIntervalEXT") && Wgl.Load("wglSwapIntervalEXT");
|
||||
}
|
||||
|
||||
base.LoadAll();
|
||||
}
|
||||
|
@ -240,7 +247,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
#region --- IGLContextInternal Members ---
|
||||
#region IGLContextInternal Members
|
||||
|
||||
#region IWindowInfo IGLContextInternal.Info
|
||||
/*
|
||||
|
@ -262,12 +269,15 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
#region --- Private Methods ---
|
||||
#region Private Methods
|
||||
|
||||
#region void SetGraphicsModePFD(GraphicsMode format, WinWindowInfo window)
|
||||
#region SetGraphicsModePFD
|
||||
|
||||
// Note: there is no relevant ARB function.
|
||||
void SetGraphicsModePFD(GraphicsMode mode, WinWindowInfo window)
|
||||
{
|
||||
Debug.Write("Setting pixel format... ");
|
||||
|
||||
if (!mode.Index.HasValue)
|
||||
throw new GraphicsModeException("Invalid or unsupported GraphicsMode.");
|
||||
|
||||
|
@ -281,20 +291,12 @@ namespace OpenTK.Platform.Windows
|
|||
throw new GraphicsContextException(String.Format(
|
||||
"Requested GraphicsMode not available. SetPixelFormat error: {0}", Marshal.GetLastWin32Error()));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region void SetGraphicsModeARB(GraphicsMode format, IWindowInfo window)
|
||||
|
||||
void SetGraphicsModeARB(GraphicsMode format, IWindowInfo window)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Internal Methods ---
|
||||
#region Internal Methods
|
||||
|
||||
#region internal IntPtr DeviceContext
|
||||
|
||||
|
@ -302,16 +304,32 @@ namespace OpenTK.Platform.Windows
|
|||
{
|
||||
get
|
||||
{
|
||||
return Wgl.GetCurrentDC();
|
||||
return Wgl.Imports.GetCurrentDC();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
static internal void Init()
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
// Dynamically load the OpenGL32.dll in order to use the extension loading capabilities of Wgl.
|
||||
if (opengl32Handle == IntPtr.Zero)
|
||||
{
|
||||
opengl32Handle = Functions.LoadLibrary(opengl32Name);
|
||||
if (opengl32Handle == IntPtr.Zero)
|
||||
throw new ApplicationException(String.Format("LoadLibrary(\"{0}\") call failed with code {1}",
|
||||
opengl32Name, Marshal.GetLastWin32Error()));
|
||||
Debug.WriteLine(String.Format("Loaded opengl32.dll: {0}", opengl32Handle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Overrides ---
|
||||
#region Overrides
|
||||
|
||||
/// <summary>Returns a System.String describing this OpenGL context.</summary>
|
||||
/// <returns>A System.String describing this OpenGL context.</returns>
|
||||
|
@ -322,7 +340,7 @@ namespace OpenTK.Platform.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
#region --- IDisposable Members ---
|
||||
#region IDisposable Members
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue