Added automatic error checking for all OpenGL function calls (debug mode only). Begin()-End() regions are handled correctly.
This commit is contained in:
parent
3914aaa1e6
commit
fc103aa8ec
6 changed files with 203 additions and 81 deletions
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// The Open Toolkit Library License
|
||||
//
|
||||
// Copyright (c) 2006 - 2008 the Open Toolkit library, except where noted.
|
||||
// Copyright (c) 2006 - 2009 the Open Toolkit library.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -350,11 +350,7 @@ namespace Bind.Structures
|
|||
{
|
||||
// No special wrapper needed - just call this delegate:
|
||||
Function f = new Function(this);
|
||||
|
||||
if (f.ReturnType.CurrentType.ToLower().Contains("void"))
|
||||
f.Body.Add(String.Format("{0};", f.CallString()));
|
||||
else
|
||||
f.Body.Add(String.Format("return {0};", f.CallString()));
|
||||
f.CreateBody(false);
|
||||
|
||||
wrappers.Add(f);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,11 @@ namespace Bind.Structures
|
|||
static Regex endings = new Regex(@"((([df]|u?[isb])v?)|v)", RegexOptions.Compiled | RegexOptions.RightToLeft);
|
||||
static Regex endingsNotToTrim = new Regex("(ib|[tdrey]s|[eE]n[vd]|bled|Flagv|Tess|Status|Pixels)", RegexOptions.Compiled | RegexOptions.RightToLeft);
|
||||
|
||||
// Add a trailing v to functions matching this regex. Used to differntiate between overloads taking both
|
||||
// a 'type' and a 'ref type' (such overloads are not CLS Compliant).
|
||||
// The default Regex matches no functions. Create a new Regex in Bind.Generator classes to override the default behavior.
|
||||
internal static Regex endingsAddV = new Regex("^0", RegexOptions.Compiled);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
@ -44,15 +49,6 @@ namespace Bind.Structures
|
|||
int index;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Add a trailing v to functions matching this regex. Used to differntiate between overloads taking both
|
||||
/// a 'type' and a 'ref type' (such overloads are not CLS Compliant).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default Regex matches no functions. Create a new Regex in Bind.Generator classes to override the default behavior.
|
||||
/// </remarks>
|
||||
internal static Regex endingsAddV = new Regex("^0", RegexOptions.Compiled);
|
||||
|
||||
#region --- Constructors ---
|
||||
|
||||
|
@ -72,12 +68,16 @@ namespace Bind.Structures
|
|||
|
||||
#endregion
|
||||
|
||||
#region public Delegate WrappedDelegate
|
||||
|
||||
public Delegate WrappedDelegate
|
||||
{
|
||||
get { return wrapped_delegate; }
|
||||
set { wrapped_delegate = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public void TurnVoidPointersToIntPtr()
|
||||
|
||||
public void TurnVoidPointersToIntPtr()
|
||||
|
@ -394,10 +394,10 @@ namespace Bind.Structures
|
|||
|
||||
#region public void CreateBody(bool wantCLSCompliance)
|
||||
|
||||
static List<string> handle_statements = new List<string>();
|
||||
static List<string> handle_release_statements = new List<string>();
|
||||
static List<string> fixed_statements = new List<string>();
|
||||
static List<string> assign_statements = new List<string>();
|
||||
readonly List<string> handle_statements = new List<string>();
|
||||
readonly List<string> handle_release_statements = new List<string>();
|
||||
readonly List<string> fixed_statements = new List<string>();
|
||||
readonly List<string> assign_statements = new List<string>();
|
||||
|
||||
public void CreateBody(bool wantCLSCompliance)
|
||||
{
|
||||
|
@ -459,7 +459,21 @@ namespace Bind.Structures
|
|||
}
|
||||
}
|
||||
|
||||
if (!f.Unsafe || fixed_statements.Count > 0)
|
||||
// Automatic OpenGL error checking.
|
||||
// See OpenTK.Graphics.ErrorHelper for more information.
|
||||
// Make sure that no error checking is added to the GetError function,
|
||||
// as that would cause infinite recursion!
|
||||
if (f.TrimmedName != "GetError")
|
||||
{
|
||||
f.Body.Add("#if DEBUG");
|
||||
f.Body.Add("using (new ErrorHelper(GraphicsContext.CurrentContext))");
|
||||
f.Body.Add("{");
|
||||
if (f.TrimmedName == "Begin")
|
||||
f.Body.Add("GraphicsContext.CurrentContext.EnterBeginRegion();");
|
||||
f.Body.Add("#endif");
|
||||
}
|
||||
|
||||
if (!f.Unsafe && fixed_statements.Count > 0)
|
||||
{
|
||||
f.Body.Add("unsafe");
|
||||
f.Body.Add("{");
|
||||
|
@ -529,7 +543,7 @@ namespace Bind.Structures
|
|||
f.Body.Add("}");
|
||||
}
|
||||
|
||||
if (!f.Unsafe || fixed_statements.Count > 0)
|
||||
if (!f.Unsafe && fixed_statements.Count > 0)
|
||||
{
|
||||
f.Body.Unindent();
|
||||
f.Body.Add("}");
|
||||
|
@ -541,6 +555,15 @@ namespace Bind.Structures
|
|||
f.Body.Add("}");
|
||||
}
|
||||
|
||||
if (f.TrimmedName != "GetError")
|
||||
{
|
||||
f.Body.Add("#if DEBUG");
|
||||
if (f.TrimmedName == "End")
|
||||
f.Body.Add("GraphicsContext.CurrentContext.ExitBeginRegion();");
|
||||
f.Body.Add("}");
|
||||
f.Body.Add("#endif");
|
||||
}
|
||||
|
||||
this.Body = f.Body;
|
||||
}
|
||||
|
||||
|
|
74
Source/OpenTK/Graphics/GL/ErrorHelper.cs
Normal file
74
Source/OpenTK/Graphics/GL/ErrorHelper.cs
Normal file
|
@ -0,0 +1,74 @@
|
|||
#region License
|
||||
//
|
||||
// The Open Toolkit Library License
|
||||
//
|
||||
// Copyright (c) 2006 - 2009 the Open Toolkit library.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenTK.Graphics
|
||||
{
|
||||
// Used in debug-mode only, for automatic OpenGL error-checking.
|
||||
//
|
||||
// Works like this: an instance is created before each OpenGL function is called.
|
||||
// The constructor resets the OpenGL error state. Once the native function returns,
|
||||
// the error state is checked again, raising the relevant exceptions.
|
||||
//
|
||||
// A using-region is used to ensure Dispose() is called.
|
||||
//
|
||||
// Make sure that no error checking is added to the GetError function,
|
||||
// as that would cause infinite recursion!
|
||||
struct ErrorHelper : IDisposable
|
||||
{
|
||||
#region Fields
|
||||
|
||||
readonly GraphicsContext Context;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public ErrorHelper(GraphicsContext context)
|
||||
{
|
||||
if (context == null)
|
||||
throw new GraphicsContextMissingException();
|
||||
|
||||
Context = context;
|
||||
Context.ResetErrors();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Context.CheckErrors();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -266,7 +266,6 @@ namespace OpenTK.Graphics
|
|||
MethodInfo m;
|
||||
return
|
||||
GetExtensionDelegate(name, signature) ??
|
||||
/*((m = importsClass.GetMethod(name.Substring(2), BindingFlags.Static | BindingFlags.NonPublic)) != null ?*/
|
||||
(Imports.FunctionMap.TryGetValue((name.Substring(2)), out m) ?
|
||||
Delegate.CreateDelegate(signature, m) : null);
|
||||
}
|
||||
|
|
|
@ -120,6 +120,8 @@ namespace OpenTK.Graphics
|
|||
|
||||
#region --- Static Members ---
|
||||
|
||||
#region public static GraphicsContext CreateDummyContext()
|
||||
|
||||
/// <summary>
|
||||
/// Creates a dummy GraphicsContext to allow OpenTK to work with contexts created by external libraries.
|
||||
/// </summary>
|
||||
|
@ -143,34 +145,27 @@ namespace OpenTK.Graphics
|
|||
|
||||
#endregion
|
||||
|
||||
#region --- Private Members ---
|
||||
|
||||
#region void ContextDestroyed(IGraphicsContext context, EventArgs e)
|
||||
#region public static void Assert()
|
||||
|
||||
/// <summary>
|
||||
/// Handles the Destroy event.
|
||||
/// Checks if a GraphicsContext exists in the calling thread and throws a GraphicsContextException if it doesn't.
|
||||
/// </summary>
|
||||
/// <param name="context">The OpenTK.Platform.IGraphicsContext that was destroyed.</param>
|
||||
/// <param name="e">Not used.</param>
|
||||
void ContextDestroyed(IGraphicsContext context, EventArgs e)
|
||||
/// <exception cref="GraphicsContextMissingException">Generated when no GraphicsContext is current in the calling thread.</exception>
|
||||
public static void Assert()
|
||||
{
|
||||
this.Destroy -= ContextDestroyed;
|
||||
//available_contexts.Remove(((IGraphicsContextInternal)this).Context);
|
||||
if (GraphicsContext.CurrentContext == null)
|
||||
throw new GraphicsContextMissingException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Public Members ---
|
||||
|
||||
#region public static IGraphicsContext CurrentContext
|
||||
|
||||
internal delegate ContextHandle GetCurrentContextDelegate();
|
||||
internal static GetCurrentContextDelegate GetCurrentContext;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current GraphicsContext in the calling thread.
|
||||
/// Gets the GraphicsContext that is current in the calling thread.
|
||||
/// </summary>
|
||||
public static GraphicsContext CurrentContext
|
||||
{
|
||||
|
@ -187,13 +182,6 @@ namespace OpenTK.Graphics
|
|||
return null;
|
||||
}
|
||||
}
|
||||
//set
|
||||
//{
|
||||
// if (value != null)
|
||||
// value.MakeCurrent();
|
||||
// else if (CurrentContext != null)
|
||||
// CurrentContext.IsCurrent = false;
|
||||
//}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -231,20 +219,84 @@ namespace OpenTK.Graphics
|
|||
|
||||
#endregion
|
||||
|
||||
#region public static AvailableDisplayFormats
|
||||
#endregion
|
||||
|
||||
#region --- Internal Members ---
|
||||
|
||||
bool inside_begin_region;
|
||||
List<ErrorCode> error_list = new List<ErrorCode>();
|
||||
|
||||
// Indicates that we entered a GL.Begin() - GL.End() region.
|
||||
[Conditional("DEBUG")]
|
||||
internal void EnterBeginRegion()
|
||||
{
|
||||
inside_begin_region = true;
|
||||
}
|
||||
|
||||
// Indicates that we left a GL.Begin() - GL.End() region.
|
||||
[Conditional("DEBUG")]
|
||||
internal void ExitBeginRegion()
|
||||
{
|
||||
inside_begin_region = false;
|
||||
}
|
||||
|
||||
// Retrieve all OpenGL errors to clear the error list.
|
||||
// See http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/geterror.html
|
||||
[Conditional("DEBUG")]
|
||||
internal void ResetErrors()
|
||||
{
|
||||
if (!inside_begin_region)
|
||||
{
|
||||
while (GL.GetError() != ErrorCode.NoError)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve all OpenGL errors and throw an exception if anything other than NoError is returned.
|
||||
[Conditional("DEBUG")]
|
||||
internal void CheckErrors()
|
||||
{
|
||||
if (!inside_begin_region)
|
||||
{
|
||||
error_list.Clear();
|
||||
ErrorCode error;
|
||||
do
|
||||
{
|
||||
error = GL.GetError();
|
||||
error_list.Add(error);
|
||||
} while (error != ErrorCode.NoError);
|
||||
|
||||
if (error_list.Count != 1)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (ErrorCode e in error_list)
|
||||
{
|
||||
sb.Append(e.ToString());
|
||||
sb.Append(", ");
|
||||
}
|
||||
sb.Remove(sb.Length - 2, 2);
|
||||
|
||||
Debug.Assert(error_list.Count == 1, "OpenTK detected an OpenGL error.",
|
||||
String.Format("The following errors where reported: \"{0}\"", sb.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public static void Assert()
|
||||
#region --- Private Members ---
|
||||
|
||||
#region void ContextDestroyed(IGraphicsContext context, EventArgs e)
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a GraphicsContext exists in the calling thread and throws a GraphicsContextException if it doesn't.
|
||||
/// Handles the Destroy event.
|
||||
/// </summary>
|
||||
public static void Assert()
|
||||
/// <param name="context">The OpenTK.Platform.IGraphicsContext that was destroyed.</param>
|
||||
/// <param name="e">Not used.</param>
|
||||
void ContextDestroyed(IGraphicsContext context, EventArgs e)
|
||||
{
|
||||
if (GraphicsContext.CurrentContext == null)
|
||||
throw new GraphicsContextMissingException();
|
||||
this.Destroy -= ContextDestroyed;
|
||||
//available_contexts.Remove(((IGraphicsContextInternal)this).Context);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -344,60 +396,38 @@ namespace OpenTK.Graphics
|
|||
|
||||
#region --- IGraphicsContextInternal Members ---
|
||||
|
||||
#region Implementation
|
||||
|
||||
/// <summary>
|
||||
/// Gets the platform-specific implementation of this IGraphicsContext.
|
||||
/// </summary>
|
||||
IGraphicsContext IGraphicsContextInternal.Implementation
|
||||
{
|
||||
get { return implementation; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region void LoadAll()
|
||||
|
||||
/// <summary>
|
||||
/// Loads all OpenGL extensions.
|
||||
/// </summary>
|
||||
void IGraphicsContextInternal.LoadAll()
|
||||
{
|
||||
(implementation as IGraphicsContextInternal).LoadAll();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <internal />
|
||||
/// <summary>Gets a handle to the OpenGL rendering context.</summary>
|
||||
/// <summary>
|
||||
/// Gets a handle to the OpenGL rendering context.
|
||||
/// </summary>
|
||||
ContextHandle IGraphicsContextInternal.Context
|
||||
{
|
||||
get { return ((IGraphicsContextInternal)implementation).Context; }
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Gets the IWindowInfo describing the window associated with this context.
|
||||
/// </summary>
|
||||
IWindowInfo IGraphicsContextInternal.Info
|
||||
{
|
||||
get { return (implementation as IGraphicsContextInternal).Info; }
|
||||
//internal set { (implementation as IGLContextInternal).Info = value; }
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GraphicsMode of the context.
|
||||
/// </summary>
|
||||
public GraphicsMode GraphicsMode
|
||||
{
|
||||
get { return implementation.GraphicsMode; }
|
||||
get { return (implementation as IGraphicsContextInternal).GraphicsMode; }
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Gets a System.IntPtr containing the handle to the OpenGL context which is current in the
|
||||
///// calling thread, or IntPtr.Zero if no OpenGL context is current.
|
||||
///// </summary>
|
||||
///// <returns>A System.IntPtr that holds the handle to the current OpenGL context.</returns>
|
||||
//ContextHandle IGLContextInternal.GetCurrentContext()
|
||||
//{
|
||||
// return (implementation as IGLContextInternal).GetCurrentContext();
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Registers an OpenGL resource for disposal.
|
||||
/// </summary>
|
||||
|
|
Loading…
Reference in a new issue