2007-08-01 23:14:39 +02:00
|
|
|
#region --- License ---
|
|
|
|
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
|
|
|
|
* See license.txt for license info
|
|
|
|
*/
|
2007-08-01 11:27:57 +02:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Text;
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using System.Diagnostics;
|
2007-08-01 23:14:39 +02:00
|
|
|
using System.IO;
|
2007-08-01 11:27:57 +02:00
|
|
|
|
|
|
|
namespace Bind.Structures
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// Represents an opengl function.
|
|
|
|
/// The return value, function name, function parameters and opengl version can be retrieved or set.
|
|
|
|
/// </summary>
|
|
|
|
public class Delegate
|
|
|
|
{
|
2007-08-01 23:14:39 +02:00
|
|
|
internal static DelegateCollection Delegates;
|
|
|
|
|
|
|
|
private static bool delegatesLoaded;
|
2007-08-10 22:16:05 +02:00
|
|
|
|
|
|
|
#region internal static void Initialize(string glSpec, string glSpecExt)
|
|
|
|
|
2007-08-05 01:39:56 +02:00
|
|
|
internal static void Initialize(string glSpec, string glSpecExt)
|
2007-08-01 23:14:39 +02:00
|
|
|
{
|
|
|
|
if (!delegatesLoaded)
|
|
|
|
{
|
2007-08-05 01:39:56 +02:00
|
|
|
using (StreamReader sr = Utilities.OpenSpecFile(Settings.InputPath, glSpec))
|
2007-08-01 23:14:39 +02:00
|
|
|
{
|
|
|
|
Delegates = Bind.MainClass.Generator.ReadDelegates(sr);
|
|
|
|
}
|
|
|
|
|
2007-08-05 01:39:56 +02:00
|
|
|
if (!String.IsNullOrEmpty(glSpecExt))
|
|
|
|
{
|
|
|
|
using (StreamReader sr = Utilities.OpenSpecFile(Settings.InputPath, glSpecExt))
|
|
|
|
{
|
|
|
|
foreach (Delegate d in Bind.MainClass.Generator.ReadDelegates(sr).Values)
|
|
|
|
{
|
|
|
|
Utilities.Merge(Delegates, d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-08-01 23:14:39 +02:00
|
|
|
delegatesLoaded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-10 22:16:05 +02:00
|
|
|
#endregion
|
|
|
|
|
2007-08-01 11:27:57 +02:00
|
|
|
#region --- Constructors ---
|
|
|
|
|
|
|
|
public Delegate()
|
|
|
|
{
|
|
|
|
Parameters = new ParameterCollection();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Delegate(Delegate d)
|
|
|
|
{
|
2007-08-05 01:39:56 +02:00
|
|
|
this.Category = !String.IsNullOrEmpty(d.Category) ? new string(d.Category.ToCharArray()) : "";
|
2007-08-01 11:27:57 +02:00
|
|
|
//this.Extension = !String.IsNullOrEmpty(d.Extension) ? new string(d.Extension.ToCharArray()) : "";
|
|
|
|
this.Name = new string(d.Name.ToCharArray());
|
2007-08-01 23:14:39 +02:00
|
|
|
//this.NeedsWrapper = d.NeedsWrapper;
|
2007-08-01 11:27:57 +02:00
|
|
|
this.Parameters = new ParameterCollection(d.Parameters);
|
2007-08-01 23:14:39 +02:00
|
|
|
this.ReturnType = new Type(d.ReturnType);
|
2007-08-01 11:27:57 +02:00
|
|
|
this.Version = !String.IsNullOrEmpty(d.Version) ? new string(d.Version.ToCharArray()) : "";
|
|
|
|
//this.Unsafe = d.Unsafe;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region --- Properties ---
|
|
|
|
|
|
|
|
#region public bool CLSCompliant
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the CLSCompliant property. True if the delegate is not CLSCompliant.
|
|
|
|
/// </summary>
|
|
|
|
public bool CLSCompliant
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (Unsafe)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!ReturnType.CLSCompliant)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
foreach (Parameter p in Parameters)
|
|
|
|
{
|
|
|
|
if (!p.CLSCompliant)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public string Category
|
|
|
|
|
|
|
|
private string _category;
|
|
|
|
|
|
|
|
public string Category
|
|
|
|
{
|
|
|
|
get { return _category; }
|
|
|
|
set { _category = value; }
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public bool NeedsWrapper
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Indicates whether this function needs to be wrapped with a Marshaling function.
|
|
|
|
/// This flag is set if a function contains an Array parameter, or returns
|
|
|
|
/// an Array or string.
|
|
|
|
/// </summary>
|
|
|
|
public bool NeedsWrapper
|
|
|
|
{
|
2007-08-01 23:14:39 +02:00
|
|
|
//get { return _needs_wrapper; }
|
|
|
|
//set { _needs_wrapper = value; }
|
|
|
|
|
|
|
|
get
|
|
|
|
{
|
|
|
|
// TODO: Add special cases for (Get)ShaderSource.
|
|
|
|
|
|
|
|
if (ReturnType.WrapperType != WrapperTypes.None)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
foreach (Parameter p in Parameters)
|
|
|
|
{
|
|
|
|
if (p.WrapperType != WrapperTypes.None)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public virtual bool Unsafe
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// True if the delegate must be declared as 'unsafe'.
|
|
|
|
/// </summary>
|
|
|
|
public virtual bool Unsafe
|
|
|
|
{
|
|
|
|
//get { return @unsafe; }
|
|
|
|
//set { @unsafe = value; }
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (ReturnType.Pointer)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
foreach (Parameter p in Parameters)
|
|
|
|
{
|
|
|
|
if (p.Pointer)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public Parameter ReturnType
|
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
Type _return_type = new Type();
|
2007-08-01 11:27:57 +02:00
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the return value of the opengl function.
|
|
|
|
/// </summary>
|
2007-08-01 23:14:39 +02:00
|
|
|
public Type ReturnType
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
|
|
|
get { return _return_type; }
|
|
|
|
set
|
|
|
|
{
|
2007-08-01 23:14:39 +02:00
|
|
|
_return_type = Type.Translate(value);
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
#region public virtual string Name
|
2007-08-01 11:27:57 +02:00
|
|
|
|
|
|
|
string _name;
|
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the name of the opengl function.
|
|
|
|
/// </summary>
|
2007-08-01 23:14:39 +02:00
|
|
|
public virtual string Name
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
|
|
|
get { return _name; }
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (!String.IsNullOrEmpty(value))
|
2007-08-20 12:46:37 +02:00
|
|
|
{
|
2007-08-01 11:27:57 +02:00
|
|
|
_name = value.Trim();
|
2007-08-20 12:46:37 +02:00
|
|
|
}
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public ParameterCollection Parameters
|
|
|
|
|
|
|
|
ParameterCollection _parameters;
|
|
|
|
|
|
|
|
public ParameterCollection Parameters
|
|
|
|
{
|
|
|
|
get { return _parameters; }
|
2007-08-01 23:14:39 +02:00
|
|
|
protected set { _parameters = value; }
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public string Version
|
|
|
|
|
|
|
|
string _version;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Defines the opengl version that introduced this function.
|
|
|
|
/// </summary>
|
|
|
|
public string Version
|
|
|
|
{
|
|
|
|
get { return _version; }
|
|
|
|
set { _version = value; }
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public bool Extension
|
|
|
|
|
|
|
|
string _extension;
|
|
|
|
|
|
|
|
public string Extension
|
|
|
|
{
|
|
|
|
//get { return _extension; }
|
|
|
|
//set { _extension = value; }
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (!String.IsNullOrEmpty(Name))
|
|
|
|
{
|
|
|
|
_extension = Utilities.GetGL2Extension(Name);
|
|
|
|
return String.IsNullOrEmpty(_extension) ? "Core" : _extension;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region --- Strings ---
|
|
|
|
|
|
|
|
#region public string CallString()
|
|
|
|
|
|
|
|
public string CallString()
|
|
|
|
{
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
sb.Append(Settings.DelegatesClass);
|
2007-08-20 12:46:37 +02:00
|
|
|
sb.Append(".");
|
2007-08-20 14:25:48 +02:00
|
|
|
sb.Append(Settings.FunctionPrefix);
|
2007-08-01 11:27:57 +02:00
|
|
|
sb.Append(Name);
|
2007-08-20 14:25:48 +02:00
|
|
|
sb.Append(Parameters.CallString(Settings.Compatibility == Settings.Legacy.Tao));
|
2007-08-01 11:27:57 +02:00
|
|
|
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public string DeclarationString()
|
|
|
|
|
|
|
|
public string DeclarationString()
|
|
|
|
{
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
sb.Append(Unsafe ? "unsafe " : "");
|
|
|
|
sb.Append(ReturnType);
|
|
|
|
sb.Append(" ");
|
|
|
|
sb.Append(Name);
|
|
|
|
sb.Append(Parameters.ToString());
|
|
|
|
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region override public string ToString()
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the string representing the full function declaration without decorations
|
|
|
|
/// (ie "void glClearColor(float red, float green, float blue, float alpha)"
|
|
|
|
/// </summary>
|
|
|
|
override public string ToString()
|
|
|
|
{
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
sb.Append(Unsafe ? "unsafe " : "");
|
|
|
|
sb.Append("delegate ");
|
|
|
|
sb.Append(ReturnType);
|
|
|
|
sb.Append(" ");
|
|
|
|
sb.Append(Name);
|
|
|
|
sb.Append(Parameters.ToString());
|
|
|
|
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
public Delegate GetCLSCompliantDelegate()
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
|
|
|
Delegate f = new Delegate(this);
|
|
|
|
|
|
|
|
for (int i = 0; i < f.Parameters.Count; i++)
|
|
|
|
{
|
2007-08-01 23:14:39 +02:00
|
|
|
f.Parameters[i].CurrentType = f.Parameters[i].GetCLSCompliantType();
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
f.ReturnType.CurrentType = f.ReturnType.GetCLSCompliantType();
|
2007-08-01 11:27:57 +02:00
|
|
|
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region --- Wrapper Creation ---
|
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
#region public IEnumerable<Function> CreateWrappers()
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
public void CreateWrappers()
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
if (this.Name.Contains("GenBuffers"))
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
List<Function> wrappers = new List<Function>();
|
|
|
|
if (!NeedsWrapper)
|
|
|
|
{
|
|
|
|
// No special wrapper needed - just call this delegate:
|
|
|
|
Function f = new Function(this);
|
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
if (f.ReturnType.CurrentType.ToLower().Contains("void"))
|
2007-08-01 11:27:57 +02:00
|
|
|
f.Body.Add(String.Format("{0};", f.CallString()));
|
|
|
|
else
|
|
|
|
f.Body.Add(String.Format("return {0};", f.CallString()));
|
|
|
|
|
|
|
|
wrappers.Add(f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-08-01 23:14:39 +02:00
|
|
|
Function f = WrapReturnType();
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
WrapParameters(new Function((Function)f ?? this), wrappers);
|
|
|
|
}
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
// If the function is not CLS-compliant (e.g. it contains unsigned parameters)
|
|
|
|
// we need to create a CLS-Compliant overload. However, we should only do this
|
|
|
|
// iff the opengl function does not contain unsigned/signed overloads itself
|
|
|
|
// to avoid redefinitions.
|
|
|
|
foreach (Function f in wrappers)
|
|
|
|
{
|
|
|
|
Bind.Structures.Function.Wrappers.AddChecked(f);
|
|
|
|
//Bind.Structures.Function.Wrappers.Add(f);
|
|
|
|
|
|
|
|
if (!f.CLSCompliant)
|
|
|
|
{
|
|
|
|
Function cls = new Function(f);
|
|
|
|
|
|
|
|
cls.Body.Clear();
|
|
|
|
if (!cls.NeedsWrapper)
|
|
|
|
{
|
|
|
|
cls.Body.Add((f.ReturnType.CurrentType != "void" ? "return " + this.CallString() : this.CallString()) + ";");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cls.Body.AddRange(this.CreateBody(cls, true));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool somethingChanged = false;
|
|
|
|
for (int i = 0; i < f.Parameters.Count; i++)
|
|
|
|
{
|
|
|
|
cls.Parameters[i].CurrentType = cls.Parameters[i].GetCLSCompliantType();
|
|
|
|
if (cls.Parameters[i].CurrentType != f.Parameters[i].CurrentType)
|
|
|
|
somethingChanged = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (somethingChanged)
|
|
|
|
Bind.Structures.Function.Wrappers.AddChecked(cls);
|
|
|
|
}
|
|
|
|
}
|
2007-08-01 23:14:39 +02:00
|
|
|
}
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
#endregion
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
#region protected Function WrapReturnType()
|
|
|
|
|
|
|
|
protected Function WrapReturnType()
|
|
|
|
{
|
|
|
|
// We have to add wrappers for all possible WrapperTypes.
|
|
|
|
Function f;
|
|
|
|
|
|
|
|
// First, check if the return type needs wrapping:
|
|
|
|
switch (this.ReturnType.WrapperType)
|
|
|
|
{
|
|
|
|
// If the function returns a string (glGetString) we must manually marshal it
|
|
|
|
// using Marshal.PtrToStringXXX. Otherwise, the GC will try to free the memory
|
|
|
|
// used by the string, resulting in corruption (the memory belongs to the
|
|
|
|
// unmanaged boundary).
|
|
|
|
case WrapperTypes.StringReturnType:
|
|
|
|
f = new Function(this);
|
|
|
|
f.ReturnType.CurrentType = "System.String";
|
|
|
|
|
|
|
|
f.Body.Add(
|
|
|
|
String.Format(
|
|
|
|
"return System.Runtime.InteropServices.Marshal.PtrToStringAnsi({0});",
|
|
|
|
this.CallString()
|
|
|
|
)
|
|
|
|
);
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
return f; // Only occurs in glGetString, there's no need to check parameters.
|
|
|
|
|
|
|
|
// If the function returns a void* (GenericReturnValue), we'll have to return an IntPtr.
|
|
|
|
// The user will unfortunately need to marshal this IntPtr to a data type manually.
|
|
|
|
case WrapperTypes.GenericReturnType:
|
|
|
|
ReturnType.CurrentType = "IntPtr";
|
|
|
|
ReturnType.Pointer = false;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WrapperTypes.None:
|
|
|
|
default:
|
|
|
|
// No return wrapper needed
|
|
|
|
break;
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
return null;
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
2007-08-01 23:14:39 +02:00
|
|
|
|
2007-08-01 11:27:57 +02:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region protected void WrapParameters(Function function, List<Function> wrappers)
|
|
|
|
|
|
|
|
protected static int index = 0;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// This function needs some heavy refactoring. I'm ashamed I ever wrote it, but it works...
|
|
|
|
/// What it does is this: it adds to the wrapper list all possible wrapper permutations
|
|
|
|
/// for functions that have more than one IntPtr parameter. Example:
|
|
|
|
/// "void Delegates.f(IntPtr p, IntPtr q)" where p and q are pointers to void arrays needs the following wrappers:
|
|
|
|
/// "void f(IntPtr p, IntPtr q)"
|
|
|
|
/// "void f(IntPtr p, object q)"
|
|
|
|
/// "void f(object p, IntPtr q)"
|
|
|
|
/// "void f(object p, object q)"
|
|
|
|
/// </summary>
|
2007-08-01 23:14:39 +02:00
|
|
|
protected void WrapParameters(Function function, List<Function> wrappers)
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
|
|
|
if (index == 0)
|
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
bool containsPointerParameters = false, containsReferenceParameters = false;
|
2007-08-01 11:27:57 +02:00
|
|
|
// Check if there are any IntPtr parameters (we may have come here from a ReturnType wrapper
|
|
|
|
// such as glGetString, which contains no IntPtr parameters)
|
|
|
|
foreach (Parameter p in function.Parameters)
|
|
|
|
{
|
|
|
|
if (p.Pointer)
|
|
|
|
{
|
|
|
|
containsPointerParameters = true;
|
|
|
|
break;
|
|
|
|
}
|
2007-08-20 14:25:48 +02:00
|
|
|
else if (p.Reference)
|
|
|
|
{
|
|
|
|
containsReferenceParameters = true;
|
|
|
|
break;
|
|
|
|
}
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (containsPointerParameters)
|
|
|
|
{
|
|
|
|
wrappers.Add(DefaultWrapper(function));
|
|
|
|
}
|
2007-08-20 14:25:48 +02:00
|
|
|
else if (containsReferenceParameters)
|
|
|
|
{
|
|
|
|
}
|
2007-08-01 11:27:57 +02:00
|
|
|
else
|
|
|
|
{
|
2007-08-01 23:14:39 +02:00
|
|
|
if (function.Body.Count == 0)
|
|
|
|
wrappers.Add(DefaultWrapper(function));
|
|
|
|
else
|
|
|
|
wrappers.Add(function);
|
2007-08-01 11:27:57 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index >= 0 && index < function.Parameters.Count)
|
|
|
|
{
|
|
|
|
Function f;
|
|
|
|
|
|
|
|
if (function.Parameters[index].WrapperType == WrapperTypes.None)
|
|
|
|
{
|
|
|
|
// No wrapper needed, visit the next parameter
|
|
|
|
++index;
|
2007-08-01 23:14:39 +02:00
|
|
|
WrapParameters(function, wrappers);
|
2007-08-01 11:27:57 +02:00
|
|
|
--index;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (function.Parameters[index].WrapperType)
|
|
|
|
{
|
|
|
|
case WrapperTypes.ArrayParameter:
|
|
|
|
// Recurse to the last parameter
|
|
|
|
++index;
|
2007-08-01 23:14:39 +02:00
|
|
|
WrapParameters(function, wrappers);
|
2007-08-01 11:27:57 +02:00
|
|
|
--index;
|
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
if (function.Name == "UseFontOutlinesA")
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2007-08-01 11:27:57 +02:00
|
|
|
// On stack rewind, create array wrappers
|
2007-08-20 14:25:48 +02:00
|
|
|
f = new Function(function);
|
|
|
|
f.Parameters[index].Reference = false;
|
|
|
|
f.Parameters[index].Array = 1;
|
|
|
|
f.Parameters[index].Pointer = false;
|
|
|
|
f.Body = CreateBody(f, false);
|
|
|
|
//f = ReferenceWrapper(new Function(function), index);
|
2007-08-01 11:27:57 +02:00
|
|
|
wrappers.Add(f);
|
|
|
|
|
|
|
|
// Recurse to the last parameter again, keeping the Array wrappers
|
|
|
|
++index;
|
2007-08-01 23:14:39 +02:00
|
|
|
WrapParameters(f, wrappers);
|
2007-08-01 11:27:57 +02:00
|
|
|
--index;
|
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
f = new Function(function);
|
|
|
|
f.Parameters[index].Reference = true;
|
|
|
|
f.Parameters[index].Array = 0;
|
|
|
|
f.Parameters[index].Pointer = false;
|
|
|
|
f.Body = CreateBody(f, false);
|
|
|
|
//f = ReferenceWrapper(new Function(function), index);
|
2007-08-01 11:27:57 +02:00
|
|
|
wrappers.Add(f);
|
|
|
|
|
|
|
|
// Keeping the current Ref wrapper, visit all other parameters once more
|
|
|
|
++index;
|
2007-08-01 23:14:39 +02:00
|
|
|
WrapParameters(f, wrappers);
|
2007-08-01 11:27:57 +02:00
|
|
|
--index;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WrapperTypes.GenericParameter:
|
|
|
|
// Recurse to the last parameter
|
|
|
|
++index;
|
2007-08-01 23:14:39 +02:00
|
|
|
WrapParameters(function, wrappers);
|
2007-08-01 11:27:57 +02:00
|
|
|
--index;
|
|
|
|
|
|
|
|
// On stack rewind, create array wrappers
|
2007-08-20 14:25:48 +02:00
|
|
|
f = new Function(function);
|
|
|
|
f.Parameters[index].Reference = false;
|
|
|
|
f.Parameters[index].Array = 0;
|
|
|
|
f.Parameters[index].Pointer = false;
|
|
|
|
f.Parameters[index].CurrentType = "object";
|
|
|
|
f.Parameters[index].Flow = Parameter.FlowDirection.Undefined;
|
|
|
|
|
|
|
|
f.Body = CreateBody(f, false);
|
2007-08-01 11:27:57 +02:00
|
|
|
wrappers.Add(f);
|
|
|
|
|
|
|
|
// Keeping the current Object wrapper, visit all other parameters once more
|
|
|
|
++index;
|
2007-08-01 23:14:39 +02:00
|
|
|
WrapParameters(f, wrappers);
|
2007-08-01 11:27:57 +02:00
|
|
|
--index;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
case WrapperTypes.ReferenceParameter:
|
|
|
|
// Recurse to the last parameter
|
|
|
|
++index;
|
|
|
|
WrapParameters(function, wrappers);
|
|
|
|
--index;
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
// On stack rewind, create reference wrappers
|
|
|
|
f = new Function(function);
|
|
|
|
f.Parameters[index].Reference = true;
|
|
|
|
f.Parameters[index].Array = 0;
|
|
|
|
f.Parameters[index].Pointer = false;
|
|
|
|
f.Body = CreateBody(f, false);
|
|
|
|
//f = ReferenceWrapper(new Function(function), index);
|
|
|
|
wrappers.Add(f);
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
// Keeping the current Object wrapper, visit all other parameters once more
|
|
|
|
++index;
|
|
|
|
WrapParameters(f, wrappers);
|
|
|
|
--index;
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region protected Function DefaultWrapper(Function f)
|
|
|
|
|
|
|
|
protected Function DefaultWrapper(Function f)
|
|
|
|
{
|
2007-08-01 23:14:39 +02:00
|
|
|
bool returns = f.ReturnType.CurrentType.ToLower().Contains("void") && !f.ReturnType.Pointer;
|
2007-08-01 11:27:57 +02:00
|
|
|
string callString = String.Format(
|
|
|
|
"{0} {1}{2}; {3}",
|
|
|
|
Unsafe ? "unsafe {" : "",
|
|
|
|
returns ? "" : "return ",
|
2007-08-01 23:14:39 +02:00
|
|
|
this.CallString(),
|
2007-08-01 11:27:57 +02:00
|
|
|
Unsafe ? "}" : "");
|
|
|
|
|
|
|
|
f.Body.Add(callString);
|
|
|
|
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
#region protected FunctionBody CreateBody(Function fun, bool wantCLSCompliance)
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
static List<string> handle_statements = new List<string>();
|
|
|
|
static List<string> fixed_statements = new List<string>();
|
|
|
|
static List<string> assign_statements = new List<string>();
|
|
|
|
static string function_call_statement;
|
|
|
|
|
|
|
|
protected FunctionBody CreateBody(Function fun, bool wantCLSCompliance)
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
Function f = new Function(fun);
|
|
|
|
|
2007-08-01 11:27:57 +02:00
|
|
|
f.Body.Clear();
|
2007-08-20 14:25:48 +02:00
|
|
|
handle_statements.Clear();
|
|
|
|
fixed_statements.Clear();
|
|
|
|
assign_statements.Clear();
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
if (f.Name == "LoadDisplayColorTableEXT")
|
|
|
|
{
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Obtain pointers by pinning the parameters
|
2007-08-20 14:25:48 +02:00
|
|
|
int param = 0;
|
2007-08-01 11:27:57 +02:00
|
|
|
foreach (Parameter p in f.Parameters)
|
|
|
|
{
|
|
|
|
if (p.NeedsPin)
|
|
|
|
{
|
|
|
|
// Use GCHandle to obtain pointer to generic parameters and 'fixed' for arrays.
|
|
|
|
// This is because fixed can only take the address of fields, not managed objects.
|
|
|
|
if (p.WrapperType == WrapperTypes.GenericParameter)
|
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
handle_statements.Add(String.Format(
|
|
|
|
"{0} {1} = {0}.Alloc({2}, System.Runtime.InteropServices.GCHandleType.Pinned);",
|
|
|
|
"System.Runtime.InteropServices.GCHandle", p.Name + "_ptr", p.Name));
|
|
|
|
|
|
|
|
if (p.Flow == Parameter.FlowDirection.Out)
|
|
|
|
{
|
|
|
|
assign_statements.Add(String.Format(
|
|
|
|
" {0} = ({1}){2}.Target;",
|
|
|
|
p.Name, p.CurrentType, p.Name + "_ptr"));
|
|
|
|
}
|
|
|
|
|
2007-08-01 11:27:57 +02:00
|
|
|
// Note! The following line modifies f.Parameters, *not* function.Parameters
|
|
|
|
p.Name = "(void*)" + p.Name + "_ptr.AddrOfPinnedObject()";
|
2007-08-20 14:25:48 +02:00
|
|
|
}
|
|
|
|
else if (p.WrapperType == WrapperTypes.PointerParameter ||
|
|
|
|
p.WrapperType == WrapperTypes.ArrayParameter ||
|
|
|
|
p.WrapperType == WrapperTypes.ReferenceParameter)
|
|
|
|
{
|
|
|
|
fixed_statements.Add(String.Format(
|
|
|
|
"fixed ({0}* {1} = {2})",
|
|
|
|
wantCLSCompliance && !p.CLSCompliant ? p.GetCLSCompliantType() : p.CurrentType,
|
|
|
|
p.Name + "_ptr",
|
|
|
|
p.Array > 0 ? p.Name : "&" + p.Name));
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
if (p.Flow == Parameter.FlowDirection.Out && p.Array == 0) // Fixed Arrays of blittable types don't need explicit assignment.
|
|
|
|
{
|
|
|
|
assign_statements.Add(String.Format(" {0} = *{0}_ptr;", p.Name));
|
|
|
|
}
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
p.Name = p.Name + "_ptr";
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
throw new ApplicationException("Unknown parameter type");
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
//if (!f.Unsafe && (fixed_statements.Count > 0 || fixed_statements.Count > 0))
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
f.Body.Add("unsafe");
|
|
|
|
f.Body.Add("{");
|
|
|
|
f.Body.Indent();
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
if (fixed_statements.Count > 0)
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
f.Body.AddRange(fixed_statements);
|
|
|
|
f.Body.Add("{");
|
|
|
|
f.Body.Indent();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handle_statements.Count > 0)
|
|
|
|
{
|
|
|
|
f.Body.AddRange(handle_statements);
|
|
|
|
f.Body.Add("try");
|
|
|
|
f.Body.Add("{");
|
|
|
|
f.Body.Indent();
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
if (f.ReturnType.CurrentType.ToLower().Contains("void"))
|
2007-08-20 14:25:48 +02:00
|
|
|
{
|
|
|
|
f.Body.Add(String.Format("{0};", f.CallString()));
|
|
|
|
}
|
2007-08-01 11:27:57 +02:00
|
|
|
else
|
2007-08-20 14:25:48 +02:00
|
|
|
{
|
|
|
|
f.Body.Add(String.Format("{0} {1} = {2};", f.ReturnType.CurrentType, "retval", f.CallString()));
|
|
|
|
}
|
2007-08-01 11:27:57 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
if (assign_statements.Count > 0)
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
f.Body.AddRange(assign_statements);
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return:
|
2007-08-01 23:14:39 +02:00
|
|
|
if (!f.ReturnType.CurrentType.ToLower().Contains("void"))
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
f.Body.Add("return retval;");
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
if (handle_statements.Count > 0)
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
f.Body.Unindent();
|
|
|
|
f.Body.Add("}");
|
|
|
|
f.Body.Add("finally");
|
|
|
|
f.Body.Add("{");
|
|
|
|
f.Body.Indent();
|
|
|
|
// Free all allocated GCHandles
|
2007-08-01 23:14:39 +02:00
|
|
|
foreach (Parameter p in this.Parameters)
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
if (p.NeedsPin && p.WrapperType == WrapperTypes.GenericParameter)
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
f.Body.Add(String.Format(" {0}_ptr.Free();", p.Name));
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
}
|
2007-08-20 14:25:48 +02:00
|
|
|
f.Body.Unindent();
|
|
|
|
f.Body.Add("}");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fixed_statements.Count > 0)
|
|
|
|
{
|
|
|
|
f.Body.Unindent();
|
|
|
|
f.Body.Add("}");
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
//if (!f.Unsafe && (fixed_statements.Count > 0 || fixed_statements.Count > 0))
|
2007-08-01 11:27:57 +02:00
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
f.Body.Unindent();
|
2007-08-01 11:27:57 +02:00
|
|
|
f.Body.Add("}");
|
|
|
|
}
|
|
|
|
|
|
|
|
return f.Body;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#endregion
|
2007-08-01 23:14:39 +02:00
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
#region Translate
|
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
/// <summary>
|
|
|
|
/// Translates the opengl return type to the equivalent C# type.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="d">The opengl function to translate.</param>
|
|
|
|
/// <remarks>
|
|
|
|
/// First, we use the official typemap (gl.tm) to get the correct type.
|
|
|
|
/// Then we override this, when it is:
|
|
|
|
/// 1) A string (we have to use Marshal.PtrToStringAnsi, to avoid heap corruption)
|
|
|
|
/// 2) An array (translates to IntPtr)
|
|
|
|
/// 3) A generic object or void* (translates to IntPtr)
|
|
|
|
/// 4) A GLenum (translates to int on Legacy.Tao or GL.Enums.GLenum otherwise).
|
|
|
|
/// Return types must always be CLS-compliant, because .Net does not support overloading on return types.
|
|
|
|
/// </remarks>
|
|
|
|
protected virtual void TranslateReturnType()
|
|
|
|
{
|
|
|
|
if (Bind.Structures.Type.GLTypes.ContainsKey(ReturnType.CurrentType))
|
|
|
|
ReturnType.CurrentType = Bind.Structures.Type.GLTypes[ReturnType.CurrentType];
|
|
|
|
|
|
|
|
if (Bind.Structures.Type.CSTypes.ContainsKey(ReturnType.CurrentType))
|
|
|
|
ReturnType.CurrentType = Bind.Structures.Type.CSTypes[ReturnType.CurrentType];
|
|
|
|
|
|
|
|
if (ReturnType.CurrentType.ToLower().Contains("void") && ReturnType.Pointer)
|
|
|
|
{
|
|
|
|
ReturnType.WrapperType = WrapperTypes.GenericReturnType;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ReturnType.CurrentType.ToLower().Contains("string"))
|
|
|
|
{
|
|
|
|
ReturnType.CurrentType = "IntPtr";
|
|
|
|
ReturnType.WrapperType = WrapperTypes.StringReturnType;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ReturnType.CurrentType.ToLower().Contains("object"))
|
|
|
|
{
|
|
|
|
ReturnType.CurrentType = "IntPtr";
|
|
|
|
ReturnType.WrapperType |= WrapperTypes.GenericReturnType;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ReturnType.CurrentType.Contains("GLenum"))
|
|
|
|
{
|
|
|
|
if (Settings.Compatibility == Settings.Legacy.None)
|
2007-08-03 02:14:31 +02:00
|
|
|
ReturnType.CurrentType =
|
|
|
|
String.Format("{0}.{1}",
|
|
|
|
Settings.GLEnumsClass,
|
|
|
|
Settings.CompleteEnumName);
|
2007-08-01 23:14:39 +02:00
|
|
|
else
|
|
|
|
ReturnType.CurrentType = "int";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ReturnType.CurrentType.ToLower().Contains("bool"))
|
|
|
|
{
|
2007-08-20 14:25:48 +02:00
|
|
|
// TODO: Is the translation to 'int' needed 100%? It breaks WGL.
|
|
|
|
/*
|
2007-08-01 23:14:39 +02:00
|
|
|
if (Settings.Compatibility == Settings.Legacy.Tao)
|
2007-08-20 14:25:48 +02:00
|
|
|
{
|
2007-08-01 23:14:39 +02:00
|
|
|
ReturnType.CurrentType = "int";
|
2007-08-20 14:25:48 +02:00
|
|
|
}
|
2007-08-01 23:14:39 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
}
|
2007-08-20 14:25:48 +02:00
|
|
|
*/
|
2007-08-01 23:14:39 +02:00
|
|
|
|
|
|
|
//ReturnType.WrapperType = WrapperTypes.ReturnsBool;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnType.CurrentType = ReturnType.GetCLSCompliantType();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual void TranslateParameters()
|
|
|
|
{
|
2007-08-12 18:14:23 +02:00
|
|
|
if (this.Name.Contains("SetLayerPaletteEntries"))
|
2007-08-01 23:14:39 +02:00
|
|
|
{
|
2007-08-12 18:14:23 +02:00
|
|
|
// Console.WriteLine();
|
2007-08-01 23:14:39 +02:00
|
|
|
}
|
|
|
|
for (int i = 0; i < Parameters.Count; i++)
|
|
|
|
{
|
|
|
|
Parameters[i] = Parameter.Translate(Parameters[i], this.Category);
|
|
|
|
|
|
|
|
// Special cases: glLineStipple and gl(Get)ShaderSource:
|
|
|
|
// Check for LineStipple (should be unchecked)
|
|
|
|
if (Parameters[i].CurrentType == "UInt16" && Name.Contains("LineStipple"))
|
|
|
|
{
|
|
|
|
Parameters[i].WrapperType = WrapperTypes.UncheckedParameter;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Name.Contains("ShaderSource") && Parameters[i].CurrentType.ToLower().Contains("string"))
|
|
|
|
{
|
|
|
|
// Special case: these functions take a string[]
|
|
|
|
//IsPointer = true;
|
|
|
|
Parameters[i].Array = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void Translate()
|
|
|
|
{
|
|
|
|
TranslateReturnType();
|
|
|
|
TranslateParameters();
|
|
|
|
|
2007-08-20 14:25:48 +02:00
|
|
|
CreateWrappers();
|
2007-08-01 23:14:39 +02:00
|
|
|
}
|
2007-08-20 14:25:48 +02:00
|
|
|
|
|
|
|
#endregion
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|
|
|
|
|
2007-08-01 23:14:39 +02:00
|
|
|
#region class DelegateCollection : Dictionary<string, Delegate>
|
|
|
|
|
2007-08-01 11:27:57 +02:00
|
|
|
class DelegateCollection : Dictionary<string, Delegate>
|
|
|
|
{
|
|
|
|
public void Add(Delegate d)
|
|
|
|
{
|
|
|
|
if (!this.ContainsKey(d.Name))
|
|
|
|
{
|
|
|
|
this.Add(d.Name, d);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Trace.WriteLine(String.Format(
|
|
|
|
"Spec error: function {0} redefined, ignoring second definition.",
|
|
|
|
d.Name));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-08-01 23:14:39 +02:00
|
|
|
|
|
|
|
#endregion
|
2007-08-01 11:27:57 +02:00
|
|
|
}
|